1 package kotlinx.coroutines.debug 2 3 import android.annotation.* 4 import kotlinx.coroutines.debug.internal.* 5 import org.codehaus.mojo.animal_sniffer.* 6 import sun.misc.* 7 import java.lang.instrument.* 8 import java.lang.instrument.ClassFileTransformer 9 import java.security.* 10 11 /* 12 * This class is loaded if and only if kotlinx-coroutines-core was used as -javaagent argument, 13 * but Android complains anyway (java.lang.instrument.*), so we suppress all lint checks here 14 */ 15 @Suppress("unused") 16 @SuppressLint("all") 17 @IgnoreJRERequirement // Never touched on Android 18 internal object AgentPremain { 19 <lambda>null20 private val enableCreationStackTraces = runCatching { 21 System.getProperty("kotlinx.coroutines.debug.enable.creation.stack.trace")?.toBoolean() 22 }.getOrNull() ?: DebugProbesImpl.enableCreationStackTraces 23 24 @JvmStatic 25 @Suppress("UNUSED_PARAMETER") premainnull26 fun premain(args: String?, instrumentation: Instrumentation) { 27 AgentInstallationType.isInstalledStatically = true 28 instrumentation.addTransformer(DebugProbesTransformer) 29 DebugProbesImpl.enableCreationStackTraces = enableCreationStackTraces 30 DebugProbesImpl.install() 31 installSignalHandler() 32 } 33 34 internal object DebugProbesTransformer : ClassFileTransformer { transformnull35 override fun transform( 36 loader: ClassLoader?, 37 className: String, 38 classBeingRedefined: Class<*>?, 39 protectionDomain: ProtectionDomain, 40 classfileBuffer: ByteArray? 41 ): ByteArray? { 42 if (loader == null || className != "kotlin/coroutines/jvm/internal/DebugProbesKt") { 43 return null 44 } 45 /* 46 * DebugProbesKt.bin contains `kotlin.coroutines.jvm.internal.DebugProbesKt` class 47 * with method bodies that delegate all calls directly to their counterparts in 48 * kotlinx.coroutines.debug.DebugProbesImpl. This is done to avoid classfile patching 49 * on the fly (-> get rid of ASM dependency). 50 * You can verify its content either by using javap on it or looking at out integration test module. 51 */ 52 AgentInstallationType.isInstalledStatically = true 53 return loader.getResourceAsStream("DebugProbesKt.bin").readBytes() 54 } 55 } 56 installSignalHandlernull57 private fun installSignalHandler() { 58 try { 59 Signal.handle(Signal("TRAP")) { // kill -5 60 if (DebugProbesImpl.isInstalled) { 61 // Case with 'isInstalled' changed between this check-and-act is not considered 62 // a real debug probes use-case, thus is not guarded against. 63 DebugProbesImpl.dumpCoroutines(System.out) 64 } else { 65 println("Cannot perform coroutines dump, debug probes are disabled") 66 } 67 } 68 } catch (t: Throwable) { 69 // Do nothing, signal cannot be installed, e.g. because we are on Windows 70 } 71 } 72 } 73