• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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