0

I know it's a common question, but I have read all the other answers and couldn't find a solution. I am trying to understand the Java classpath, but I run into the Error: Could not find or load main class Hello when I try to specify an external library.

I started with this simple program, which resides directly in my home directory:

import java.util.*;

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

This compiles and runs just fine...

[user ~]> ls -l
Hello.java
[user ~]> javac Hello.java
[user ~]> ls -l
Hello.java
Hello.class
[user ~]> java Hello
Hello world

...which tells me that the classpath environment variable is set correctly (because it finds the java.util package).

Yet when I try to import a random 3rd party package and specify its location in the -classpathI get the error:

[user ~]> cat Hello.java
import java.util.*;
import org.apache.commons.lang3.time.*;

public class Hello {
    public static void main(String[] args) {
        StopWatch sw = new StopWatch();
        Date date = new Date();
        System.out.println("Hello world");
    }
}
[user ~]> ls .m2/repository/org/apache/commons/commons-lang3/3.3.1
commons-lang3-3.3.1.jar
[user ~]> javac -classpath ~/.m2/repository/org/apache/commons/commons-lang3/3.3.1/commons-lang3-3.3.1.jar Hello.java
[user ~]> java -classpath ~/.m2/repository/org/apache/commons/commons-lang3/3.3.1/commons-lang3-3.3.1.jar Hello
Error: Could not find or load main class Hello

Could someone give me an idea what I'm doing wrong here?

gmolau
  • 2,815
  • 1
  • 22
  • 45
  • When not explicity defining the classpath, the compiler will search in the current folder. When you defined classpath for the external JAR, you sicceeded in telling the compiler where it is, but then it ignored the current directory. – Tim Biegeleisen Feb 18 '17 at 15:41

1 Answers1

1

First, java.util classes are part of the JRE itself, and are thus automatically available, whatever the classpath is.

The first example works fine because you're not specifying any classpath, and the default one (which is just ., i.e. the current directory) is thus used.

The second example specifies a classpath, but doesn't include . (the current directory) in it, so the commons-lang classes are available at runtime, but not your Hello class. Use

java -classpath .:~/.m2/repository/org/apache/commons/commons-lang3/3.3.1/commons-lang3-3.3.1.jar Hello

Also, in the future:

  • don't ever, ever put a class in the default package
  • create a real project structure, containing
    • a root directory
    • a source directory containing the .java files, properly organized in a package structure
    • a classes directory, containing the compiled .class files, that you can just clear when you want to recompile everything from scratch

The next step would of course to use Gradle or Maven as a build tool, and follow their recommended project layout.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Ok, that is really disappointing, I thought the classpath would always include the current directory automatically. I am normally using Maven and its recommended project structure, I just set this up as a simple experiment to look under the hood. Thanks for your answer. – gmolau Feb 18 '17 at 15:50