I have a question about how the serviceloader changed in Java 9 based on this scenario
Scenario
Project gert
Class Main
package gert;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
public class Main {
static public void test() throws JAXBException {
InputStream is = new ByteArrayInputStream("<Classes RUNTIME_INCLUDE_JARS=\"\"><Class></Class></Classes>".getBytes(StandardCharsets.UTF_8));
JAXBContext jaxbContext = JAXBContext.newInstance(ClassesDef.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
unmarshaller.unmarshal(is);
}
}
Project gert
Class ClassesDef
package gert;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="Classes")
public class ClassesDef {
@XmlAttribute(name="RUNTIME_INCLUDE_JARS")
public String jars=null;
@XmlElement(name="Class")
public String classes;
}
Project gert
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>gert</groupId>
<artifactId>gert</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>gert.Main</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency><!-- org.eclipse.persistence.jaxb.JAXBContextFactory comes with this dependency-->
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.26</version>
</dependency>
</dependencies>
</project>
Project cristina
Class Main
package cristina;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
public class Main {
public static void main(String[] args) throws Exception {
System.setProperty("javax.xml.bind.JAXBContextFactory", "org.eclipse.persistence.jaxb.JAXBContextFactory");
String bWithDep = "C:\\Users\\gert\\eclipse-workspace91java\\gert\\target\\gert-0.0.1-SNAPSHOT-jar-with-dependencies.jar";
List<URL> jars = new java.util.ArrayList<URL>();
File f;
f = new File(bWithDep);
jars.add(f.toURL());
URL[] urls = (URL[])jars.toArray(new URL[jars.size()]);
URLClassLoader urlloader = URLClassLoader.newInstance(urls, ClassLoader.getSystemClassLoader());
System.out.println("Before\tgert.Main.test();.");
Class<?> c= Class.forName("gert.Main", true, urlloader);
Object gert = c.newInstance();
Method m = c.getMethod("test");
m.invoke(gert);
System.out.println("After\tgert.Main.test();.");
}
}
Project cristina
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cristina</groupId>
<artifactId>cristina</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- <dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.26</version>
</dependency> -->
</dependencies>
</project>
So the cristina main
loads the gert project and executes a method of gert named test()
Testing
Java 8
When the project is run with java 8 it works
Command
"C:\Program Files\Java\jre1.8.0_151\bin\java.exe" -cp C:\Users\gert\eclipse-workspace91java\cristina\target\cristina-0.0.1-SNAPSHOT.jar cristina.Main
Output
Before gert.Main.test();.
After gert.Main.test();.
Java 9
When the same is done with java 9 it doesnt
Command
"C:\Program Files\Java\jre-9.0.1\bin\java.exe" -cp C:\Users\gert\eclipse-workspace91java\cristina\target\cristina-0.0.1-SNAPSHOT.jar cristina.Main
Output
Before gert.Main.test();.
Exception in thread "main" java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at cristina.Main.main(Main.java:23)
Caused by: javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
- with linked exception:
[java.lang.ClassNotFoundException: org.eclipse.persistence.jaxb.JAXBContextFactory]
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:278)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:397)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:721)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:662)
at gert.Main.test(Main.java:14)
... 5 more
Caused by: java.lang.ClassNotFoundException: org.eclipse.persistence.jaxb.JAXBContextFactory
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
at javax.xml.bind.ServiceLoaderUtil.nullSafeLoadClass(ServiceLoaderUtil.java:122)
at javax.xml.bind.ServiceLoaderUtil.safeLoadClass(ServiceLoaderUtil.java:155)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:276)
... 9 more
The 2 above are done directly from the command line.
BUT
When I uncomment the dependencies in the pom.xml
of the cristina
project and I do a maven install and run the project from eclipse, java 9 works. So it seems that eclipse also takes the maven dependencies into consideration when running a project.
Question
When the dependencies are in the gert
project and only used by the gert
project why does the cristina
project throw an exception when running it with Java 9?