Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java can't find main class

Tags:

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.class
  • Hello.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?

like image 379
IAmYourFaja Avatar asked Aug 23 '12 16:08

IAmYourFaja


People also ask

How do you fix Cannot find a class with the main method in java?

The java program needs this fully-qualified class name to understand which class you are referring to. Set the destination directory for class files. The destination directory must already exist; javac will not create the destination directory.

Why could not find or load main class?

Reasons to Occur Error The error generates because the JVM fails to load the main class or package name. There are some other reasons that generate the same error, as follows: The class has been declared in the wrong package. Dependencies missing from the CLASSPATH.

Can a Java class not have main?

Yes, we can execute a java program without a main method by using a static block. Static block in Java is a group of statements that gets executed only once when the class is loaded into the memory by Java ClassLoader, It is also known as a static initialization block.


1 Answers

Your class Hello belongs to the package com. So the fully qualified name of your class is com.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 your main method and omit the .class, like so:

java com.Hello 

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 the Exception that you see; you've incorrectly used Hello.class, which java is interpreting as a package named Hello, and a class named class, and is looking for the directory structure Hello/class:

java.lang.NoClassDefFoundError: 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 -d flag:

-d directory

Set the destination directory for class files. The destination directory must already exist; javac will not create the destination directory. If a class is part of a package, javac puts the class file in a subdirectory reflecting the package name, creating directories as needed. For example, if you specify -d c:\myclasses and the class is called com.mypackage.MyClass, then the class file is called c:\myclasses\com\mypackage\MyClass.class.

If -d is not specified, javac puts the class file in the same directory as the source file.

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:

  1. In your case, it's fine if you supply the current directory as the destination directory, like so (the period . means current directory):

    javac -d . Hello.java 

    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.

  2. 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:

    javac com\Hello.java 

    You haven't supplied the -d flag, but that's fine, because you've created the directory structure yourself, and quoting again from the documentation above:

    If -d is not specified, javac puts the class file in the same directory as the source file.

    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:

-cp classpath

Specify a list of directories, JAR archives, and ZIP archives to search for class files. Class path entries are separated by semicolons (;). Specifying -classpath or -cp overrides any setting of the CLASSPATH environment variable.

If -classpath and -cp are not used and CLASSPATH is not set, the user class path consists of the current directory (.).

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.

like image 112
pb2q Avatar answered Sep 22 '22 18:09

pb2q