I'm migrating a project to Android Studio 3 and Gradle 3.
We have multiples modules, with different dependencies. When I compile the project, everything looks fine.
I have one module with executable classes (main) to generate some internal reports. The problem is that inside it, I'm using methods from another modules, and one of them is throwing NoClassDefFoundError. It worked fine before the migration.
Here are the gradle files. Let's say that ModuleA is the executable one, ModuleB is an intermediate one, and ModuleC is the one crashing:
ModuleA:
dependencies {
compile project(':ModuleB')
compile group: 'com.googlecode.protobuf-rpc-pro', name: 'protobuf-rpc-pro-duplex', version: '3.3'
testCompile "junit:junit:4.12"
}
sourceSets {
test {
java {
srcDirs = ['test']
}
resources {
srcDirs = ['test']
}
}
}
test {
afterTest { desc, result ->
println "Executing test ${desc.name} [${desc.className}] with result: ${result.resultType}"
}
workingDir = new File(rootProject.projectDir, '/Output')
jvmArgs "-Xmx1536m"
}
ModuleB:
dependencies {
compile project(':ModuleC')
compile project(':AnotherModule')
compile group: 'com.h2database', name: 'h2', version:'1.3.176'
compile group: 'com.google.code.gson', name: 'gson', version:'2.7'
compile group: 'org.json', name: 'json', version:'20080701'
}
ModuleC:
dependencies {
compile project(':AnotherModule')
compile project(':AnotherModule')
compile project(':AnotherModule')
compile group: 'org.slf4j', name: 'log4j-over-slf4j', version:'1.7.25'
compile group: 'org.slf4j', name: 'jul-to-slf4j', version:'1.7.25'
compile group: 'com.google.protobuf', name: 'protobuf-java', version:'2.6.1'
compile(group: 'com.google.inject', name: 'guice', version:'4.1.0', classifier:'no_aop') {
exclude(module: 'aopalliance')
}
compile(group: 'com.mortennobel', name: 'java-image-scaling', version:'0.8.6') {
exclude group: 'com.squareup.retrofit2', module: 'retrofit'
}
compile group: 'com.google.guava', name: 'guava', version: '19.0'
}
The class that can not be found is being used in ModuleC: com.google.common.base.Joiner and it's dependency (guava) it's being added inside it's gradle file
This is the error:
(1/124) RUNNING 'Internal check xxx'...
Exception in thread "main" java.lang.NoClassDefFoundError: com/google/common/base/Joiner
at com.degoo.util.FirebaseAnalyticsUtil.adjustTestKeyForFirebase(FirebaseAnalyticsUtil.java:35)
at com.degoo.util.FirebaseAnalyticsUtil.adjustPropertyString(FirebaseAnalyticsUtil.java:16)
at com.degoo.splittestrunner.SplitTestRunner.getQuery(SplitTestRunner.java:109)
at com.degoo.splittestrunner.SplitTestRunner.run(SplitTestRunner.java:67)
at com.degoo.splittestrunner.SplitTestRunner.main(SplitTestRunner.java:50)
Caused by: java.lang.ClassNotFoundException: com.google.common.base.Joiner
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 5 more
Any idea what can be happening? Thanks a lot!
EDIT:
This is the dependency tree if I run gradlew. Guava is present in compile, default, runtime and so on..
runtime - Runtime dependencies for source set 'main' (deprecated, use 'runtimeOnly ' instead).
+--- project :ProjectBackup
| +--- com.myapp:PackJPG:1.5
| +--- com.myapp:xz:1.2
| +--- org.ocpsoft.prettytime:prettytime:2.1.2.Final
| +--- joda-time:joda-time:2.1
| +--- project :ProjectCommon
| | +--- project :Utilities
| | +--- project :ProcessPriority
| | | +--- com.nativelibs4java:bridj:0.6.2
| | | | \--- com.google.android.tools:dx:1.7
| | | +--- net.java.dev.jna:jna:4.1.0
| | | +--- net.java.dev.jna:jna-platform:4.1.0
| | | | \--- net.java.dev.jna:jna:4.1.0
| | | +--- org.tinylog:slf4j-binding:1.2
| | | | +--- org.tinylog:tinylog:1.2
| | | | \--- org.slf4j:slf4j-api:[1.6,1.8) -> 1.7.25
| | | \--- project :Utilities
| | +--- project :ProjectHttp
| | | +--- commons-logging:commons-logging:1.2
| | | +--- org.tinylog:jcl-binding:1.2
| | | | +--- org.tinylog:tinylog:1.2
| | | | \--- commons-logging:commons-logging:[1.2,1.3) -> 1.2
| | | \--- commons-codec:commons-codec:1.10
| | +--- org.slf4j:log4j-over-slf4j:1.7.25
| | | \--- org.slf4j:slf4j-api:1.7.25
| | +--- org.slf4j:jul-to-slf4j:1.7.25
| | | \--- org.slf4j:slf4j-api:1.7.25
| | +--- com.google.protobuf:protobuf-java:2.6.1
| | +--- com.google.inject:guice:4.1.0
| | | +--- javax.inject:javax.inject:1
| | | \--- com.google.guava:guava:19.0
| | +--- org.bouncycastle:bcprov-jdk16:1.46
| | +--- com.mortennobel:java-image-scaling:0.8.6
| | | \--- com.jhlabs:filters:2.0.235
| | +--- com.google.guava:guava:19.0
| | \--- com.drewnoakes:metadata-extractor:2.9.1
| | \--- com.adobe.xmp:xmpcore:5.1.2
| +--- project :PackJPGInterFileCompression
| | +--- project :ProjectCommon (*)
| | \--- com.myapp:PackJPG:1.5
| +--- com.h2database:h2:1.3.176
| +--- com.google.code.gson:gson:2.7
| +--- org.json:json:20080701
| \--- itadaki:jbzip2:0.9.1
\--- com.googlecode.protobuf-rpc-pro:protobuf-rpc-pro-duplex:3.3
+--- com.google.protobuf:protobuf-java:2.6.1
+--- io.netty:netty-transport:4.0.23.Final
| \--- io.netty:netty-buffer:4.0.23.Final
| \--- io.netty:netty-common:4.0.23.Final
+--- io.netty:netty-common:4.0.23.Final
+--- io.netty:netty-handler:4.0.23.Final
| +--- io.netty:netty-buffer:4.0.23.Final (*)
| +--- io.netty:netty-transport:4.0.23.Final (*)
| \--- io.netty:netty-codec:4.0.23.Final
| \--- io.netty:netty-transport:4.0.23.Final (*)
+--- io.netty:netty-codec:4.0.23.Final (*)
\--- org.slf4j:slf4j-api:1.7.2 -> 1.7.25
Edit:
We have another similar case (the same error) but with classLoader and tinyLog
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: org/pmw/tinylog/writers/Writer
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
at java.lang.Class.getMethod0(Class.java:3018)
at java.lang.Class.getMethod(Class.java:1784)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:544)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:526)
Caused by: java.lang.ClassNotFoundException: org.pmw.tinylog.writers.Writer
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 7 more
lang. NoClassDefFoundError, which means the Class Loader file responsible for dynamically loading classes can not find the . class file. So to remove this error, you should set your classpath to the location where your Class Loader is present.
The NoClassDefFoundError is a runtime error in Java that occurs if the Java Virtual Machine (JVM) or a ClassLoader instance attempts to load the definition of a class that could not be found. The class definition exists at compile-time but is not available at runtime.
To resolve module dependency, we use the module path. However, adding external jars in the module path does not make them available for the class loader. Hence the class loader considers them as missing dependencies and throws the NoClassDefFoundError.
NoClassDefFoundError is thrown when a class has been compiled with a specific class from the classpath but if same class not available during run-time. Missing JAR files are the most basic reason to get NoClassDefFoundError.
It turned out to be a bug in IntelliJ/Android Studio: https://github.com/gradle/gradle/issues/1276. The iml file created after a Gradle sync did not set the dependencies in a correct way.
you can check jar files used in project after build, maybe find more than one class with different version in this path
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With