152

Most websites on the internet say:

"use the javac command to compile a .java file. Then run it using the java command"

But today I tried to run a java program without javac and I got a strange result.

Here are the contents of a file called hello.java:

public class Myclass {
 public static void main(String[] args){
    System.out.println("hello world");
  }
}

Then I ran:

$ javac hello.java

Which gives me this error:

hello.java:1: error: class Myclass is public, should be declared in a file named Myclass.java
public class Myclass {
       ^
1 error

But when I run it without the javac command, it executed without any errors.

$ java hello.java
hello world

Does the java command also compile the program? If yes, why do we need the javac command?

The version of my java is:

openjdk version "12.0.2" 2019-07-16
OpenJDK Runtime Environment (build 12.0.2+10)
OpenJDK 64-Bit Server VM (build 12.0.2+10, mixed mode)
Malekai
  • 4,765
  • 5
  • 25
  • 60
milad
  • 1,854
  • 2
  • 11
  • 27
  • 13
    Which version are you using? I think they introduced Java Console in Java 9, and that might be what you experienced. – Matthieu Sep 24 '19 at 18:44
  • 7
    You need to match the class name with its filename - that's the Java standard. Just change the file name to `Myclass.java` and then from the command line compile it like this `javac Myclass.java` and then run it like this `java Myclass`. – unnsse Sep 24 '19 at 18:45
  • 6
    yes, `javac` still used to compile if you don't want to deploy source code, or you have more than a single file ([documentation](https://docs.oracle.com/en/java/javase/13/docs/specs/man/java.html) of `java` for source-file option: Only used to launch a single source-file program.) – user85421 Sep 24 '19 at 18:48
  • @Matthieu the output of "java -version" is: openjdk version "12.0.2" 2019-07-16 OpenJDK Runtime Environment (build 12.0.2+10) OpenJDK 64-Bit Server VM (build 12.0.2+10, mixed mode) – milad Sep 24 '19 at 18:50
  • 1
    @Milad - What happens is this - `javac` compiles the Java source into JVM specific interpreted bytecode and the `java` command loads it inside the JVM's ClassLoader. – unnsse Sep 24 '19 at 18:57
  • @unnsse: That doesn't answer the question about how `java hello.java` works at all though... – Jon Skeet Jul 07 '23 at 06:14
  • I would recommend reading [this](https://stackoverflow.com/a/64015013/1553537) as well as it will give you a better understanding of the context and motivation behind turning `java` launcher into a compiler too, sometimes, for a single-file applications. – Giorgi Tsiklauri Jul 07 '23 at 06:33

5 Answers5

201

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.

Kaan
  • 5,434
  • 3
  • 19
  • 41
  • 50
    introduced in Java 11: [What's New](https://www.oracle.com/technetwork/java/javase/11-relnote-issues-5012449.html#NewFeature) or/and [JEP 330: Launch Single-File Source-Code Programs](http://openjdk.java.net/jeps/330) – user85421 Sep 24 '19 at 19:09
  • thanks @CarlosHeuberger for the additional details. I made a small edit in my answer to reflect that it was introduced in Java 11. – Kaan Sep 24 '19 at 19:16
  • How do I check if I'm using Java 11+? `java -version` gives me `openjdk version "1.8.0_222" OpenJDK Runtime Environment (build 1.8.0_222-8u222-b10-1ubuntu1~16.04.1-b10) OpenJDK 64-Bit Server VM (build 25.222-b10, mixed mode) ` – Spikatrix Sep 25 '19 at 05:20
  • 7
    @Spikatrix that's Java 8 (They dropped the `1.` in `1.8` in newer releases) – muru Sep 25 '19 at 05:45
  • 2
    You didn't answer the question why we still need javac--I think java only operates on the single file you supply it and previously compiled files. I believe you must compile all the other files you wish to use from the file you call. – Bill K Sep 26 '19 at 16:48
  • from [JEP 330](https://openjdk.java.net/jeps/330): the motivation was to make it easier for _"early stages of learning Java, and when writing small utility programs"_ without changing any other existing uses. When using the shortcut, no `.class` file will be generated - `javac` is still needed to create `.class` files. – Kaan Sep 26 '19 at 17:19
  • 2
    This answer does not address why this new method does not result in a file name vs. class name error as reported by `javac`. – sebrockm Sep 27 '19 at 09:13
  • I am new to java, but by your answer, what i understand is : now we can use .java file as standalone program file and also can be used as crontab to automate small processes ? such as python can do ? – Abhinav Verma Oct 01 '19 at 17:55
57

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.

Evan
  • 2,441
  • 23
  • 36
  • thank you, java version is: openjdk version "12.0.2" 2019-07-16 OpenJDK Runtime Environment (build 12.0.2+10) OpenJDK 64-Bit Server VM (build 12.0.2+10, mixed mode) – milad Sep 24 '19 at 18:54
  • 5
    check [Using Source-File Mode to Launch Single-File Source-Code Programs](https://docs.oracle.com/en/java/javase/13/docs/specs/man/java.html#using-source-file-mode-to-launch-single-file-source-code-programs): "The compiler does not enforce the optional restriction defined at the end of JLS ??7.6, that a type in a named package should exist in a file whose name is composed from the type name followed by the .java extension." – user85421 Sep 24 '19 at 18:54
  • 2
    The Java scripting API and Java Single-File Source-Code Program Launch ([JEP 330](https://openjdk.java.net/jeps/330)) are two completely separate and totally unrelated things. – David Conrad Sep 25 '19 at 16:55
  • @DavidConrad, updated verbiage accordingly. Thanks. – Evan Sep 25 '19 at 18:03
  • Appreciate the input, @T.J.Crowder. But, I'm fairly sure I meant to write it as is. Also, second definition in your links: Promiscuous means including a wide range of different things. – Evan Sep 27 '19 at 18:04
  • @Evan - "Wide range of different things" doesn't fit the sentence above. – T.J. Crowder Sep 28 '19 at 08:33
  • How about my ad hoc definition: Promiscuous means it takes whatever it can get? Highly amused at the amount of comments now discussing the word promiscuous. – Evan Sep 28 '19 at 13:01
9

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:

  1. Rename the class to public class Hello or

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

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76
7

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

  1. As a single .java file to bytecode
  2. Via the JIT compiler as it interprets the bytecode (though for helloWorld it might not actually get time to run any of the compiled native code)
hardillb
  • 54,545
  • 11
  • 67
  • 105
  • 7
    This doesn't answer the question. – David Conrad Sep 25 '19 at 16:52
  • 3
    @DavidConrad But it does! The answer to "Does the 'java' command compile Java programs?" is a resounding "yes" for the reasons hardlib gives here: it will compile byte code to native instructions just-in-time (for non-trivial programs, with standard settings). – Peter - Reinstate Monica Sep 26 '19 at 12:31
  • Is compilation now mandatory? Historically Java byte code could be interpreted; JIT compilation was optional. – MSalters Sep 26 '19 at 15:21
  • The JIT is on by default these days (for a very long time), as show by the `mixed-mode` in the version output – hardillb Sep 26 '19 at 15:23
0

enter image description hereThe command to run the java file is using java filename. ie: simply create a file in notepad and enter the java code inside the file, the name of the file should same as the Main class in our code then save the file as Myclass.java(example), then open the command prompt and run javac Myclass.java it will create a class file in the location where file is created then use java Myclass to run the program, we can't simply run using java Myclass we have to convert it to class file using javac command so that virtual machine will read the code.

code:

Main.java

public class Main
{
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

Thanks.

  • _and using java command we can compile the program_ Don't you mean: _and using java command we can RUN the program_ ? – Abra Jul 07 '23 at 05:35
  • So [edit] your answer and correct it. – Abra Jul 07 '23 at 05:53
  • 1
    Yes we can run, the command to run the java file is using java filename. ie: simply create a file in notepad and enter the java code inside the file, the name of the file should same as the Main class in our code then save the file as Myclass.java(example), then open the command prompt and run javac Myclass.java it will create a class file in the location where file is created then use java Myclass to run the program, we can't simply run using java Myclass we have to convert it to class file using javac command so that virtual machine will read the code. Thanks, – Gokul Krishnan J Jul 07 '23 at 06:01
  • Just click on the link in my other comment and you can edit your answer. Your comment should be part of your answer. – Abra Jul 07 '23 at 06:07