From c80b8d1cfb92acf01986b7781bf93feb25110bab Mon Sep 17 00:00:00 2001 From: berest Date: Mon, 6 Feb 2023 02:59:15 +0400 Subject: [PATCH 1/2] #21 spring boot resource loading fix --- build.gradle.kts | 5 ++-- settings.gradle.kts | 7 ++--- .../main/kotlin/registry-jvm-agent-common.kt | 5 ++-- .../src/main/kotlin/utils-jvm-agent-common.kt | 11 ++++--- .../src/main/kotlin/utils-jvm-common.kt | 30 +++++++++++++++---- stdlib/src/main/kotlin/stdlib.kt | 2 ++ 6 files changed, 38 insertions(+), 22 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 3de56e7..3265eac 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,10 +7,9 @@ buildscript { } } dependencies { - classpath("com.android.tools.build:gradle:7.0.3") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0") + classpath("com.android.tools.build:gradle:7.0.4") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.22") classpath("gradle.plugin.com.github.johnrengelman:shadow:7.1.2") - classpath("net.vrallev.gradle:jarjar-gradle:1.1.0") } } diff --git a/settings.gradle.kts b/settings.gradle.kts index 687e7c7..1fa7aae 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,18 +1,15 @@ rootProject.name = "stacktrace-decoroutinator" include( "stacktrace-decoroutinator-common", - "stacktrace-decoroutinator-jvm-common", "stacktrace-decoroutinator-jvm-agent-common", "stacktrace-decoroutinator-jvm-legacy-common", "stacktrace-decoroutinator-jvm", "stacktrace-decoroutinator-jvm-agent", "stacktrace-decoroutinator-jvm-legacy", - "stacktrace-decoroutinator-android", - "stacktrace-decoroutinator-noop", - - "jvm-agent-tests", "stdlib", + + "jvm-agent-tests" ) diff --git a/stacktrace-decoroutinator-jvm-agent-common/src/main/kotlin/registry-jvm-agent-common.kt b/stacktrace-decoroutinator-jvm-agent-common/src/main/kotlin/registry-jvm-agent-common.kt index 39ec813..04e1d7c 100644 --- a/stacktrace-decoroutinator-jvm-agent-common/src/main/kotlin/registry-jvm-agent-common.kt +++ b/stacktrace-decoroutinator-jvm-agent-common/src/main/kotlin/registry-jvm-agent-common.kt @@ -1,20 +1,19 @@ package dev.reformator.stacktracedecoroutinator.jvmagentcommon import dev.reformator.stacktracedecoroutinator.common.getFileClass +import dev.reformator.stacktracedecoroutinator.jvmcommon.loadResource import org.objectweb.asm.ClassReader import org.objectweb.asm.Opcodes import org.objectweb.asm.Type import org.objectweb.asm.tree.ClassNode import java.lang.invoke.MethodHandles -import java.nio.file.FileSystems import java.util.concurrent.ConcurrentHashMap enum class DecoroutinatorJvmAgentDebugMetadataInfoResolveStrategy: DecoroutinatorDebugMetadataInfoResolver { SYSTEM_RESOURCE { override fun getDebugMetadataInfo(className: String): DebugMetadataInfo? { val path = className.replace('.', '/') + ".class" - return ClassLoader.getSystemResourceAsStream(path)?.use { classBodyStream -> - val classBody = classBodyStream.readBytes() + return loadResource(path)?.let { classBody -> val classReader = ClassReader(classBody) val classNode = ClassNode(Opcodes.ASM9) classReader.accept(classNode, ClassReader.SKIP_CODE) diff --git a/stacktrace-decoroutinator-jvm-agent-common/src/main/kotlin/utils-jvm-agent-common.kt b/stacktrace-decoroutinator-jvm-agent-common/src/main/kotlin/utils-jvm-agent-common.kt index aaca93e..6cf1e8d 100644 --- a/stacktrace-decoroutinator-jvm-agent-common/src/main/kotlin/utils-jvm-agent-common.kt +++ b/stacktrace-decoroutinator-jvm-agent-common/src/main/kotlin/utils-jvm-agent-common.kt @@ -1,13 +1,14 @@ package dev.reformator.stacktracedecoroutinator.jvmagentcommon import dev.reformator.stacktracedecoroutinator.common.BASE_CONTINUATION_CLASS_NAME +import dev.reformator.stacktracedecoroutinator.jvmcommon.loadResource import org.objectweb.asm.Type import org.objectweb.asm.tree.ClassNode import java.lang.instrument.Instrumentation import kotlin.coroutines.suspendCoroutine val BASE_CONTINUATION_INTERNAL_CLASS_NAME = BASE_CONTINUATION_CLASS_NAME.replace('.', '/') -val REGISTER_LOOKUP_METHOD_NAME = "\$decoroutinatorRegisterLookup" +const val REGISTER_LOOKUP_METHOD_NAME = "\$decoroutinatorRegisterLookup" private val debugMetadataAnnotationClassDescriptor = Type.getDescriptor(JavaUtilsImpl.metadataAnnotationClass) @Target(AnnotationTarget.CLASS) @@ -42,9 +43,7 @@ fun addDecoroutinatorClassFileTransformers(inst: Instrumentation) { Class.forName(BASE_CONTINUATION_CLASS_NAME) val stubClassName = _preloadStub::class.java.name val stubClassPath = stubClassName.replace('.', '/') + ".class" - val stubClassBody = ClassLoader.getSystemResourceAsStream(stubClassPath).use { classBodyStream -> - classBodyStream.readBytes() - } + val stubClassBody = loadResource(stubClassPath)!! val stubClassInternalName = stubClassName.replace('.', '/') DecoroutinatorClassFileTransformer.transform( loader = null, @@ -68,7 +67,7 @@ internal fun ClassNode.getDebugMetadataInfo(): DebugMetadataInfo? { val internalClassName = (parameters["c"] as String).replace('.', '/') val methodName = parameters["m"] as String val fileName = (parameters["f"] as String).ifEmpty { null } - val lineNumbers = (parameters["l"] as List).toSet() + @Suppress("UNCHECKED_CAST") val lineNumbers = (parameters["l"] as List).toSet() if (lineNumbers.isEmpty()) { return null } @@ -83,9 +82,9 @@ internal fun ClassNode.getDebugMetadataInfo(): DebugMetadataInfo? { return null } - @Suppress("ClassName") private class _preloadStub { + @Suppress("Unused") suspend fun suspendFun() { suspendCoroutine { } } diff --git a/stacktrace-decoroutinator-jvm-common/src/main/kotlin/utils-jvm-common.kt b/stacktrace-decoroutinator-jvm-common/src/main/kotlin/utils-jvm-common.kt index 4cd8d22..b0e9f62 100644 --- a/stacktrace-decoroutinator-jvm-common/src/main/kotlin/utils-jvm-common.kt +++ b/stacktrace-decoroutinator-jvm-common/src/main/kotlin/utils-jvm-common.kt @@ -1,11 +1,31 @@ package dev.reformator.stacktracedecoroutinator.jvmcommon -import dev.reformator.stacktracedecoroutinator.common.DecoroutinatorMarker -import org.objectweb.asm.Type - -private val decoroutinatorMarkerClassDescriptor = Type.getDescriptor(DecoroutinatorMarker::class.java) +@Suppress("ClassName") +private class _jvmcommonStub fun loadDecoroutinatorBaseContinuationClassBody(): ByteArray = - ClassLoader.getSystemResourceAsStream("decoroutinatorBaseContinuation.class").use { + loadResource("decoroutinatorBaseContinuation.class")!! + +fun loadResource(name: String): ByteArray? { + val classLoader = try { + Thread.currentThread().contextClassLoader + } catch (_: Throwable) { + null + } ?: try { + _jvmcommonStub::class.java.classLoader + } catch (_: Throwable) { + null + } ?: try { + ClassLoader.getSystemClassLoader() + } catch (_: Throwable) { + null + } + val stream = if (classLoader != null) { + classLoader.getResourceAsStream(name) + } else { + ClassLoader.getSystemResourceAsStream(name) + } + return stream?.use { it.readBytes() } +} diff --git a/stdlib/src/main/kotlin/stdlib.kt b/stdlib/src/main/kotlin/stdlib.kt index 653400f..73e5bb0 100644 --- a/stdlib/src/main/kotlin/stdlib.kt +++ b/stdlib/src/main/kotlin/stdlib.kt @@ -1,3 +1,5 @@ +@file:Suppress("PackageDirectoryMismatch") + package dev.reformator.stacktracedecoroutinator.stdlib import dev.reformator.stacktracedecoroutinator.common.* From aa97c4dead4be726bf7d2329d3896fbb981a821c Mon Sep 17 00:00:00 2001 From: berest Date: Mon, 6 Feb 2023 04:46:36 +0400 Subject: [PATCH 2/2] release --- README.md | 8 ++++---- build.gradle.kts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 273351f..c0c4d15 100644 --- a/README.md +++ b/README.md @@ -84,9 +84,9 @@ Thus, if the coroutine throws an exception, they mimic the real call stack of th ### JVM There are three ways to enable Stacktrace-decoroutinator for JVM. -1. (recommended) Add dependency `dev.reformator.stacktracedecoroutinator:stacktrace-decoroutinator-jvm:2.3.5` and call method `DecoroutinatorRuntime.load()`. -2. Add `-javaagent:stacktrace-decoroutinator-jvm-agent-2.3.5.jar` to your JVM start arguments. Corresponding dependency is `dev.reformator.stacktracedecoroutinator:stacktrace-decoroutinator-jvm-agent:2.3.5`. -3. (less recommended) Add dependency `dev.reformator.stacktracedecoroutinator:stacktrace-decoroutinator-jvm-legacy:2.3.5` and call method `DecoroutinatorRuntime.load()`. This way doesn't use Java instrumentation API unlike the way number 1. +1. (recommended) Add dependency `dev.reformator.stacktracedecoroutinator:stacktrace-decoroutinator-jvm:2.3.6` and call method `DecoroutinatorRuntime.load()`. +2. Add `-javaagent:stacktrace-decoroutinator-jvm-agent-2.3.6.jar` to your JVM start arguments. Corresponding dependency is `dev.reformator.stacktracedecoroutinator:stacktrace-decoroutinator-jvm-agent:2.3.6`. +3. (less recommended) Add dependency `dev.reformator.stacktracedecoroutinator:stacktrace-decoroutinator-jvm-legacy:2.3.6` and call method `DecoroutinatorRuntime.load()`. This way doesn't use Java instrumentation API unlike the way number 1. Usage example: ```kotlin @@ -152,7 +152,7 @@ java.lang.Exception: exception at 1653565535416 ``` ### Android -To enable Stacktrace-decoroutinator for Android you should add dependency `dev.reformator.stacktracedecoroutinator:stacktrace-decoroutinator-android:2.3.5` in your Android application and call method `DecoroutinatorRuntime.load()` before creating any coroutines. +To enable Stacktrace-decoroutinator for Android you should add dependency `dev.reformator.stacktracedecoroutinator:stacktrace-decoroutinator-android:2.3.6` in your Android application and call method `DecoroutinatorRuntime.load()` before creating any coroutines. It's recomended to add `DecoroutinatorRuntime.load()` call in your `Application.onCreate()` method. Example: ```kotlin diff --git a/build.gradle.kts b/build.gradle.kts index 3265eac..fcff982 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,5 +15,5 @@ buildscript { subprojects { group = "dev.reformator.stacktracedecoroutinator" - version = "2.3.5" + version = "2.3.6" }