arrow-kt / arrow

Λrrow - Functional companion to Kotlin's Standard Library
http://arrow-kt.io
Other
6.18k stars 452 forks source link

Fatal exception java.lang.VerifyError: arrow/core/internal/AtomicBooleanW using IO.fx on Dalvik VMs #1798

Closed tomjhall closed 4 years ago

tomjhall commented 4 years ago

I get a VerifyError (exception below) on a Dalvik VM when I run the following code:

unsafe { runBlocking { IO.fx { !sleep(1.seconds) } } }

I have created a repo with the minimal libraries demonstrating the issue here.

To reproduce - just run the app on a pre Lollipop device (I am using API 19), the app will crash with something like the following:

register1 v2 type 17, wanted 5 rejecting opcode 0x71 at 0x000a rejected Larrow/core/internal/AtomicBooleanW;.updateAndGet (Lkotlin/jvm/functions/Function1;)Z Verifier rejected class Larrow/core/internal/AtomicBooleanW; Shutting down VM threadid=1: thread exiting with uncaught exception (group=0x9ccb8b20) FATAL EXCEPTION: main Process: com.sample.arrowtest, PID: 2693 java.lang.VerifyError: arrow/core/internal/AtomicBooleanW at arrow.fx.IO$Companion$cancelable$1.invoke(IO.kt:1110) at arrow.fx.IO$Companion$cancelable$1.invoke(IO.kt:52) at arrow.fx.IORunLoop$RestartCallback.start(IORunLoop.kt:397) at arrow.fx.IORunLoop.loop(IORunLoop.kt:218) at arrow.fx.IORunLoop.access$loop(IORunLoop.kt:21) at arrow.fx.IORunLoop$suspendAsync$1.invoke(IORunLoop.kt:145) at arrow.fx.IORunLoop$suspendAsync$1.invoke(IORunLoop.kt:21) at arrow.fx.IORunLoop$RestartCallback.start(IORunLoop.kt:397) at arrow.fx.IORunLoop.loop(IORunLoop.kt:218) at arrow.fx.IORunLoop.start(IORunLoop.kt:24) at arrow.fx.IO.unsafeRunAsync(IO.kt:796) at arrow.fx.internal.Platform.unsafeResync(Utils.kt:156) at arrow.fx.IO$Async.unsafeRunTimedTotal$arrow_fx(IO.kt:1017) at arrow.fx.IO.unsafeRunTimed(IO.kt:862) at arrow.fx.IO.unsafeRunSync(IO.kt:851) at arrow.fx.extensions.IOUnsafeRun$DefaultImpls.runBlocking(io.kt:247) at arrow.fx.extensions.io.unsafeRun.IOUnsafeRunKt$unsafeRun_singleton$1.runBlocking(IOUnsafeRun.kt:21) at arrow.fx.extensions.io.unsafeRun.IOUnsafeRunKt.runBlocking(IOUnsafeRun.kt:31) at com.sample.arrowtest.MainActivity$onCreate$1.invokeSuspend(MainActivity.kt:18) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlin.coroutines.ContinuationKt.startCoroutine(Continuation.kt:128) at arrow.unsafe.invoke(unsafe.kt:30) at com.sample.arrowtest.MainActivity.onCreate(MainActivity.kt:17) at android.app.Activity.performCreate(Activity.java:5231) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245) at android.app.ActivityThread.access$800(ActivityThread.java:135) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5017) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595) at dalvik.system.NativeStart.main(Native Method) Force finishing activity com.sample.arrowtest/.MainActivity

I am building on Android Studio 3.5.2 (Linux) using Arrow 0.10.3. Tested on emulator API 19 (fails), and API 22 (works).

aballano commented 4 years ago

Hi @tomjhall it seems the problem is that Arrow is not compatible with Android API < 21 due to some Java api usages only available from API 21 and upwards.

tomjhall commented 4 years ago

Hi thanks for the quick response. Is there any way we Arrow could have a fallback for pre 21 APIs? According to the distribution dashboard 4.x devices (back to API 16) account for 10% of devices on the Android platform.

If not a fallback perhaps a @RequiresApi annotation for any methods that do require certain APIs (so that these could be avoided/a warning would be shown in the IDE). I realise that Arrow isn't just used for Android so this could be problematic.

aballano commented 4 years ago

Hi thanks for the quick response. Is there any way we Arrow could have a fallback for pre 21 APIs? According to the distribution dashboard 4.x devices (back to API 16) account for 10% of devices on the Android platform.

If not a fallback perhaps a @RequiresApi annotation for any methods that do require certain APIs (so that these could be avoided/a warning would be shown in the IDE). I realise that Arrow isn't just used for Android so this could be problematic.

So, the bad news here is that is not straightforward, because there are several parts using Java 8 APIs that were added on Android +21, and I'm not sure they can be easily changed

The good news is that we have a checker for that checking vs API 21 (animal sniffer, thanks to @junron), so it should be really easy discovering which of Arrow APIs use functions or other APIs not present in a specific Android version.

Although I would have arguments to not support lower APIs than that if it's not straightforward to do so, actually not even Google is doing so in their new frameworks (e.g. the new Compose). But I'd like to hear other people's opinions on this as well

aballano commented 4 years ago

@tomjhall I'm closing this issue now as the issue seems to be related to the Android version you're using. But please feel free to open a new one if you would like Arrow to support a lower API version, thank you :)