I have some .jar files in a directory, /home/unix/dfernand/bin/picard/picard-tools-1.106.

But when I add the directory to the PATH and CLASSPATH in my bashrc, java still does not recognize the .jar files and I have no idea why.

I have tried:

>export PATH="/home/unix/dfernand/bin/picard/picard-tools-1.106:$PATH"
> export CLASSPATH=$CLASSPATH:/home/unix/dfernand/bin/picard/picard-tools-1.106
> java -jar AddOrReplaceReadGroups.jar -h
Unable to access jarfile AddOrReplaceReadGroups.jar
>export CLASSPATH="/home/unix/dfernand/bin/picard/picard-tools-1.106:$CLASSPATH"
>java -jar AddOrReplaceReadGroups.jar -h
Unable to access jarfile AddOrReplaceReadGroups.jar

If I do,

[niveum]dfernand> java -jar /home/unix/dfernand/bin/picard/picard-tools-1.106/AddOrReplaceReadGroups.jar -h

it works!, but I want them in my PATH/CLASSPATH

Does anyone have an idea on where is my bug? Do I have to add something else to the PATH/CLASSPATH? Am I using some wrong syntax?


First of all, let's clear up the differences between the two environment variables and their purpose:

PATH is only used by the shell to find executables, for example java or ls or bash. So you don't need to touch that, unless the shell complains something like java: command not found.

CLASSPATH is what Java is using to find the class that is to be loaded. However, it works a bit differently from PATH: it should contain either paths to single .class, .zip or .jar files, or entries with wildcard.

Class paths to the .jar, .zip or .class files. Each classpath should end with a filename or directory depending on what you are setting the class path to:

  • For a .jar or .zip file that contains .class files, the class path ends with the name of the .zip or .jar file.

  • For .class files in an unnamed package, the class path ends with the directory that contains the .class files.

  • For .class files in a named package, the class path ends with the directory that contains the "root" package (the first package in the full package name). Class path entries can contain the basename wildcard character , which is considered equivalent to specifying a list of all the files in the directory with the extension .jar or .JAR. For example, the class path entry foo/ specifies all JAR files in the directory named foo. A classpath entry consisting simply of * expands to a list of all the jar files in the current directory.

A class path entry that contains * will not match class files. To match both classes and JAR files in a single directory foo, use either foo;foo/* or foo/*;foo. The order chosen determines whether the classes and resources in foo are loaded before JAR files in foo, or vice versa.

In this case, you should add the path to the AddOrReplaceReadGroups.jar file to CLASSPATH and then call the class with full package name to start the application. The class being called should be the one that contains the main() method. In this case, I have no idea what that class is, but a wild guess after a google search is that the class to call is net.sf.picard.sam.AddOrReplaceReadGroups.

But when classes are stored in an archive file (a .zip or .jar file) the class path entry is the path to and including the .zip or .jar file. For example, to use a class library that is in a .jar file, the command would look something like this:

C:> java -classpath C:\java\MyClasses\myclasses.jar utility.myapp.Cool

(above quotes from Oracle JavaSE7 docs: Setting the class path, see also Java tutorial on PATH and CLASSPATH for a more complete explanation on their meanings)

So, the command line to use after adding the path to AddOrReplaceReadGroups.jar to CLASSPATH should be:

> java net.sf.picard.sam.AddOrReplaceReadGroups

If that is still too cumbersome, you could put that in either a shell alias or in a script.

Using the script approach, you also could directly put the working command-line you mentioned in the question to the script without touching the environment variable at all. This actually seems to be the preferred way according to the Java documentation, possibly at least partly since putting a lot of stuff in the globally used CLASSPATH will add overhead to class loading since all the (unrelated) places mentioned in the classpath will need to be visited, too, to find the class to be loaded. However, I don't know if this can be an issue with desktop applications unless the classpath is very long with many large archives. Avoiding adding things globally also prevents version conflicts if many archives contain different versions of the same class.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.