简体   繁体   中英

Android Studio java-library module classpath NoClassDefFoundError

My project is started to be large, so I decided to split it into separated modules - gui and domain . My domain module mustn't know that it is a part of Android project, so I created java-library module and put some classes there. It works like a charm but there is a problem when I add some other dependencies inside my java-library module like RxJava. I've created a Main class to simply test my code. Builds passes, but when it tries to invoke RxJava classes it crashes with exception:

    Exception in thread "main" java.lang.NoClassDefFoundError: io/reactivex/Observable
    at com.example.domain.Main.main(Main.java:13)
    Caused by: java.lang.ClassNotFoundException: io.reactivex.Observable
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 1 more

My Main class:

package com.example.domain;

import io.reactivex.Observable;

public class Main {

    public static void main(String[] args) {
        Observable.just(1)
                .subscribe(integer -> System.out.println(integer));
    }

}

My build.gradle file:

apply plugin: 'java-library'

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    api 'io.reactivex.rxjava2:rxjava:2.1.2'
}

sourceCompatibility = "1.8"
targetCompatibility = "1.8"

1) If I use com.android.library instead it works

2) If I add RxJava library as a .jar file it changes nothing

EDIT:

I looked into Domain.iml file and I found something strange:

<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id=":Domain" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" type="JAVA_MODULE" version="4">
  <component name="FacetManager">
    <facet type="android-gradle" name="Android-Gradle">
      <configuration>
        <option name="GRADLE_PROJECT_PATH" value=":Domain" />
      </configuration>
    </facet>
    <facet type="java-gradle" name="Java-Gradle">
      <configuration>
        <option name="BUILD_FOLDER_PATH" value="$MODULE_DIR$/build" />
        <option name="BUILDABLE" value="true" />
      </configuration>
    </facet>
  </component>
  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
    <output url="file://$MODULE_DIR$/build/classes/java/main" />
    <output-test url="file://$MODULE_DIR$/build/classes/java/test" />
    <exclude-output />
    <content url="file://$MODULE_DIR$">
      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
      <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
      <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
      <excludeFolder url="file://$MODULE_DIR$/.gradle" />
      <excludeFolder url="file://$MODULE_DIR$/build" />
    </content>
    <orderEntry type="inheritedJdk" />
    <orderEntry type="sourceFolder" forTests="false" />
    <orderEntry type="library" exported="" scope="PROVIDED" name="rxjava-2.1.2" level="project" />
    <orderEntry type="library" exported="" scope="PROVIDED" name="reactive-streams-1.0.0" level="project" />
  </component>
</module>

The weird part is scope attribute in orderEntry node

<orderEntry type="library" exported="" scope="PROVIDED" name="rxjava-2.1.2" level="project" />
<orderEntry type="library" exported="" scope="PROVIDED" name="reactive-streams-1.0.0" level="project" />

If I remove it manually:

<orderEntry type="library" exported="" name="rxjava-2.1.2" level="project" />
<orderEntry type="library" exported="" name="reactive-streams-1.0.0" level="project" />

It works like a charm.

Unfortunately if I sync my build.gradle file it overrides my modification.

How to make it works permanently and why this acts like this?

The weird part is scope attribute in orderEntry node

 <orderEntry type="library" exported="" scope="PROVIDED" name="rxjava-2.1.2" level="project" /> <orderEntry type="library" exported="" scope="PROVIDED" name="reactive-streams-1.0.0" level="project" /> 

If I remove it manually:

 <orderEntry type="library" exported="" name="rxjava-2.1.2" level="project" /> <orderEntry type="library" exported="" name="reactive-streams-1.0.0" level="project" /> 

It works like a charm.

Unfortunately if I sync my build.gradle file it overrides my modification.

Have you tried to change the scope via Android Studios Project Structure?

File -> Project Structure then select the Dependencies Tab and add the Dependency for the required module. In your case that would be java-library I believe.

As far as i know you can't change the scope of the dependency once added. So if you have already added it, try to remove and add it again. Be sure to assign the implementation scope though and see if it works.

I hope this was helpful

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM