NoClassDefFoundError во время выполнения

Я переношу проект в Android Studio 3 и Gradle 3.

У нас есть модули с разными значениями. Когда я скомпилирую проект, все выглядит отлично.

У меня есть один модуль с исполняемыми классами (основной) для создания некоторых внутренних отчетов. Проблема в том, что внутри него я использую методы из других модулей, и один из них бросает 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), который добавляется внутри него Gradle file

Это ошибка:

(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

Любая идея, что может случиться? Большое спасибо!

EDIT:

Это дерево зависимостей, если я запускаю 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

Edit:

У нас есть другой подобный случай (та же ошибка), но с 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

Ответ 1

Это оказалось ошибкой в ​​IntelliJ/Android Studio: https://github.com/gradle/gradle/issues/1276. Файл iml, созданный после синхронизации Gradle, не задал зависимостей правильным образом.

Ответ 2

Основываясь на этом документе, это проблема с информацией:

https://developer.android.com/studio/build/gradle-plugin-3-0-0.html

Плагин Firebase версии 1.1.0 может вызвать несоответствие в Guava зависимостей при использовании Android-плагина 3.0.0-alpha5, в результате чего следующая ошибка:

Основываясь на stacktrace, проблема связана с этим плагином, хотя я не вижу в нем зависимостей, перечисленных в ваших файлах.

Но предлагаемое решение состоит в том, чтобы исключить его из пути к классам:

dependencies {
  classpath ('com.google.firebase:firebase-plugins:1.1.0') {
          exclude group: 'com.google.guava', module: 'guava-jdk5'
  }
}

Ответ 3

Как уже упоминалось в этом ответе, попробуйте напечатать фактический путь к классам во время выполнения.

Похоже, у вас есть другая версия Guava на пути к классам. Я также хотел бы проверить, имеет ли в ваших манифестах атрибут Class-Path. Guava может быть включен таким образом, не будучи обнаруженным в зависимостях Gradle.

Ответ 4

NoClassDefFoundError не вызван тем, что не нашел этот конкретный класс, и в этом случае возникло бы исключение ClassNotFoundException.

NoClassDefFoundError возникает, когда класс не может быть загружен во время выполнения загрузчиком класса. Итак, класс найден, но что-то плохое происходит при его загрузке. Обычно это какой-то статический материал, который идет не так.

Еще более типично для меня это класс, который загружает dll или такой файл. Обычно, поскольку реализация класса является родной. Ваша jni-ошибка указывает на то, что происходит. Таким образом, в этом случае вам нужно найти DLL или так, что будет с банкой, и добавить ее в PATH или LD_LIBRARY_PATH.

Эта проблема, кажется, иллюстрирует кого-то другого с аналогичной проблемой, исправляя его собственную проблему через некоторое время.: https://github.com/google/guava/issues/1533 Человек isn Особенно подробно в его объяснении, но его/ее описание проблемы "Поскольку я новичок в android, я не знал, что библиотеки должны быть помещены в папку" libs ", это еще одно указание на меня, вот что происходит плохой.

Во всяком случае, там, где NoClassDefFoundError прослушивал меня в прошлом, особенно в сочетании с jni-ошибками.

Но, как сказано, обычно это не так, как в статическом коде, как любое неперехваченное исключение. Например, это может быть вызвано классом, в статическом коде внутри этого класса, например. открывая файл и не обрабатывая исключение. Итак, возможно, приведенные здесь советы также могут быть полезны: http://javareferencegv.blogspot.be/2013/10/debugging-javalangnoclassdeffounderror.html

Ответ 5

проверьте файлы jar в .war\WEB-INF\lib после сборки возможно, найти два класса с другой версией на этом пути :)