问题
I created a jar file for utility files and added it as a dependency for my main project. When I run mvn install
to build my main project, the correct utility jar is used in my unit tests.
However, when I later run the main project jar using java -jar supervisor.jar
, I get a java.lang.NoClassDefFoundError:
caused by java.lang.ClassNotFoundException: com.seeq.utilities.process.OperatingSystem
.
In my unit tests, OperatingSystem
is used and the tests run fine, so I am assuming that the utility jar is not found when by java when using java -jar
. Is that the issue and how could I fix it?
Exception in thread "main" java.lang.NoClassDefFoundError: com/seeq/utilities/process/OperatingSystem
at com.seeq.supervisor.util.ProcessManager.buildCommand(ProcessManager.java:78)
at com.seeq.supervisor.util.ProcessManager.<init>(ProcessManager.java:27)
at com.seeq.supervisor.Supervisor.start(Supervisor.java:40)
at com.seeq.supervisor.Main.main(Main.java:21)
Caused by: java.lang.ClassNotFoundException: com.seeq.utilities.process.OperatingSystem
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
... 4 more
How I added the dependency in my pom.xml:
<dependency>
<groupId>com.seeq.utilities</groupId>
<artifactId>seeq-utilities</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/../common/libraries/java/seeq-utilities/target/seeq-utilities-1.0.jar</ systemPath>
</dependency>
回答1:
If the not found class is inside a jar, you have to provide the classpath arguments; for example:
java -cp a.jar -jar supervisor.jar
回答2:
If you want to package your jar and its dependencies together into a single executable uber jar, consider using the maven shade plugin http://maven.apache.org/plugins/maven-shade-plugin/. An executable uber jar is convenient because you can run it immediately without extra "java -cp" steps.
An example pom plugin entry for an executable uber jar is show below (also see http://maven.apache.org/plugins/maven-shade-plugin/examples/executable-jar.html).
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.example.MyMainClass/mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
This article also gives a nice overview of what the maven shade plugin can do: http://steveperkins.net/batteries-included-distribution-using-maven-shaded-jars/.
One annoying bug with the maven shade plugin is that it will give duplicate class warnings if you run mvn package
more than once. This issue is still unaddressed as of maven-shader-plugin 2.0: http://jira.codehaus.org/browse/MSHADE-126). To work around the issue, you can re-create your jar from scratch on each invocation, with the following maven-jar-plugin configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<forceCreation>true</forceCreation>
</configuration>
</plugin>
Another issue that you may run into is that re-packaging signed jars invalidates their signatures. If that causes errors for you, see this answer: https://stackoverflow.com/a/6743609/1454388
来源:https://stackoverflow.com/questions/22870361/classnotfoundexception-when-running-executable-jar