Prior to Java 11, to run your code you have to first compile it, then you can run it. Here's an example:
javac test.java
java test
Since Java 11, you can still do javac
+ java
, or you can run java
by itself to compile and auto-run your code. Note that no .class
file will be generated. Here's an example:
java test.java
If you run java -help
, you'll see the various allowed usages. Here's what it looks like on my machine. The last one is what you ran into: java [options] <sourcefile> [args]
which will "execute a single source-file program".
$ java -help
Usage: java [options] <mainclass> [args...]
(to execute a class)
or java [options] -jar <jarfile> [args...]
(to execute a jar file)
or java [options] -m <module>[/<mainclass>] [args...]
java [options] --module <module>[/<mainclass>] [args...]
(to execute the main class in a module)
or java [options] <sourcefile> [args]
(to execute a single source-file program)
UPDATE:
As pointed out by @BillK, OP also asked:
why do we need the javac command?
The reason we need javac
is to create .class
files so that code can be created, tested, distributed, run, shared, etc. like it is today. The motivation for JEP 330 was to make it easier for "early stages of learning Java, and when writing small utility programs" without changing any other existing uses.
If you are running Java 11, there is a new feature that allows single source file execution. The single source compiler is more promiscuous in terms of class name versus file name, so that is how you are able to run but not successfully compile.
If you are on a previous version of Java, then your current hello.java does not compile, because of compile errors, specifically around the class name. So there's absolutely no way that calling java hello.java compiled your code, because it does not compile.
It seems most entirely likely that you were running some previously compiled code when executing the java command.
To answer why this error is given, the class name for the file must match the file's basename
.
You have two options to have this code work for the traditional javac
; java
sequence:
Rename the class to public class Hello
or
Rename hello.java
to myclass.java
.
The java
interpreter for Java 11 does not impose this requirement. The class that contains main
can have any name, as long as it is the first class in the file. This was mainly intended to ease the learning process for beginners, and to allow "java scripting" with the shebang (ref.).
Yes, but not in the way you probably mean.
When you use the javac
command to compile a .java file to a .class file the output is something called bytecode. Bytecode is a the machine code (native instructions) for a theoretical CPU based on the Java Virtual Machine specification.
This virtual CPU specification is sort of an average of types of CPUs that were common at the time the specification was written. Because of this it is close to lots of different types of CPU making it easier to run the same Java .class files on multiple CPU types.
When Java was first launched the java
command would read the .class file and interpret the bytecode instructions one at a time and then map them to the equivalent native instruction for what ever CPU it was actually running on. This worked but wasn't particularly fast. To improve this Just in Time (JIT) compilation was added to the Java Runtime.
With JIT the java
command takes the bytecode and compiles it again to the native instructions for the CPU it is running on. Modern Java runtimes tend to start out interpreting the bytecode while JIT compiling in the background and switch to the compiled native instructions when it's ready and will also profile the running application and then recompile the bytecode again with different optimisation to get the best possible performance.
EDIT (to appease the down voters):
So in your specific case (as you are running a JRE newer than v11) the code is compiled (at least) twice
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With