What is Java classpath?
Tags: java, codenewbie
Published: 2021-06-12 12:48:57

Have you ever read a tutorial, or someone in a forum, or in Discord, say "make sure it's on the classpath" and don't have the foggiest idea what they are talking about? Well it's your lucky day because we are going to figure out what the mysterious Java classpath is.

> There is a TLDR at the bottom, if you'd like the concise answer

##How the terminal finds and runs programs
First of all, you are going to be running a lot of your Java programs from a terminal. You've probably already used a number of commands in the terminal already, one such example is -

```cmd
D:\Coding\Dev\Classpath example demo>echo Hello, World
Hello, world
```  
What is happening here? We're using a program called `echo` to print the line of text "Hello, World". We are calling the program by typing its name then some text, but how does the computer know we have a program called "echo" and how does it find it? There is something called an *environment variable* which stores a semi-colon separated list of paths to programs, one is aptly called `Path`. 

Lets have a look at my `Path` using `echo`

```
D:\Coding\Dev\Classpath example demo>echo %Path%
C:\Python38\Scripts\;C:\Python38\;C:\Program Files\Java\jdk-13.0.2\bin;
C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\ProgramData\Oracle\Java\javapath;
C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;
C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;
...
C:\Program Files\Java\jdk-13.0.2\bin;
... 
```
> Wrapping a string with `%` symbols identifies it as a variable

I've omitted quite a bit here, but you can see these are directory paths within your computer to the location of a program file. The command terminal will check your `Path` variable's *paths* when you type a command and see if it can find a matching program with that name, then it will run the program with any options you added, like the text "Hello, world". 

##Making and running a simple `.java` program
So now we know how the computer finds a program, and we can see from the list `C:\Program Files\Java\jdk-13.0.2\bin`, this is the location of the `java` program. This is how we run our Java code, lets make a simple program and run it. Let's stick to the old faithful, slightly modified, it will output "Hello, world, from Main class" to the terminal.

```java
public class Main {
    public static main(String[] args) {
        System.out.println("Hello, world, from Main class");
    }
}
```
Now we have a program, lets use `java` to run it.
```
D:\Coding\Dev\Classpath example demo>java Main
Error: Could not find or load main class Main
Caused by: java.lang.ClassNotFoundException: Main
```
Huh, something went wrong. It seems `java` couldn't find our class called "Main". Well, there's a hint in the error, `java` is looking for a `.class` file. A class file is a compiled version of our `.java` file, which the computer can understand and execute. If we look at the [documentation](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html#BABDJJFI) for `java` (always a good idea to read the doc's!) we can see that the structure for a command is `java [options] classname [args]`. So how do we get a `.class` file? We can use another program called `javac`.

`javac`, short for Java Compiler, will compile your `.java` into a `.class` file. Lets give it a go.
```
D:\Coding\Dev\Classpath example demo>javac Main.java
D:\Coding\Dev\Classpath example demo>dir
 Volume in drive D is Data
 Volume Serial Number is 64F6-4376

 Directory of D:\Coding\Dev\Classpath example demo

26/05/2021  15:42    <DIR>          .
26/05/2021  15:42    <DIR>          ..
26/05/2021  15:42               414 Main.class
26/05/2021  14:07               162 Main.java
               2 File(s)            576 bytes
               2 Dir(s)  320,053,022,720 bytes free

```
> dir - lists out all the folders and files in the current directory

You can see here there is a new file created `Main.class`. We can now run this file with `java`.

```
D:\Coding\Dev\Classpath example demo>java Main
Hello, world, from Main class
```
##Complicating matters
So this is great. What's the issue with "classpath" then? Lets move our `Main.class` and try again to run the program.

```
D:\Coding\Dev\Classpath example demo>mkdir SubFolder

D:\Coding\Dev\Classpath example demo>move Main.class SubFolder
        1 file(s) moved.

D:\Coding\Dev\Classpath example demo>tree /F
Folder PATH listing for volume Data
Volume serial number is 64F6-4376
D:.
│   Main.java
│
└───SubFolder
        Main.class

```
> `tree /F` prints a folder and file hierarchy to the console

Here we have created a new sub-folder  called "SubFolder" and placed `Main.class` within. Running the program as before, this happens -

```
D:\Coding\Dev\Classpath example demo>java Main
Error: Could not find or load main class Main    
Caused by: java.lang.ClassNotFoundException: Main
```
We've lost our `Main.class`! So how do we tell `java` where it is? We put it on the classpath! Lets do that -

```
D:\Coding\Dev\Classpath example demo>java -cp ./SubFolder Main 
Hello, world, from Main class
```
> `.` before `/SubFolder` means the path is relative to where we
> are in the file system

What we just did is set the classpath with the `-cp` option. This tells the JVM where to find the `.class` file, and it now runs! 

##A more "real world" example
Ok, so everything is great, right? Well, right now. In real applications there is a lot of classes and a lot of dependencies. Dependencies are code files which your code *depends* on, and are usually kept in a library of related files you download and add to your project. These are normally kept outside of your project file structure, usually in a some type of container like a `.jar` file. So, lets look at a practical example, when a class is out in another folder on it's on, simulating being a dependency.

First we will create our new java file and update `Main.java` with some code that utilises the new class -

```java
public class ExternalClazz {
   
    public void printText() {
        System.out.println("Hi from elsewhere");
    } 
}
```
```java
public class Main {

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

        ExternalClazz externalClazz = new ExternalClazz();
        externalClazz.printText();
    }
}
```
and compile it, along with `Main.java` to update that code -
```
javac ExternalClazz.java
javac Main.java
```
> In fact we could have just used `javac Main.java`, and it would
> have compiled both files, as it will parse through `Main.java`
> and discover it needs to compile `ExternalClazz.java` for 
> `Main.java` to work correctly

This creates `ExternalClazz.class` in our current directory. We can add it to a `.jar` file and move it to "Dependency" folder -
```
D:\Coding\Dev\Classpath example demo>jar cvf MyJar.jar ExternalClazz.class
added manifest
adding: ExternalClazz.class(in = 417) (out= 292)(deflated 29%)

D:\Coding\Dev\Classpath example demo>move MyJar.jar Dependency
        1 file(s) moved.
```
Now the file structure looks like this -
```
D:.
│   ExternalClazz.java
│   Main.java
│
├───Dependency
│       MyJar.jar
│
└───SubFolder
        Main.class
```
So now we have our `Main.class` in a sub-folder, and our `main` method has some code which is dependent on a `.class` which is in a `.jar` file, also in another folder. How do we run this?
```
D:\Coding\Dev\Classpath example demo>java -cp ./Dependency/MyJar.jar;./SubFolder Main
Hello, world, from Main class
Hi from elsewhere
```
We have used the argument `-cp` to define the classpath, but this time we've used multiple paths. One points to the `.jar` file, and the other to where our `Main.class` is. Does this remind you of anything? That's right, it's the same as the `Path` environment variable, a list of `;` separated paths to target locations.

##Developer tools
Now, generally we all use IDEs to make our projects, like InteliJ IDEA, VSCode or Eclipse. Normally these integrated development environments will handle setting the classpath and running the programming, but this is still good knowledge to have and understand. 

Here in InteliJ IDEA is where the classpath is set for your project, in run/debug configurations, "Use classpath of module" -
![Setting classpath in InteliJ IDEA](https://blog.jetbrains.com/wp-content/uploads/2017/10/idea-Screen-Shot-2017-10-09-at-08.58.33.png)

and in VSCode, after installing the Java extension -
![Setting classpath in VSCode](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2r7dh6p8zz96cxslt47e.jpg)

IDEs are very powerful tools and handle a lot of the *under the bonnet* configuration, but should we ever run into issues with these configs we'll already be prepared. There are other tools called "build" tools such as Maven and Gradle, which handle pointing JVM to the right places, which is totally out of the scope of this blog post, but they are incredibly useful and you should spend some time to learn them, too.

##TLDR;
The Java classpath is a collection of folder or file paths that tell the Java Virtual Machine where the compiled code is which is to be executed in your program. When it can't find the `.class` files your program cannot run, as the JVM can't find it's instructions. "Putting it on the classpath" means making sure compiled java files are in a folder the classpath knows. Otherwise, you will need to specify that folder when you run your java program. Classpath will check the current folder by default, if it can't find the `.class` files you need to specify the path with the `-cp` or `-classpath` argument, more than one path can be separated with a `;`. You can point to `.class` files or `.jar` files.

I hope this is helpful, please let me know if I missed anything 😃

Header image photo by <a href="https://unsplash.com/@alschim?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Alexander Schimmeck</a> on <a href="https://unsplash.com/s/photos/signpost?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>