Kotlin / kotlinx-datetime

KotlinX multiplatform date/time library

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Clock.System.now() fails on Android SDK less than 26

dekar91 opened this issue · comments

Hi!
Call of Clock.System.now() fails with java.lang.NoClassDefFoundError: kotlinx.datetime.Instant() on Android 7 and earlier because Instant() was added to SDK in version 26.

Should I provide platform-specific implementation instead?

This looks extremely strange. kotlinx.datetime.Instant is a class from our library, not the Instant from the SDK, so this NoClassDefFoundError should mean that it is our library that is not available. Could you provide a full stack trace or a small reproducing project? Or maybe this is some kind of build misconfiguration, but if so, typically the problem should reproduce on all SDK versions.

Looks weird - tried to reproduce the problem with another project, but it does not compile because "Clock is deprecated, use TimeSource".
For my main project stacktrace looks like this:

  java.lang.NoClassDefFoundError: kotlinx.datetime.Instant
        at kotlinx.datetime.Clock$System.now(Clock.kt:17)
            ...
     
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
    ```

You've likely imported the wrong Clock: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.time/-clock.html, as opposed to kotlinx.datetime.Clock.

There is my sample code: https://github.com/dekar91/kolinx.datetime_clock
Try to run it on sdk 21 device:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: ru.test, PID: 5529
    java.lang.NoClassDefFoundError: Failed resolution of: Ljava/time/Instant;
        at kotlinx.datetime.Instant.<clinit>(Instant.kt:78)
        at kotlinx.datetime.Clock$System.now(Clock.kt:17)
        at ru.test.ru.test.utils.ServerTime.getServerDateString(ServerTime.kt:24)
        at ru.test.ui.MainActivity.onCreate(MainActivity.kt:16)
        at android.app.Activity.performCreate(Activity.java:5937)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
        at android.app.ActivityThread.access$800(ActivityThread.java:144)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5221)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "java.time.Instant" on path: DexPathList[[zip file "/data/app/ru.test-2/base.apk"],nativeLibraryDirectories=[/data/app/ru.test-2/lib/x86_64, /vendor/lib64, /system/lib64]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
        at kotlinx.datetime.Instant.<clinit>(Instant.kt:78) 
        at kotlinx.datetime.Clock$System.now(Clock.kt:17) 
        at ru.test.ru.test.utils.ServerTime.getServerDateString(ServerTime.kt:24) 
        at ru.test.ui.MainActivity.onCreate(MainActivity.kt:16) 
        at android.app.Activity.performCreate(Activity.java:5937) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360) 
        at android.app.ActivityThread.access$800(ActivityThread.java:144) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:135) 
        at android.app.ActivityThread.main(ActivityThread.java:5221) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at java.lang.reflect.Method.invoke(Method.java:372) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 
    	Suppressed: java.lang.ClassNotFoundException: java.time.Instant
        at java.lang.Class.classForName(Native Method)
        at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
        at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
        		... 18 more
     Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available
     ```

Judging by the trace, this reproduces another problem, possibly a duplicate of #92, though I'll look into it. Observe that the class that is not found in this case is java.time.Instant, which is less abnormal than kotlinx.datetime.Instant not being found.

Well, I reproduces the problem a little bit incorrecly. There is full stacktrace from my main project:

E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-1
    Process: ru.rest, PID: 6345
    java.lang.NoClassDefFoundError: Failed resolution of: Ljava/time/Instant;
        at kotlinx.datetime.Instant.<clinit>(Instant.kt:78)
        at kotlinx.datetime.Clock$System.now(Clock.kt:17)
     
     ....
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56)
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
     Caused by: java.lang.ClassNotFoundException: Didn't find class "java.time.Instant" on path: DexPathList[[zip file "/data/app/ru.test-1/base.apk"],nativeLibraryDirectories=[/data/app/ru.test.scanner-1/lib/x86_64, /vendor/lib64, /system/lib64]]
        at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
        at kotlinx.datetime.Instant.<clinit>(Instant.kt:78) 
        at kotlinx.datetime.Clock$System.now(Clock.kt:17) 
       ...
       
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) 
        at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56) 
        at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571) 
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738) 
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678) 
        at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665) 
    	Suppressed: java.lang.ClassNotFoundException: java.time.Instant
        at java.lang.Class.classForName(Native Method)
        at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
        at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
        		... 17 more
     Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack available
V/FA: Recording user engagement, ms: 11913
Disconnected from the target VM, address: 'localhost:61815', transport: 'socket'

I see, the same supressed Caused by: java.lang.ClassNotFoundException: Didn't find class "java.time.Instant", but explicitly added kotlinx.datetime` to android gradle does not solve the problem.

Update tried to add kotlinx.datetime explicitly at github I provided does not fix the problem as well. Probably, I've imported the library incorrectly?

WeSeems I've found a solution:

  1. Add coreLibraryDesugator by official documentation,
  2. Add kotlinx.datetime to android dependencies.

Android 6 does not crash anymore.
Thank you for your help.
This issue can be closed.