If you keep getting the main class not found error in your Java project for no apparent reason, don't worry, you're not alone.

As one of the most unforeseeable and spontaneous errors, thanks to JVM's (Java Virtual Machine) tendency to stick to a default classpath, the 'main class not found' issue is something that haunts amateurs and professionals alike.

But this issue is actually less intimidating than it seems to be. Read on to find out how you can get rid of this error once and for all.

Why Was the Main Class Not Found?

Before we try to understand how and why JVM was not able to find the main class, we need to understand the concept of Classpath in Java.

What Is Classpath?

The classpath is the file path that the Java runtime environment searches for classes and other resource files. It can be set using either the -classpath option when executing a program or by setting the system CLASSPATH environment variable.

As the name suggests, it's simply a file path where the .class files can be found in a JDK package or directory.

When the JVM is unable to locate the main class, it’s often because it's looking for the corresponding .class files in the wrong classpath. Of course, the way to rectify this problem is to manually specify the classpath by either using packages or specifying the classpath.

At this point, if you'd like to refresh your memory of Java classes, check out our guide for creating classes in Java.

Using Packages

Let’s create a class called Test. Place it in a package called testPackage. Packages are used in Java in order to group similar classes together or provide a unique namespace for classes.

In this simple example, using a package will help you visualise how Java’s classpath works. In your file manager application, a package is represented as an independent folder.

            package testPackage;
public class Test {
    public static void main(String args[]) {
        System.out.println("File successfully found!");
        }
     }

    

Now, open a new terminal and make sure your working directory is the same as the one that contains the package folder. You can change the working directory by using the cd command on any operating system.

Compile Test.java by running the following command:

            package testPackage;
javac testPackage/Test.java

    

This will save the compiled binary file (the .class file) in testPackage.

To run the compiled class, you need to type in the fully qualified class name in the command line. A Java class’ fully qualified name refers to its name prefixed with its package name. In this case, this should look something like this:

        java testPackage.Test

This way of calling class files also ensures that you can call executables from different packages from the same working directory. All you have to do is modify the fully qualified class name.

In more advanced implementations, we recommend that you create separate subfolders for your classes and source files to better manage files within the package.

Manually Specifying Classpath

The recommended way to manage your java files is to create separate directories for source files and classes. If you’re working on a project, it’s likely that you’re already doing this.

Conventionally, the directory with source files is labelled as src and the one with .class files is labelled as classes. This is also a way to ensure that the likelihood of JVM not finding the main class is reduced significantly, owing to the properly structured directory.

If we use this method, this is what the directory structure will look like before compiling:

        |---myFolder
| |---src
| |---testPackage
| |---Test.java
|
| |---classes

Every indent in the above illustration corresponds to one level of the file hierarchy that your project should follow.

To compile this, make sure your working directory is myFolder. Now, type the following command:

            javac -d classes src/testPackage/Test.java

    

The .class executable should be saved in myFolder/classes/testPackage. Accordingly, the file directory structure looks something like this:

        |---myFolder
| |---src
| |---testPackage
| |---Test.java
|
| |---classes
| |---testPackage
| |---Test.class

To run the .class file, run the Java command with the fully qualified class name and specify the local classpath. Every path is declared relative to the working directory, which in this case is myFolder.

        java -classpath classes testPackage

Running this command should give you the desired output. But, why is so much reorganization necessary to solve a simple error?

The Importance of Organizing Files in Java

The very reason why the ‘Could Not Find or Load Main Class’ is thrown is because JVM was not able to find where your .class files were being stored.

The easiest way to resolve this error is to control where the .class files are stored and explicitly tell JVM to look there. This is made possible by organising your source files and executables separately and controlling everything from a working directory.

As you start adding constructs such as inheritance to your project, the file system complexity is bound to increase manifold. In such projects or even those where the use of JAR files or custom libraries is required, the simple practice of segregating and managing files can save you countless hours of troubleshooting and debugging.

To read more about how classpath works in Java and the numerous things you can control when it comes to running your code, you can also take a look at Oracle’s detailed and user-friendly reference.