ART crash with coroutines in obfuscated code
See original GitHub issueHello. Thanks for your work!
I’ve got a sample coroutine code in a tiny Android project.
It works great, but obfuscated and optimized code crashes ART (I use Nexus 5x with Android 7.1.1). Surprisingly, -useuniqueclassmembernames
ProGuard flag fixes the issue: my aggressive proguard-rules.pro.
Stack trace:
art/runtime/class_linker.cc:5452] Check failed: super_class->IsResolved()
art/runtime/runtime.cc:422] Runtime aborting...
art/runtime/runtime.cc:422] Aborting thread:
art/runtime/runtime.cc:422] "main" prio=10 tid=1 Runnable
art/runtime/runtime.cc:422] | group="" sCount=0 dsCount=0 obj=0x75600a68 self=0x7ce6095a00
art/runtime/runtime.cc:422] | sysTid=10811 nice=-10 cgrp=default sched=0/0 handle=0x7cea043a98
art/runtime/runtime.cc:422] | state=R schedstat=( 143266706 22457552 211 ) utm=7 stm=6 core=4 HZ=100
art/runtime/runtime.cc:422] | stack=0x7fd84e6000-0x7fd84e8000 stackSize=8MB
art/runtime/runtime.cc:422] | held mutexes= "abort lock" "mutator lock"(shared held)
art/runtime/runtime.cc:422] native: #00 pc 000000000047e090 /system/lib64/libart.so (_ZN3art15DumpNativeStackERNSt3__113basic_ostreamIcNS0_11char_traitsIcEEEEiP12BacktraceMapPKcPNS_9ArtMethodEPv+220)
art/runtime/runtime.cc:422] native: #01 pc 000000000047e08c /system/lib64/libart.so (_ZN3art15DumpNativeStackERNSt3__113basic_ostreamIcNS0_11char_traitsIcEEEEiP12BacktraceMapPKcPNS_9ArtMethodEPv+216)
art/runtime/runtime.cc:422] native: #02 pc 00000000004521f8 /system/lib64/libart.so (_ZNK3art6Thread9DumpStackERNSt3__113basic_ostreamIcNS1_11char_traitsIcEEEEbP12BacktraceMap+480)
art/runtime/runtime.cc:422] native: #03 pc 0000000000440170 /system/lib64/libart.so (_ZNK3art10AbortState10DumpThreadERNSt3__113basic_ostreamIcNS1_11char_traitsIcEEEEPNS_6ThreadE+56)
art/runtime/runtime.cc:422] native: #04 pc 000000000043ff90 /system/lib64/libart.so (_ZNK3art10AbortState4DumpERNSt3__113basic_ostreamIcNS1_11char_traitsIcEEEE+576)
art/runtime/runtime.cc:422] native: #05 pc 0000000000433998 /system/lib64/libart.so (_ZN3art7Runtime5AbortEPKc+148)
art/runtime/runtime.cc:422] native: #06 pc 00000000000e5a7c /system/lib64/libart.so (_ZN3art10LogMessageD2Ev+1592)
art/runtime/runtime.cc:422] native: #07 pc 000000000012810c /system/lib64/libart.so (_ZN3art11ClassLinker22LoadSuperAndInterfacesENS_6HandleINS_6mirror5ClassEEERKNS_7DexFileE+1324)
art/runtime/runtime.cc:422] native: #08 pc 0000000000124acc /system/lib64/libart.so (_ZN3art11ClassLinker11DefineClassEPNS_6ThreadEPKcmNS_6HandleINS_6mirror11ClassLoaderEEERKNS_7DexFileERKNS9_8ClassDefE+596)
art/runtime/runtime.cc:422] native: #09 pc 00000000001246dc /system/lib64/libart.so (_ZN3art11ClassLinker26FindClassInPathClassLoaderERNS_33ScopedObjectAccessAlreadyRunnableEPNS_6ThreadEPKcmNS_6HandleINS_6mirror11ClassLoaderEEEPPNS8_5ClassE+1484)
art/runtime/runtime.cc:422] native: #10 pc 000000000012566c /system/lib64/libart.so (_ZN3art11ClassLinker9FindClassEPNS_6ThreadEPKcNS_6HandleINS_6mirror11ClassLoaderEEE+944)
art/runtime/runtime.cc:422] native: #11 pc 000000000010ccb8 /system/lib64/libart.so (_ZN3art11ClassLinker11ResolveTypeERKNS_7DexFileEtNS_6HandleINS_6mirror8DexCacheEEENS4_INS5_11ClassLoaderEEE+200)
art/runtime/runtime.cc:422] native: #12 pc 0000000000115e60 /system/lib64/libart.so (_ZN3art11ClassLinker11ResolveTypeERKNS_7DexFileEtPNS_6mirror5ClassE+168)
art/runtime/runtime.cc:422] native: #13 pc 0000000000127cd4 /system/lib64/libart.so (_ZN3art11ClassLinker22LoadSuperAndInterfacesENS_6HandleINS_6mirror5ClassEEERKNS_7DexFileE+244)
art/runtime/runtime.cc:422] native: #14 pc 0000000000124acc /system/lib64/libart.so (_ZN3art11ClassLinker11DefineClassEPNS_6ThreadEPKcmNS_6HandleINS_6mirror11ClassLoaderEEERKNS_7DexFileERKNS9_8ClassDefE+596)
art/runtime/runtime.cc:422] native: #15 pc 00000000001246dc /system/lib64/libart.so (_ZN3art11ClassLinker26FindClassInPathClassLoaderERNS_33ScopedObjectAccessAlreadyRunnableEPNS_6ThreadEPKcmNS_6HandleINS_6mirror11ClassLoaderEEEPPNS8_5ClassE+1484)
art/runtime/runtime.cc:422] native: #16 pc 000000000012566c /system/lib64/libart.so (_ZN3art11ClassLinker9FindClassEPNS_6ThreadEPKcNS_6HandleINS_6mirror11ClassLoaderEEE+944)
art/runtime/runtime.cc:422] native: #17 pc 000000000010ccb8 /system/lib64/libart.so (_ZN3art11ClassLinker11ResolveTypeERKNS_7DexFileEtNS_6HandleINS_6mirror8DexCacheEEENS4_INS5_11ClassLoaderEEE+200)
art/runtime/runtime.cc:422] native: #18 pc 00000000000dfc90 /system/lib64/libart.so (_ZN3art11ClassLinker11ResolveTypeEtPNS_9ArtMethodE+340)
art/runtime/runtime.cc:422] native: #19 pc 000000000028de5c /system/lib64/libart.so (_ZN3art22ResolveVerifyAndClinitEjPNS_9ArtMethodEPNS_6ThreadEbb+96)
art/runtime/runtime.cc:422] native: #20 pc 000000000055d214 /system/lib64/libart.so (MterpInstanceOf+36)
art/runtime/runtime.cc:422] native: #21 pc 00000000000c2a18 /system/lib64/libart.so (ExecuteMterpImpl+4248)
art/runtime/runtime.cc:422] at _.nj.a(unavailable:-1) // kotlinx.coroutines.experimental.JobSupport#*
art/runtime/runtime.cc:422] at _.lz.a(unavailable:-1) // kotlinx.coroutines.experimental.AbstractCoroutine#*
art/runtime/runtime.cc:422] at _.jx.a(unavailable:-1) // kotlin.coroutines.experimental.jvm.internal.CoroutineImpl#*
art/runtime/runtime.cc:422] at _.ms.run(unavailable:-1) // kotlinx.coroutines.experimental.DispatchTask#run
art/runtime/runtime.cc:422] at android.os.Handler.handleCallback(Handler.java:751)
art/runtime/runtime.cc:422] at android.os.Handler.dispatchMessage(Handler.java:95)
art/runtime/runtime.cc:422] at android.os.Looper.loop(Looper.java:154)
art/runtime/runtime.cc:422] at android.app.ActivityThread.main(ActivityThread.java:6119)
art/runtime/runtime.cc:422] at java.lang.reflect.Method.invoke!(Native method)
art/runtime/runtime.cc:422] at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
art/runtime/runtime.cc:422] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Because of mixed class names, it’s very problematically to figure out which code causes this fault. Relevant part of mapping.txt:
kotlinx.coroutines.experimental.JobSupport -> _.nj:
void initParentJob(kotlinx.coroutines.experimental.Job) -> a
boolean updateState(java.lang.Object,java.lang.Object,int) -> a
void notifyCompletion(kotlinx.coroutines.experimental.JobSupport$NodeList,java.lang.Throwable) -> a
java.lang.Throwable getCompletionException() -> a
kotlinx.coroutines.experimental.DisposableHandle invokeOnCompletion(kotlin.jvm.functions.Function1) -> a
kotlinx.coroutines.experimental.DisposableHandle installHandler(kotlin.jvm.functions.Function1,boolean) -> a
kotlinx.coroutines.experimental.JobNode makeNode(kotlin.jvm.functions.Function1,boolean) -> a
boolean addLastAtomic(java.lang.Object,kotlinx.coroutines.experimental.JobSupport$NodeList,kotlinx.coroutines.experimental.JobNode) -> a
void promoteEmptyToNodeList(kotlinx.coroutines.experimental.Empty) -> a
void promoteSingleToNodeList(kotlinx.coroutines.experimental.JobNode) -> a
boolean getHasCancellingState() -> a
boolean cancel(java.lang.Throwable) -> a
boolean updateStateCancelled(kotlinx.coroutines.experimental.JobSupport$Incomplete,java.lang.Throwable) -> a
java.lang.Object access$getState$p(kotlinx.coroutines.experimental.JobSupport) -> a
java.util.concurrent.atomic.AtomicReferenceFieldUpdater access$getSTATE$cp() -> a
kotlinx.coroutines.experimental.AbstractCoroutine -> _.lz:
kotlin.coroutines.experimental.CoroutineContext getContext() -> a
boolean getHasCancellingState() -> a
void resume(java.lang.Object) -> a
void resumeWithException(java.lang.Throwable) -> a
kotlin.coroutines.experimental.jvm.internal.CoroutineImpl -> _.jx:
kotlin.coroutines.experimental.CoroutineContext getContext() -> a
kotlin.coroutines.experimental.Continuation getFacade() -> a
void resume(java.lang.Object) -> a
void resumeWithException(java.lang.Throwable) -> a
java.lang.Object doResume(java.lang.Object,java.lang.Throwable) -> a
kotlin.coroutines.experimental.Continuation create$469cb911(kotlin.coroutines.experimental.Continuation) -> a
I know this issue may be not on your side, but someone facing the same issue would be able to find the workaround mentioned above.
If anyone wants to reproduce: download app.zip, change extension to apk
, install, run, click ‘Coroutines’.
Issue Analytics
- State:
- Created 6 years ago
- Comments:5 (4 by maintainers)
Top Results From Across the Web
Random crashes when using kotlin coroutines - Stack Overflow
1 Answer 1 ... Step one should be to retrieve the obfuscation mapping.txt for the build in question and finding what e.b maps...
Read more >Is Your Kotlin Code Really Obfuscated? - ProAndroidDev
Solution. ProGuard's rules can be used for more than just preventing code from being obfuscated or deleted, it can be also be used...
Read more >C++ Coroutines Do Not Spark Joy - Hacker News
This article discusses things that are totally irrelevant to someone who will actually use coroutines, because they will use https://github.com/ ...
Read more >Is obfuscation worth it when it comes to security? : r/androiddev
Usually proguard crashes are very easy to spot as app is failing on particular screens immediately due to missing classes. Some QA before ......
Read more >Verifying app behavior on the Android runtime (ART)
Code produced by the Android build tools should be fine. However, some post-processing tools (especially tools that perform obfuscation) may ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Caught this on Nexus 7 with Android 5.1.
The problem is that
java.util.concurrent.atomic.AtomicReferenceFieldUpdater#newUpdater
acceptsString fieldName
, which may be standing for several fields at the same time.Actually, that option is used for -applymapping scenario: obfuscating lib or the main app; using the obfuscation map while obfuscating another app, e.g., test app. That option will help avoid naming conflict during the second, incremental obfuscation.
Those renamed fields with the same name actually originated from your usage of -overloadaggressively: https://www.guardsquare.com/en/proguard/manual/usage#overloadaggressively
I can see your proguard rule still has it: https://github.com/Miha-x64/Advanced-Kotlin-Patterns/blob/8bb246cd5fd29e9dd8308fefbe9ee0c95e7871d2/app/proguard-rules.pro#L5 Without that, you might not need -keepclassmembernames at the end.