The short answer#
Running a Java program takes two commands, and they are run by two different programs:
javac Hello.java // compile: source -> bytecode
java Hello // run: bytecode -> output
javac is the compiler. It reads the text you wrote and, if the text is legal Java, writes a new file called Hello.class. java is the launcher. It starts the Java Virtual Machine and executes that .class file.
if javac complains, your program never ran at all — there is nothing to run. If java complains, your program compiled fine and then went wrong while executing. Those are compile-time and run-time errors, and they are fixed in completely different ways.
Step 1 — javac turns source into bytecode#
Start with one file, Hello.java:
public class Hello {
public static void main(String[] args) {
System.out.println("Hello, world!");
}
}
Before compiling, the directory holds one file. After javac Hello.java, it holds two:
Hello.java 119 bytes your source
Hello.class 417 bytes produced by javac
The .class file is bytecode. It is not the text you wrote, and it is also not machine code for your particular processor. It is an instruction set for an imaginary computer — the JVM — which every real machine then emulates.
You can see that it is a real, structured binary format rather than compressed text. Every .class file ever produced begins with the same four bytes:
ca fe ba be 00 00 00 41
Those first four bytes spell CAFEBABE — the format's magic number, a joke that has been in the file format since 1995. The 41 at the end is hexadecimal for 65, the class-file version written by Java 21.
Step 2 — java runs the bytecode#
Now the second command. Note carefully what you hand it:
java Hello
Hello, world!
You passed Hello, not Hello.class and not Hello.java. The launcher wants a class name, and it works out the filename itself. Typing the extension is probably the single most common first-day error:
$ java Hello.class
Error: Could not find or load main class Hello.class
Caused by: java.lang.ClassNotFoundException: Hello.class
Read that message literally and it makes sense: it went looking for a class named Hello.class, and there is no such class.
Why bother with two steps?#
Languages like C compile straight to machine code for one kind of processor, so a program built for Windows will not run on a Mac. Languages like Python skip compilation and interpret the source line by line every time, which costs speed.
Java splits the difference. javac does the expensive analysis once and produces bytecode that is not tied to any processor. Any machine with a JVM can then run that same .class file unchanged. This is what the old slogan write once, run anywhere is describing — the portable artifact is the compiled .class file, not the source.
The five errors you will actually hit first#
These are worth reading now, because you will meet all five, and each one is easier to fix when you recognize the wording.
1. The file name does not match the public class#
Saving public class Hello into a file called Greeter.java:
Greeter.java:1: error: class Hello is public, should be declared in a file named Hello.java
public class Hello {
^
1 error
A public class must live in a file of exactly the same name, capital letters included. Rename one or the other.
2. A missing semicolon#
Semi.java:3: error: ';' expected
System.out.println("hi")
^
1 error
Notice where the caret points: at the end of line 3, not at line 4. The compiler reports the position where the missing thing should have been, which is why a missing semicolon is often reported on the line above the one that looks wrong.
3. No main method#
This one compiles perfectly and then fails at run time — a class with no main is legal Java, it just cannot be used as a starting point:
Error: Main method not found in class NoMain, please define the main method as:
public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application
4. main exists but is not static#
Error: Main method is not static in class Inst, please define the main method as:
public static void main(String[] args)
The JVM has to call main before any object exists, so it can only call a method that belongs to the class itself. That is what static means here.
5. main returns something#
In C a program's entry point returns an int. In Java it does not, and the JVM says so plainly:
Error: Main method must return a value of type void in class IntMain, please
define the main method as:
public static void main(String[] args)
Compile-time or run-time?#
Sort every error you meet into one of these two columns and the fix usually suggests itself.
| Compile-time error | Run-time error | |
|---|---|---|
| Reported by | javac | java (the JVM) |
| Looks like | File.java:3: error: ... with a line number and a caret | Error: ... or Exception in thread "main" ... |
| Did the program run? | No. No .class file was produced. | Yes, and it may have already printed output before failing. |
| Typical cause | Typo, missing semicolon, wrong type, misspelled method | Missing main, bad input, dividing by zero, wrong command |
Where these go wrong#
- Editing and re-running without recompiling.
javareads the.classfile, so until you runjavacagain you are still running yesterday's program. If a change appears to have no effect at all, check this first. - Typing
java Hello.class. The launcher takes a class name. No extension, ever. - Fixing errors from the bottom up. One real mistake often produces several complaints. Fix the first error, recompile, and watch most of the rest disappear.
- Assuming a compile error means the program crashed. It never even started. There is no output to look for and no
.classfile to run. - Case.
Hello.javaandhello.javaare different files, andHelloandhelloare different classes. Windows will sometimes let you get away with this locally and then it breaks elsewhere.
Test yourself in the free Kestrel Exams app
Topic-selectable practice — offline, no ads, no account.
Practice this topic →Frequently asked questions#
Do I need to compile Java every time I change the code?
Yes. javac reads your .java source and writes a .class file; the java command only ever runs the .class file. If you edit the source and re-run without recompiling, the JVM happily runs the previous version, which is a common and very confusing way to lose ten minutes.
What is the difference between javac and java?
javac is the compiler: it turns human-readable source into bytecode and reports syntax and type errors. java is the launcher: it starts the Java Virtual Machine and executes bytecode that already compiled successfully. Errors from javac are compile-time errors; errors from java are run-time errors.
Why does my file have to be named after the class?
Java requires a public class to live in a file of exactly the same name, because that is how the compiler and the class loader find it later. Putting public class Hello in Greeter.java gives the error: class Hello is public, should be declared in a file named Hello.java.
Why do I get “Could not find or load main class”?
Most often because the .class extension was typed on the run command. The java launcher takes a class name, not a filename, so it is java Hello and never java Hello.class. The same message also appears when you run from the wrong directory.
What is bytecode?
Bytecode is the compact instruction set inside a .class file. It is not the source you wrote and not machine code for your specific processor — it is an intermediate form that any Java Virtual Machine can execute, which is what lets the same compiled file run unchanged on Windows, macOS and Linux.
