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