Call "java -jar MyFile.jar" with additional classpath option

toom picture toom · Apr 10, 2013 · Viewed 94.3k times · Source

I created a jar file containing all my compiled stuff. Additionally my ant build script copies the required libs into a subfolder "libs". The structure looks like this:

MyProgram.jar
libs/

So when I try to run my program now I get the following error:

java -cp ".:/home/user/java/MyProgram/jar/libs" -jar MyProgram.jar
java.lang.ClassNotFoundException: org.postgresql.Driver
    at java.net.URLClassLoader$1.run(URLClassLoader.java:217)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:186)
    at database.PostgresQL.getConnection(PostgresQL.java:38)
    at recommender.dao.Creative2IdxDAO.createCreatives2Idx(Creative2IdxDAO.java:19)
    at main.Main.calculateCorrelationMatrix(Main.java:51)
    at main.Main.main(Main.java:28)
java.lang.NullPointerException
    at recommender.dao.Creative2IdxDAO.createCreatives2Idx(Creative2IdxDAO.java:25)
    at main.Main.calculateCorrelationMatrix(Main.java:51)
    at main.Main.main(Main.java:28)

Why does this happen?

Answer

Ian Roberts picture Ian Roberts · Apr 10, 2013

You use either -jar or -cp, you can't combine the two. If you want to put additional JARs on the classpath then you should either put them in the main JAR's manifest and then use java -jar or you put the full classpath (including the main JAR and its dependencies) in -cp and name the main class explicitly on the command line

java -cp 'MyProgram.jar:libs/*' main.Main

(I'm using the dir/* syntax that tells the java command to add all .jar files from a particular directory to the classpath. Note that the * must be protected from expansion by the shell, which is why I've used single quotes.)

You mention that you're using Ant so for the alternative manifest approach, you can use ant's <manifestclasspath> task after copying the dependencies but before building the JAR.

<manifestclasspath property="myprogram.manifest.classpath" jarfile="MyProgram.jar">
  <classpath>
    <fileset dir="libs" includes="*.jar" />
  </classpath>
</manifestclasspath>

<jar destfile="MyProgram.jar" basedir="classes">
  <manifest>
    <attribute name="Main-Class" value="main.Main" />
    <attribute name="Class-Path" value="${myprogram.manifest.classpath}" />
  </manifest>
</jar>

With this in place, java -jar MyProgram.jar will work correctly, and will include all the libs JAR files on the classpath as well.