I have written the following Java source file (Hello.java):
package com;
public class Hello {
public static void main(String[] args) {
System.out.println("Hello!");
}
}
I save this to C:/tmpjava/Hello.java.
From the command line, I navigate to that directory and run javac Hello.java. Then I run dir:
Hello.classHello.java
Then, from the same directory that I just ran javac from, I run java Hello.class and get:
Exception in thread "main" java.lang.NoClassDefFoundError: Hello/class
Caused by: java.lang.ClassNotFoundException: Hello.class
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
Could not find the main class: Hello.class. Program will exit.
What’s going on here?!? How can javac run fine, but not java?
Your class
Hellobelongs to the packagecom. So the fully qualified name of your class iscom.Hello. When you invoke a program using java on the command-line, you should supply the fully-qualified class name of the class that contains yourmainmethod and omit the .class, like so:The java program needs this fully-qualified class name to understand which class you are referring to.
But you have another problem. The java program locates packages, sub-packages, and the classes that belong to them using the filesystem. So if you have a package structure like
com.Hello, the java program expects to find a class file named Hello.class in a directory named com, like this: com/Hello.class. In fact you can observe this behavior in theExceptionthat you see; you’ve incorrectly used Hello.class, which java is interpreting as a package namedHello, and a class namedclass, and is looking for the directory structure Hello/class:But the compiler javac doesn’t set up this directory structure by default. See the documentation for javac, but the important bit is this: when you do your compiles, you can specify a destination directory using the
-dflag:The last bit in bold is the source of much confusion for beginners, and is part of your own problem.
So you have two alternatives:
In your case, it’s fine if you supply the current directory as the destination directory, like so (the period
.means current directory):If you invoke the compiler like this, it will create the com directory for you, and put your compiled class file in it, the way that the java program expects to find it. Then when you run java as above, from c:\tmpJava, your program should execute.
You could set up your source code using a directory structure that mirrors your package structure: put your source file Hello.java inside a directory called com, in your case: c:\tmpJava\com\Hello.java. Now, from c:\tmpJava you can run your javac compile like this:
You haven’t supplied the
-dflag, but that’s fine, because you’ve created the directory structure yourself, and quoting again from the documentation above:Again, when you run java as above, your program should execute.
Note that this second alternative is one that is commonly employed by java programmers: the source code files are organized in a directory structure that mirrors the package structure.
In this explanation we’ve ignored the concept of the classpath. You’ll also need to understand that to write java programs, but in your case of simply compiling a program in the current directory – if you follow one of the two alternatives above when compiling your class – you can get away without setting a classpath because, by default, the java program has the current directory as a classpath. Another quote, this one from the documentation for java:
Note that when you use an IDE like Eclipse to run your java code, this is mostly handled for you, but you’ll still run into classpath issues.