【问题标题】:NoClassDefFoundError on runtime运行时 NoClassDefFoundError
【发布时间】:2017-11-29 17:59:07
【问题描述】:

我正在将一个项目迁移到 Android Studio 3Gradle 3

我们有多个模块,具有不同的依赖关系。当我编译项目时,一切看起来都很好。

我有一个带有可执行类(main)的模块来生成一些内部报告。 问题是在其中,我使用了来自另一个模块的方法,其中一个正在抛出 NoClassDefFoundError。在迁移之前它运行良好。

这里是 gradle 文件。假设 ModuleA 是可执行的,ModuleB 是中间的,ModuleC 是崩溃的:

模块A

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"
}

模块B

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'
}

模块C

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 并且它的依赖项(番石榴)被添加到它的内部分级文件

这是错误:

(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

【问题讨论】:

  • 不要对异常使用块引用,它会弄乱格式并使其难以阅读。请edit您的帖子并重新复制/粘贴堆栈跟踪,然后格式化为代码。
  • 检查您的 Proguard 设置是否混淆了所需的类库。​​
  • @CodeBullsInc.正如您在 gradle 代码中看到的那样,我没有在任何模块中使用 proguard。但是,我在其他模块中使用 proguard 可以使用 ModuleC 中的代码,但不是keepeng com.google.common
  • 我可能错了,但似乎 com.google.guava:guava:19.0 是通过 com.google.inject:guice:4.1 的传递依赖.0 你能把它删掉,看看它是否能解决你的问题。

标签: java gradle


【解决方案1】:

原来是 IntelliJ/Android Studio 中的一个错误:https://github.com/gradle/gradle/issues/1276。 Gradle 同步后创建的 iml 文件没有以正确的方式设置依赖关系。

【讨论】:

    【解决方案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'
      }
    }
    

    【讨论】:

    • 我已经完成了该更改。我认为这与此无关,因为在另一个模块中。
    【解决方案3】:

    您可以在构建后检查项目中使用的 jar 文件, 可能会在此路径中找到多个具有不同版本的类

    【讨论】:

      【解决方案4】:

      As mentioned in this answer 尝试在运行时打印实际的类路径。

      感觉就像你在类路径上有一些其他版本的 Guava。 我还将检查您的任何依赖项是否在其清单中具有 Class-Path 属性。 Guava 可能会以这种方式包含在 Gradle 依赖项中而不会出现。

      【讨论】:

        【解决方案5】:

        NoClassDefFoundError 不是由于没有找到特定的类引起的,在这种情况下会发生 ClassNotFoundException。

        当类加载器无法在运行时加载类时,会发生 NoClassDefFoundError。因此,找到了该类,但是在加载它时发生了一些不好的事情。通常,这是一些出错的静态内容。

        对我来说更典型的是,这是一个加载 dll 或 so 文件的类。通常是因为类的实现是本机的。您的 jni 错误表明这是正在发生的事情。因此,在这种情况下,您需要找到与 jar 一起使用的 dll,并将其添加到 PATH 或 LD_LIBRARY_PATH。

        这个问题似乎说明了其他人有类似的问题,一段时间后解决了他自己的问题。:https://github.com/google/guava/issues/1533 这个人在他的解释中没有特别详细,但他/她对问题的描述“就像我一样android中的新我不知道库必须放在“libs”文件夹中”对我来说是另一个迹象,这就是坏事。

        无论如何,这是 NoClassDefFoundError 过去一直困扰我的地方,尤其是与 jni 错误结合使用时。

        但是,如前所述,静态代码通常会出错,例如任何未捕获的异常。例如,它很可能是由一个类引起的,在该类中的静态代码中,例如打开一些文件而不处理异常。因此,也许这里列出的提示也可能会有所帮助:http://javareferencegv.blogspot.be/2013/10/debugging-javalangnoclassdeffounderror.html

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-09-03
          • 2020-11-11
          • 2018-06-16
          • 2014-04-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多