37

I am currently working on an Android application with Kotlin in version 1.1.1

In my code, I have imbrication of several forEach structures in order to read several MutableList and MutableMap.

Unfortunately, my app crashes with the following stacktrace :

java.lang.NoClassDefFoundError: com.package.fragment.ReminderAddFragment$onRetrieveBusinessObjects$$inlined$forEach$lambda$1 at com.package.fragment.ReminderAddFragment.onRetrieveBusinessObjects(ReminderAddFragment.kt:275) at com.smartnsoft.droid4me.app.Droid4mizer.onRetrieveBusinessObjects(Droid4mizer.java:552) at com.smartnsoft.droid4me.app.Droid4mizer.onRetrieveBusinessObjectsInternal(Droid4mizer.java:606) at com.smartnsoft.droid4me.app.Droid4mizer.access$000(Droid4mizer.java:46) at com.smartnsoft.droid4me.app.Droid4mizer$1.run(Droid4mizer.java:197) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423) at java.util.concurrent.FutureTask.run(FutureTask.java:237) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588) at java.lang.Thread.run(Thread.java:818)

Here the code

tutorialCategories.forEach { (_, _, _, _, _, tutorials) ->
  tutorials.forEach { tutorial ->
    if (tutorial.id == simpleReminderFromExtra.tutorialId)
    {
      //...
      val mapOfreminders = mutableMapOf<Int, MutableList<Reminder>>()
      val reminders = ReminderServices.getReminderByTutorialId(simpleReminderFromExtra.tutorialId)

      reminders.forEach { reminder ->
        //...
      }

      mapOfreminders.forEach { _, finalReminders ->
        //...

        finalReminders.forEach { reminder ->
          //...
        }

        //...
      }
    }
  }
}

Where :

  • tutorialCategories is a List ;
  • tutorials is a List ;
  • reminders is a List ;

The line 275 of the code is mapOfreminders.forEach { _, finalReminders ->.

In the debugger, I can evaluate the mapOfreminders variable and everything seems to be alright.

If someone can help to resolve this issue !

rolandl
  • 1,769
  • 1
  • 25
  • 48
  • Could you also specify, what version of Kotlin do you use? – Ilya Mar 18 '17 at 00:42
  • I am using Kotlin 1.1.1. I have edited my post. – rolandl Mar 18 '17 at 00:43
  • Can you post more context, like your includes and variable definitions? Can you, somehow fetch the version in code before the crash? If you are getting a no class-def error, you are either distributing your binary without the required dependencies, or are running with a different version then you built with. – Matt Clark Mar 18 '17 at 00:48

3 Answers3

75

After reading Dan Lew's post a couple days ago, I'll make a suggestion that this can be caused by using Map.forEach { k, v -> } method from Java 8, which may be unavailable in Android runtime.

You could try to use another forEach with the single entry parameter that comes from the Kotlin standard library:

mapOfreminders.forEach { (_, finalReminders) -> }

Here the parentheses are used to destructure entry parameter into two variables: ignored key and finalReminders value.

Ilya
  • 21,871
  • 8
  • 73
  • 92
  • also, you need to disable instant run! – iscariot Aug 10 '18 at 09:57
  • does anybody knows of a compiler flag that would throw an error or at least a warning when using the BiConsumer function from Java 8 instead of the Kotlin one? It adds crashes in my app and I'd like to make sure that I never use the wrong version again – dvkch Sep 13 '18 at 11:37
  • @dvkch That `forEach` function from Java 8 should be caught by linter in Android Studio starting from 3.2. See this issue https://issuetracker.google.com/issues/80464232 – Ilya Sep 13 '18 at 20:33
  • @ilya it is indeed underlined in red but doesn't prevent compilation in 3.2 RC3. that's a start, probably have to enable something somewhere. thanks for the tip! – dvkch Sep 14 '18 at 14:09
13

I encountered this problemjava.lang.NoClassDefFoundError on Android 6.0 and 6.0.1 by using

Map.forEach {key ,value -> }

this call java 8 api.

And then, I solved this problem by adding brackets to parameter:

Map.forEach {(key ,value) -> }

this call kotlin api

Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
zhangliang
  • 1,041
  • 9
  • 9
2

Seems like this particular error doesn't happen on all phones. I faced a similar issue with Samsung Galaxy S7, where the app was crashing with ClassNotFoundError. This solution works if we still want to use lambda. Else replacing the lambda with for ((key, value) in map) { ... }also works.

theThapa
  • 581
  • 4
  • 11