@@ -11,6 +11,21 @@ import java.util.*
11
11
import kotlin.coroutines.*
12
12
import kotlin.coroutines.intrinsics.*
13
13
14
+ /*
15
+ * `Class.forName(name).canonicalName` instead of plain `name` is required to properly handle
16
+ * Android's minifier that renames these classes and breaks our recovery heuristic without such lookup.
17
+ */
18
+ private const val baseContinuationImplClass = " kotlin.coroutines.jvm.internal.BaseContinuationImpl"
19
+ private const val stackTraceRecoveryClass = " kotlinx.coroutines.internal.StackTraceRecoveryKt"
20
+
21
+ private val baseContinuationImplClassName = runCatching {
22
+ Class .forName(baseContinuationImplClass).canonicalName
23
+ }.getOrElse { baseContinuationImplClass }
24
+
25
+ private val stackTraceRecoveryClassName = runCatching {
26
+ Class .forName(stackTraceRecoveryClass).canonicalName
27
+ }.getOrElse { stackTraceRecoveryClass }
28
+
14
29
internal actual fun <E : Throwable > recoverStackTrace (exception : E ): E {
15
30
if (recoveryDisabled(exception)) return exception
16
31
// No unwrapping on continuation-less path: exception is not reported multiple times via slow paths
@@ -21,10 +36,9 @@ internal actual fun <E : Throwable> recoverStackTrace(exception: E): E {
21
36
private fun <E : Throwable > E.sanitizeStackTrace (): E {
22
37
val stackTrace = stackTrace
23
38
val size = stackTrace.size
24
-
25
- val lastIntrinsic = stackTrace.frameIndex(" kotlinx.coroutines.internal.StackTraceRecoveryKt" )
39
+ val lastIntrinsic = stackTrace.frameIndex(stackTraceRecoveryClassName)
26
40
val startIndex = lastIntrinsic + 1
27
- val endIndex = stackTrace.frameIndex(" kotlin.coroutines.jvm.internal.BaseContinuationImpl " )
41
+ val endIndex = stackTrace.frameIndex(baseContinuationImplClassName )
28
42
val adjustment = if (endIndex == - 1 ) 0 else size - endIndex
29
43
val trace = Array (size - lastIntrinsic - adjustment) {
30
44
if (it == 0 ) {
@@ -83,7 +97,7 @@ private fun <E : Throwable> recoverFromStackFrame(exception: E, continuation: Co
83
97
private fun <E : Throwable > createFinalException (cause : E , result : E , resultStackTrace : ArrayDeque <StackTraceElement >): E {
84
98
resultStackTrace.addFirst(artificialFrame(" Coroutine boundary" ))
85
99
val causeTrace = cause.stackTrace
86
- val size = causeTrace.frameIndex(" kotlin.coroutines.jvm.internal.BaseContinuationImpl " )
100
+ val size = causeTrace.frameIndex(baseContinuationImplClassName )
87
101
if (size == - 1 ) {
88
102
result.stackTrace = resultStackTrace.toTypedArray()
89
103
return result
0 commit comments