Thursday, December 28, 2017

Command line classpath is ignored when using -jar

I was a little shocked today by my discovery of -classpath (-cp) parameter being ignored silently by Java Virtual Machine, when -jar is provided. Look at this (my jar file prints out its working directory and classpath):
java -cp /home:./ -jar ./build/jarclassscanning.jar

Working Directory = /home/me/projects/jarclassscanning
----------------
Classpath elements:
/home/me/projects/jarclassscanning/build/jarclassscanning.jar
----------------

However, if I run the same jar without -jar parameter, here's what it prints out (I've added a couple of directories to -cp just to show that it works):
java -cp /home:./:./build/jarclassscanning.jar my.package.jarclassscanning.BaseClass

Working Directory = /home/me/projects/jarclassscanning
----------------
Classpath elements:
/home/
/home/me/projects/jarclassscanning/
/home/me/projects/jarclassscanning/build/jarclassscanning.jar
----------------

So if your jar uses classes from other jars (or just plain old .class files) and you have to specify classpath, one solution is to add classpath elements to the manifest file - https://docs.oracle.com/javase/tutorial/deployment/jar/downman.html. Keep in mind, however, that you've got to use spaces to separate them, not colons.

Also I've ran into another thing - when specifying jar files as classpath elements using Class-Path field of the manifest file using relative paths, they had to be relative to the location of my jar (the one that I give to JVM using -jar).

So, since my folder structure looked like this:
build
    myjar.jar
jdbc
    postgresql-42.1.4.jar
amqp
    amqp-client-4.2.0.jar
sl4j
    slf4j-simple-1.7.25.jar
    slf4j-api-1.7.25.jar

The Class-Path field of the manifest in myjar.jar ended up looking like this (note the ".."'s):
Class-Path: ../jdbc/postgresql-42.1.4.jar ../amqp/amqp-client-4.2.0.jar ../slf4j/slf4j-simple-1.7.25.jar ../slf4j/slf4j-api-1.7.25.jar

No comments:

Post a Comment