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 premainnull29 fun premain(args: String?, instrumentation: Instrumentation) { 30 AgentInstallationType.isInstalledStatically = true 31 instrumentation.addTransformer(DebugProbesTransformer) 32 DebugProbesImpl.enableCreationStackTraces = enableCreationStackTraces 33 DebugProbesImpl.install() 34 installSignalHandler() 35 } 36 37 internal object DebugProbesTransformer : ClassFileTransformer { transformnull38 override fun transform( 39 loader: ClassLoader, 40 className: String, 41 classBeingRedefined: Class<*>?, 42 protectionDomain: ProtectionDomain, 43 classfileBuffer: ByteArray? 44 ): ByteArray? { 45 if (className != "kotlin/coroutines/jvm/internal/DebugProbesKt") { 46 return null 47 } 48 /* 49 * DebugProbesKt.bin contains `kotlin.coroutines.jvm.internal.DebugProbesKt` class 50 * with method bodies that delegate all calls directly to their counterparts in 51 * kotlinx.coroutines.debug.DebugProbesImpl. This is done to avoid classfile patching 52 * on the fly (-> get rid of ASM dependency). 53 * You can verify its content either by using javap on it or looking at out integration test module. 54 */ 55 AgentInstallationType.isInstalledStatically = true 56 return loader.getResourceAsStream("DebugProbesKt.bin").readBytes() 57 } 58 } 59 installSignalHandlernull60 private fun installSignalHandler() { 61 try { 62 Signal.handle(Signal("TRAP")) { // kill -5 63 if (DebugProbesImpl.isInstalled) { 64 // Case with 'isInstalled' changed between this check-and-act is not considered 65 // a real debug probes use-case, thus is not guarded against. 66 DebugProbesImpl.dumpCoroutines(System.out) 67 } else { 68 println("Cannot perform coroutines dump, debug probes are disabled") 69 } 70 } 71 } catch (t: Throwable) { 72 // Do nothing, signal cannot be installed, e.g. because we are on Windows 73 } 74 } 75 } 76