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