What is a classpath and how do I set it?

404.9k Views Asked by At

I was just reading this line:

The first thing the format() method does is load a Velocity template from the classpath named output.vm

Please explain what was meant by classpath in this context, and how I should set the classpath.

11

There are 11 best solutions below

6
On BEST ANSWER

When programming in Java, you make other classes available to the class you are writing by putting something like this at the top of your source file:

import org.javaguy.coolframework.MyClass;

Or sometimes you 'bulk import' stuff by saying:

import org.javaguy.coolframework.*;

So later in your program when you say:

MyClass mine = new MyClass();

The Java Virtual Machine will know where to find your compiled class.

It would be impractical to have the VM look through every folder on your machine, so you have to provide the VM a list of places to look. This is done by putting folder and jar files on your classpath.

Before we talk about how the classpath is set, let's talk about .class files, packages, and .jar files.

First, let's suppose that MyClass is something you built as part of your project, and it is in a directory in your project called output. The .class file would be at output/org/javaguy/coolframework/MyClass.class (along with every other file in that package). In order to get to that file, your path would simply need to contain the folder 'output', not the whole package structure, since your import statement provides all that information to the VM.

Now let's suppose that you bundle CoolFramework up into a .jar file, and put that CoolFramework.jar into a lib directory in your project. You would now need to put lib/CoolFramework.jar into your classpath. The VM will look inside the jar file for the org/javaguy/coolframework part, and find your class.

So, classpaths contain:

  • JAR files, and
  • Paths to the top of package hierarchies.

How do you set your classpath?

The first way everyone seems to learn is with environment variables. On a unix machine, you can say something like:

export CLASSPATH=/home/myaccount/myproject/lib/CoolFramework.jar:/home/myaccount/myproject/output/

On a Windows machine you have to go to your environment settings and either add or modify the value that is already there.

The second way is to use the -cp parameter when starting Java, like this:

java -cp "/home/myaccount/myproject/lib/CoolFramework.jar:/home/myaccount/myproject/output/"  MyMainClass

A variant of this is the third way which is often done with a .sh or .bat file that calculates the classpath and passes it to Java via the -cp parameter.

There is a "gotcha" with all of the above. On most systems (Linux, Mac OS, UNIX, etc) the colon character (:) is the classpath separator. On Windows the separator is the semicolon (;)

So what's the best way to do it?

Setting stuff globally via environment variables is bad, generally for the same kinds of reasons that global variables are bad. You change the CLASSPATH environment variable so one program works, and you end up breaking another program.

The -cp is the way to go. I generally make sure my CLASSPATH environment variable is an empty string where I develop, whenever possible, so that I avoid global classpath issues (some tools aren't happy when the global classpath is empty though - I know of two common, mega-thousand dollar licensed J2EE and Java servers that have this kind of issue with their command-line tools).

0
On

Classpath is an environment variable of system. The setting of this variable is used to provide the root of any package hierarchy to java compiler.

0
On

The classpath is a list of one or more files or directories for the Java Virtual Machine to search when it is trying to find all of the various user classes that a Java program depends on for executing. This is a Java VM mechanism and is different from the search path used by the shell for locating an executable file.

The shell finds the locations for the java and javac commands using the PATH environment variable. The java command uses the CLASSPATH environment variable or the classpath specified with the -cp option to locate user Java classes whose location it doesn't know.

In addition to the use of CLASSPATH, the Java Virtual Machine will also look for files it needs using the environment variable JAVA_HOME which points to the location of the Java VM components, libraries, etc. Under Linux this is typically a specific JDK version directory hierarchy beneath the pathname /usr/lib/jvm.

See also How is import done in Java? which discusses the import directive as well as Help with packages in java - import does not work which discusses the package directive.

This document provides details though it is a bit dated as the Extensions mechanism was removed. Oracle Java Documentation: How Classes are Found. See the JDK-21 Java VM Specification with Chapter 5. Loading, linking, and Initializing for exhaustive details.

The Java launcher, java, initiates the Java virtual machine. The virtual machine searches for and loads classes in this order:

  • Bootstrap classes - Classes that comprise the Java platform, including the classes in rt.jar and several other important jar files.
  • Extension classes - Classes that use the Java Extension mechanism. These are bundled as .jar files located in the extensions directory.
  • User classes - Classes defined by developers and third parties that do not take advantage of the extension mechanism. You identify the location of these classes using the -classpath option on the command line (the preferred method) or by using the CLASSPATH environment variable. (See Setting the Classpath for Windows or Unix.)

In effect, these three search paths are joined to form a simple class path. This is similar to the "flat" class path previously used, but the current model has some important differences:

  • It is relatively difficult to accidentally "hide" or omit the bootstrap classes.
  • In general, you only have to specify the location of user classes. Bootstrap classes and extension classes are found "automatically".
  • The tools classes are now in a separate archive (tools.jar) and can only be used if included in the user class path (to be explained shortly).

The above document then has this description about finding user classes:

User classes are classes which build on the Java platform. To find user classes, the launcher refers to the user class path -- a list of directories, JAR archives, and ZIP archives which contain class files.

A class file has a subpath name that reflects the class's fully-qualified name. For example, if the class com.mypackage.MyClass is stored under /myclasses, then /myclasses must be in the user class path and the full path to the class file must be /myclasses/com/mypackage/MyClass.class. If the class is stored in an archive named myclasses.jar, then myclasses.jar must be in the user class path, and the class file must be stored in the archive as com/mypackage/MyClass.class.

The user class path is specified as a string, with a colon (:) separating the class path entries on Solaris, and a semi-colon (;) separating entries on Microsoft Windows systems. The java launcher puts the user class path string in the java.class.path system property. The possible sources of this value are:

  • The default value, ".", meaning that user class files are all the class files in the current directory (or under it, if in a package).
  • The value of the CLASSPATH environment variable, which overrides the default value.
  • The value of the -cp or -classpath command line option, which overrides both the default value and the CLASSPATH value.
  • The JAR archive specified by the -jar option, which overrides all other values. If this option is used, all user classes must come from the specified archive.

See also this explanation about the different types of class loaders: All about Java class loaders

You can either use the CLASSPATH environment variable to specify the list of files and/or directories or you can use the -cp option with the java command to specify the list. If you use the -cp option then the CLASSPATH environment variable is ignored.

Using the CLASSPATH environment variable for the classpath is discouraged and there are good reasons for not using the CLASSPATH environment variable. However it can be useful and convenient when a directory is set up with user classes that are commonly used. An example from my recent experience was the .jar file for a database engine.

The list of files or directories use either a colon (:) on Linux or a semicolon (;) on Windows to separate each item in the list.

You can use a wildcard in a directory entry to include all of the files in that directory as in /usr/share/java/* however you do need to be aware that your shell may expand the wildcard so typically you will need to use quotes around a classpath that uses wildcards.

The rest of this post is written for Linux as that is what I can test on.

If you want to use the CLASSPATH environmental variable with some additional files and/or directories on Linux then you can specify the -cp option and include the CLASSPATH environment variable as well. If you want to search your specific files and/or directories first then search the rest of the classpath, put the $CLASSPATH variable at the end of your list. For example on Linux using the colon separator (and remember the quotes):

  • `java -cp "$CLASSPATH:/one/two/foo.jar" mypgm.java will search the addition last
  • `java -cp "/one/two/foo.jar:$CLASSPATH" mypgm.java will search the addition first

To check for a CLASSPATH environment variable and its value on Linux use the echo command as in echo "$CLASSPATH" and on Windows use the echo command with the Windows style of environment variable echo "%CLASSPATH%". The double quotes are used in case the CLASSPATH environment variable listing contains an item that is using wildcard characters such as the asterisk (*) as /usr/share/* though it appears Windows is pretty lax about wildcard expansion.

You can set the CLASSPATH environment variable at the command line or you can have a setting in your user profile which either creates, replaces, or modifies the CLASSPATH environment variable. How this is done depends on the user shell and how environmental variables are set and what files are processed at sign-in for setting up your shell environment.

0
On

Static member of a class can be called directly without creating object instance. Since the main method is static Java virtual Machine can call it without creating any instance of a class which contains the main method, which is start point of program.

0
On

CLASSPATH is an environment variable (i.e., global variables of the operating system available to all the processes) needed for the Java compiler and runtime to locate the Java packages used in a Java program. (Why not call PACKAGEPATH?) This is similar to another environment variable PATH, which is used by the CMD shell to find the executable programs.

CLASSPATH can be set in one of the following ways:

CLASSPATH can be set permanently in the environment: In Windows, choose control panel ⇒ System ⇒ Advanced ⇒ Environment Variables ⇒ choose "System Variables" (for all the users) or "User Variables" (only the currently login user) ⇒ choose "Edit" (if CLASSPATH already exists) or "New" ⇒ Enter "CLASSPATH" as the variable name ⇒ Enter the required directories and JAR files (separated by semicolons) as the value (e.g., ".;c:\javaproject\classes;d:\tomcat\lib\servlet-api.jar"). Take note that you need to include the current working directory (denoted by '.') in the CLASSPATH.

To check the current setting of the CLASSPATH, issue the following command:

> SET CLASSPATH

CLASSPATH can be set temporarily for that particular CMD shell session by issuing the following command:

> SET CLASSPATH=.;c:\javaproject\classes;d:\tomcat\lib\servlet-api.jar

Instead of using the CLASSPATH environment variable, you can also use the command-line option -classpath or -cp of the javac and java commands, for example,

> java –classpath c:\javaproject\classes com.abc.project1.subproject2.MyClass3
0
On

The classpath in this context is exactly what it is in the general context: anywhere the VM knows it can find classes to be loaded, and resources as well (such as output.vm in your case).

I'd understand Velocity expects to find a file named output.vm anywhere in "no package". This can be a JAR, regular folder, ... The root of any of the locations in the application's classpath.

0
On

The classpath is the path where the Java Virtual Machine look for user-defined classes, packages and resources in Java programs.

In this context, the format() method load a template file from this path.

2
On

Think of it as Java's answer to the PATH environment variable - OSes search for EXEs on the PATH, Java searches for classes and packages on the classpath.

5
On

The classpath is one of the fundamental concepts in the Java world and it's often misunderstood or not understood at all by java programmes, especially beginners.

Simply put, the classpath is just a set of paths where the java compiler and the JVM must find needed classes to compile or execute other classes.

Let's start with an example, suppose we have a Main.java file thats under C:\Users\HP\Desktop\org\example,

package org.example;

public class Main {
    public static void main(String[] args) {
    
            System.out.println("Hello world");
            
    }
}

And Now, suppose we are under C:\ directory and we want to compile our class, Its easy right, just run:

javac .\Users\HP\Desktop\org\example\Main.java


Now for the hard question, we are in the same folder C:\ and we want to run the compiled class.

Despite of what you might think of to be the answer, the right one is:

java -cp .\Users\HP\Desktop org.example.Main 

I'll explain why, first of all, the name of the class that we want ro tun is org.exmaple.Main not Main, or Main.class or .\users\hp\desktop\org\example\Main.class ! This is how things works with classes declared under packages.

Now, we provided the name of the class to the JVM (java command in this case), But how it (JVM) will know where to find the .class file for the Main class? Thats where the classpath comes into picture. Using -cp flag (shortcut for -classpath), we tell the JVM that our Main.class file will be located at C:\users\hp\Desktop.. In fact, not really, we tell it to just go to the Desktop directory, and, because of the name of the class org.example.Main, the JVM is smart and it will go from Desktop to org directory, and from org to example directory, searching for Main.class file, and it will find it and it will kill it, I mean, it will run it :D .

Now lets suppose that inside the Main class we want to work with another class named org.apache.commons.lang3.StringUtils and the latter is located in a jar file named commons-lang3-3.10.jar thats inside C:\Users\HP\Downloads. So Main.java will look like this now:

package org.example;

import org.apache.commons.lang3.StringUtils;

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello world");
        System.out.println(StringUtils.equals("java", "java")); //true
    }   
}


How to compile the Main.java if we are always inside C:\ ? The answer is:

javac -cp .\Users\HP\Downloads\commons-lang3-3.10.jar .\Users\HP\Desktop\org\example\Main.java
  • .\Users\HP\Desktop\org\example\Main.java is because our .java file is there in the filesystem.

  • -cp .\Users\HP\Downloads\commons-lang3-3.10.jar is because the java compiler (javac in this case) need to know the location of the class org.apache.commons.lang3.StringUtils, so we provided the path of the jar file, and the compiler will then go inside the jar file and try to find a file StringUtils.class inside a directory org\apache\commons\lang3.


And if we want to run the Main.class file, we will execute:

java -cp ".\Users\HP\Desktop\;.\Users\HP\Downloads\commons-lang3-3.10.jar" org.example.Main
  • org.example.Main is the name of the class.

  • ".\Users\HP\Desktop\;.\Users\HP\Downloads\commons-lang3-3.10.jar" are the paths (separated by ; in Windows) to the Main and StringUtils classes.

1
On

Setting the CLASSPATH System Variable

To display the current CLASSPATH variable, use these commands in Windows and UNIX (Bourne shell): In Windows: C:\> set CLASSPATH In UNIX: % echo $CLASSPATH

To delete the current contents of the CLASSPATH variable, use these commands: In Windows: C:\> set CLASSPATH= In UNIX: % unset CLASSPATH; export CLASSPATH

To set the CLASSPATH variable, use these commands (for example): In Windows: C:\> set CLASSPATH=C:\users\george\java\classes In UNIX: % CLASSPATH=/home/george/java/classes; export CLASSPATH

0
On

For linux users, and to sum up and add to what others have said here, you should know the following:

  1. $CLASSPATH is what Java uses to look through multiple directories to find all the different classes it needs for your script (unless you explicitly tell it otherwise with the -cp override). Using -cp requires that you keep track of all the directories manually and copy-paste that line every time you run the program (not preferable IMO).

  2. The colon (":") character separates the different directories. There is only one $CLASSPATH and it has all the directories in it. So, when you run "export CLASSPATH=...." you want to include the current value "$CLASSPATH" in order to append to it. For example:

    export CLASSPATH=.
    export CLASSPATH=$CLASSPATH:/usr/share/java/mysql-connector-java-5.1.12.jar
    

    In the first line above, you start CLASSPATH out with just a simple 'dot' which is the path to your current working directory. With that, whenever you run java it will look in the current working directory (the one you're in) for classes. In the second line above, $CLASSPATH grabs the value that you previously entered (.) and appends the path to a mysql dirver. Now, java will look for the driver AND for your classes.

  3. echo $CLASSPATH
    

    is super handy, and what it returns should read like a colon-separated list of all the directories, and .jar files, you want java looking in for the classes it needs.

  4. Tomcat does not use CLASSPATH. Read what to do about that here: https://tomcat.apache.org/tomcat-8.0-doc/class-loader-howto.html