Including all the jars in a directory within the Java classpath

Viewed 1207285

Is there a way to include all the jar files within a directory in the classpath?

I'm trying java -classpath lib/*.jar:. my.package.Program and it is not able to find class files that are certainly in those jars. Do I need to add each jar file to the classpath separately?

25 Answers

Using Java 6 or later, the classpath option supports wildcards. Note the following:

  • Use straight quotes (")
  • Use *, not *.jar

Windows

java -cp "Test.jar;lib/*" my.package.MainClass

Unix

java -cp "Test.jar:lib/*" my.package.MainClass

This is similar to Windows, but uses : instead of ;. If you cannot use wildcards, bash allows the following syntax (where lib is the directory containing all the Java archive files):

java -cp "$(printf %s: lib/*.jar)"

(Note that using a classpath is incompatible with the -jar option. See also: Execute jar file with multiple classpath libraries from command prompt)

Understanding Wildcards

From the Classpath document:

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.

Subdirectories are not searched recursively. For example, foo/* looks for JAR files only in foo, not in foo/bar, foo/baz, etc.

The order in which the JAR files in a directory are enumerated in the expanded class path is not specified and may vary from platform to platform and even from moment to moment on the same machine. A well-constructed application should not depend upon any particular order. If a specific order is required then the JAR files can be enumerated explicitly in the class path.

Expansion of wildcards is done early, prior to the invocation of a program's main method, rather than late, during the class-loading process itself. Each element of the input class path containing a wildcard is replaced by the (possibly empty) sequence of elements generated by enumerating the JAR files in the named directory. For example, if the directory foo contains a.jar, b.jar, and c.jar, then the class path foo/* is expanded into foo/a.jar;foo/b.jar;foo/c.jar, and that string would be the value of the system property java.class.path.

The CLASSPATH environment variable is not treated any differently from the -classpath (or -cp) command-line option. That is, wildcards are honored in all these cases. However, class path wildcards are not honored in the Class-Path jar-manifest header.

Note: due to a known bug in java 8, the windows examples must use a backslash preceding entries with a trailing asterisk: https://bugs.openjdk.java.net/browse/JDK-8131329

We get around this problem by deploying a main jar file myapp.jar which contains a manifest (Manifest.mf) file specifying a classpath with the other required jars, which are then deployed alongside it. In this case, you only need to declare java -jar myapp.jar when running the code.

So if you deploy the main jar into some directory, and then put the dependent jars into a lib folder beneath that, the manifest looks like:

Manifest-Version: 1.0
Implementation-Title: myapp
Implementation-Version: 1.0.1
Class-Path: lib/dep1.jar lib/dep2.jar

NB: this is platform-independent - we can use the same jars to launch on a UNIX server or on a Windows PC.

If you really need to specify all the .jar files dynamically you could use shell scripts, or Apache Ant. There's a commons project called Commons Launcher which basically lets you specify your startup script as an ant build file (if you see what I mean).

Then, you can specify something like:

<path id="base.class.path">
    <pathelement path="${resources.dir}"/>
    <fileset dir="${extensions.dir}" includes="*.jar" />
    <fileset dir="${lib.dir}" includes="*.jar"/>
</path>

In your launch build file, which will launch your application with the correct classpath.

For windows quotes are required and ; should be used as separator. e.g.:

java -cp "target\\*;target\\dependency\\*" my.package.Main

macOS, current folder

For Java 13 on macOS Mojave

If all your .jar files are in the same folder, use cd to make that your current working directory. Verify with pwd.

For the -classpath you must first list the JAR file for your app. Using a colon character : as a delimiter, append an asterisk * to get all other JAR files within the same folder. Lastly, pass the full package name of the class with your main method.

For example, for an app in a JAR file named my_app.jar with a main method in a class named App in a package named com.example, alongside some needed jars in the same folder:

java -classpath my_app.jar:* com.example.App

You need to add them all separately. Alternatively, if you really need to just specify a directory, you can unjar everything into one dir and add that to your classpath. I don't recommend this approach however as you risk bizarre problems in classpath versioning and unmanagability.

The only way I know how is to do it individually, for example:

setenv CLASSPATH /User/username/newfolder/jarfile.jar:jarfile2.jar:jarfile3.jar:.

Hope that helps!

Think of a jar file as the root of a directory structure. Yes, you need to add them all separately.

I have multiple jars in a folder. The below command worked for me in JDK1.8 to include all jars present in the folder. Please note that to include in quotes if you have a space in the classpath

Windows

Compiling: javac -classpath "C:\My Jars\sdk\lib\*" c:\programs\MyProgram.java

Running: java -classpath "C:\My Jars\sdk\lib\*;c:\programs" MyProgram

Linux

Compiling: javac -classpath "/home/guestuser/My Jars/sdk/lib/*" MyProgram.java

Running: java -classpath "/home/guestuser/My Jars/sdk/lib/*:/home/guestuser/programs" MyProgram

Order of arguments to java command is also important:

c:\projects\CloudMirror>java Javaside -cp "jna-5.6.0.jar;.\"
Error: Unable to initialize main class Javaside
Caused by: java.lang.NoClassDefFoundError: com/sun/jna/Callback

versus

c:\projects\CloudMirror>java -cp "jna-5.6.0.jar;.\" Javaside
Exception in thread "main" java.lang.UnsatisfiedLinkError: Unable
Related