Why doesn't java honour the class path when executing a jar file with the -jar switch?

2.6k views Asked by At

This works:

$ java -cp ".:/PATH/TO/RXTXcomm.jar:./jobexftp.jar" -Djava.library.path=/usr/lib/jni com.lhf.jobexftp.StandAloneApp
JObexFTP 2.0 beta (15/10/2010)
Java Obex File Transfer Protocol application and library
Developed under/using 100% free software.
For more information access: http://www.lhf.ind.br/jobexftp/

Usage: jobexftp <serialPort> [<commands>] [<options>]
...

This doesn't:

$ java -cp ".:/PATH/TO/RXTXcomm.jar" -Djava.library.path=/usr/lib/jni -jar jobexftp.jar
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: gnu/io/NoSuchPortException
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
    at java.lang.Class.privateGetMethodRecursive(Class.java:3048)

I found the class name to execute (for the first example) in the META-INF/MANIFEST.MF file, inside the jar:

Main-Class: com.lhf.jobexftp.StandAloneApp

Why does executing the jar file, with the -jar switch seem to cause Java to ignore the classpath and fail to find the gnu/io/NoSuchPortException class in RXTXcomm.jar?


On an older machine, running Java 1.6, I can execute the jar file without needing a classpath. How does this work?

$ env | grep CLASS
$ env | grep JAVA
$ java -jar jobexftp.jar 
JObexFTP 2.0 beta (15/10/2010)
Java Obex File Transfer Protocol application and library
Developed under/using 100% free software.
For more information access: http://www.lhf.ind.br/jobexftp/

Usage: jobexftp <serialPort> [<commands>] [<options>]
...

The reason it worked on the old machine is that it had a copy of RXTXcomm.jar in /usr/lib/jvm/java-6-sun-1.6.0.21/jre/lib/ext/.

$ ls -lA /usr/lib/jvm/java-6-sun-1.6.0.21/jre/lib/ext/RXTXcomm.jar
-rwxr-xr-x 1 root root 137764 2011-02-17 16:58 /usr/lib/jvm/java-6-sun-1.6.0.21/jre/lib/ext/RXTXcomm.jar

Making a new ext directory in /usr/lib/jvm/java-8-oracle/jre and copying RXTXcomm.jar into it doesn't get rid of the error on Java 1.8.

3

There are 3 answers

2
aioobe On BEST ANSWER

The -jar switch is intended to launch the jar as a self contained program. As stated in the java man page:

When you use the -jar option, the specified JAR file is the source of all user classes, and other class path settings are ignored.

To provide a classpath, use the Class-Path entry in the manifest file.

Further reading: The Java™ Tutorials: Adding Classes to the JAR File's Classpath

0
taotao On

you can modify the META-INF/MANIFEST.MF file and add Class-Path entry.

in maven build system you can config it like below

<plugin>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.3</version>
    <configuration>
        <archive>
            <manifest>
                <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                <addClasspath>true</addClasspath>
                <mainClass>your.main.Class</mainClass>
            </manifest>
            <manifestEntries>
                <Class-Path>./config/</Class-Path>
            </manifestEntries>
        </archive>
    </configuration>
</plugin>

from the man java we can confirmed this issue When you use this option, the JAR file is the source of all user classes, and other user class path settings are ignored.

0
Ricardo Guilherme Schmidt On

You need to copy also the .so/.dll to the jni folder. Ubuntu RXTX didn't used to work well. Check out this