我将项目迁移到 Android Studio 3 和 Gradle 3 。
我们有多个模块,具有不同的依赖关系。当我编译项目时,一切看起来都很好。
我有一个带可执行类(main)的模块来生成一些内部报告。 问题是,在其中,我使用其他模块中的方法,其中一个是抛出 NoClassDefFoundError 。它在迁移之前运行良好。
以下是gradle文件。我们假设 ModuleA 是可执行文件, ModuleB 是中间文件, ModuleC 是崩溃的文件:
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'
}
ModuleC : com.google.common.base.Joiner 中使用了无法找到的类及其依赖(guava)它& #39; s被添加到其gradle文件中
这是错误:
(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
知道会发生什么事吗? 非常感谢!
编辑:
如果我运行 gradlew ,这是依赖关系树。 Guava 存在于编译,默认,运行时等......
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
修改
我们有另一个类似的情况(相同的错误),但有classLoader和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
答案 0 :(得分:2)
根据此文档,这是一个已知的问题:
https://developer.android.com/studio/build/gradle-plugin-3-0-0.html
Firebase插件版本1.1.0可能导致Guava不匹配 使用Android插件3.0.0-alpha5时的依赖关系,导致了 以下错误:
基于堆栈跟踪,问题在于这个插件,虽然我不认为这是你文件中列出的依赖关系。
但建议的解决方案是将其从类路径中排除:
dependencies {
classpath ('com.google.firebase:firebase-plugins:1.1.0') {
exclude group: 'com.google.guava', module: 'guava-jdk5'
}
}
答案 1 :(得分:2)
原来是IntelliJ / Android Studio中的一个错误:https://github.com/gradle/gradle/issues/1276。 Gradle同步后创建的iml文件没有以正确的方式设置依赖项。
答案 2 :(得分:0)
As mentioned in this answer尝试在运行时打印实际的类路径。
感觉你在类路径上有一些其他版本的Guava。
我还会检查您的任何依赖项是否在其清单中具有Class-Path
属性。可以通过这种方式包含Guava,而不会出现在Gradle依赖项中。
答案 3 :(得分:0)
NoClassDefFoundError不是由于没有找到特定的类引起的,在这种情况下会发生ClassNotFoundException。
当类加载器无法在运行时加载类时,会发生NoClassDefFoundError。所以,找到了这个类,但加载它时发生了一些不好的事情。通常这是一些出错的静态东西。
对我来说更典型的是,这是一个加载dll或so文件的类。通常因为类的实现是本机的。你的jni错误表明这是正在发生的事情。因此,在这种情况下,您需要找到与jar一起使用的dll,并将其添加到PATH或LD_LIBRARY_PATH。
这个问题似乎说明了其他有类似问题的人,在一段时间后解决了自己的问题。https://github.com/google/guava/issues/1533这个人在他的解释中并不是特别详细,但是他/她对问题的描述“As我是android新手我不知道库必须放在“libs”文件夹中“对我来说是另一个迹象,这就是糟糕的事情。
无论如何,NoClassDefFoundError过去一直困扰着我,特别是在与jni错误结合时。
但是,如上所述,静态代码通常会出现问题,就像任何未捕获的异常一样。例如,它可能是由类中的静态代码引起的,例如,打开一些文件而不处理异常。因此,这里列出的提示可能也会有所帮助:http://javareferencegv.blogspot.be/2013/10/debugging-javalangnoclassdeffounderror.html
答案 4 :(得分:0)
你可以在构建后检查项目中使用的jar文件, 也许在这条路径中找到不同版本的多个类