Take java 9 modules into account in coroutines debug metadata

reading
 #KT-28237
This commit is contained in:
Ilmir Usmanov
2018-11-20 23:05:50 +03:00
parent bdd1eef39a
commit 1336e8f3e3
6 changed files with 91 additions and 14 deletions
@@ -5,6 +5,8 @@
package kotlin.coroutines.jvm.internal
import java.lang.reflect.Method
@Target(AnnotationTarget.CLASS)
@SinceKotlin("1.3")
internal annotation class DebugMetadata(
@@ -41,7 +43,48 @@ internal fun BaseContinuationImpl.getStackTraceElementImpl(): StackTraceElement?
checkDebugMetadataVersion(COROUTINES_DEBUG_METADATA_VERSION, debugMetadata.version)
val label = getLabel()
val lineNumber = if (label < 0) -1 else debugMetadata.lineNumbers[label]
return StackTraceElement(debugMetadata.className, debugMetadata.methodName, debugMetadata.sourceFile, lineNumber)
val moduleName = ModuleNameRetriever.getModuleName(this)
val moduleAndClass = if (moduleName == null) debugMetadata.className else "$moduleName/${debugMetadata.className}"
return StackTraceElement(moduleAndClass, debugMetadata.methodName, debugMetadata.sourceFile, lineNumber)
}
private object ModuleNameRetriever {
private class Cache(
@JvmField
val getModuleMethod: Method?,
@JvmField
val getDescriptorMethod: Method?,
@JvmField
val nameMethod: Method?
)
private val notOnJava9 = Cache(null, null, null)
@JvmField
var cache: Cache? = null
fun getModuleName(continuation: BaseContinuationImpl): String? {
val cache = this.cache ?: buildCache(continuation)
if (cache === notOnJava9) {
return null
}
val module = cache.getModuleMethod?.invoke(continuation.javaClass) ?: return null
val descriptor = cache.getDescriptorMethod?.invoke(module) ?: return null
return cache.nameMethod?.invoke(descriptor) as? String
}
private fun buildCache(continuation: BaseContinuationImpl): Cache {
try {
val getModuleMethod = Class::class.java.getDeclaredMethod("getModule")
val methodClass = continuation.javaClass.classLoader.loadClass("java.lang.Module")
val getDescriptorMethod = methodClass.getDeclaredMethod("getDescriptor")
val moduleDescriptorClass = continuation.javaClass.classLoader.loadClass("java.lang.module.ModuleDescriptor")
val nameMethod = moduleDescriptorClass.getDeclaredMethod("name")
return Cache(getModuleMethod, getDescriptorMethod, nameMethod).also { cache = it }
} catch (ignored: Exception) {
return notOnJava9.also { cache = it }
}
}
}
private fun BaseContinuationImpl.getDebugMetadataAnnotation(): DebugMetadata? =