development

'java'명령이 Java 프로그램을 컴파일합니까?

big-blog 2020. 7. 16. 07:41
반응형

'java'명령이 Java 프로그램을 컴파일합니까?


인터넷상의 대부분의 웹 사이트는 다음과 같이 말합니다.

" javac명령을 사용하여 .java파일 을 컴파일 하십시오. 그런 다음 명령을 사용하여 파일을 실행하십시오. java"

그러나 오늘 나는 Java 프로그램을 실행하지 않고 javac이상한 결과를 얻었습니다.

파일의 내용은 다음과 같습니다 hello.java.

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

그런 다음 나는 달렸다.

$ javac hello.java

이 오류가 발생합니다.

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

그러나 javac명령없이 실행하면 오류없이 실행되었습니다.

$ java hello.java
hello world

않는 java명령은 프로그램을 컴파일? 그렇다면 왜 javac명령이 필요한가?

내 자바의 버전은 다음과 같습니다

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)

Java 11 이전에는 코드를 실행하려면 먼저 코드를 컴파일 한 다음 실행할 수 있습니다. 예를 들면 다음과 같습니다.

javac test.java
java test

Java 11부터는 javac+ java를 수행하거나 java자체적으로 실행하여 코드를 컴파일하고 자동 실행할 수 있습니다. .class파일이 생성 되지 않습니다 . 예를 들면 다음과 같습니다.

java test.java

을 실행 java -help하면 다양한 허용 된 사용법이 표시됩니다. 내 컴퓨터의 모습은 다음과 같습니다. 마지막 java [options] <sourcefile> [args]은 "단일 소스 파일 프로그램을 실행하는 것"입니다.

$ 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)

최신 정보:

@BillK가 지적했듯이 OP는 다음과 같이 물었습니다.

왜 javac 명령이 필요한가요?

우리가 필요한 이유 는 오늘날처럼 코드를 생성, 테스트, 배포, 실행, 공유 할 수 있도록 파일 javac을 생성 .class하는 것입니다. JEP 330 의 동기는 기존의 다른 용도를 변경하지 않고 "자바 학습의 초기 단계 및 소규모 유틸리티 프로그램 작성시"를 보다 쉽게 ​​만드는 것 입니다.


Java 11을 실행중인 경우 단일 소스 파일 실행을 허용하는 새로운 기능이 있습니다. 단일 소스 컴파일러는 클래스 이름과 파일 이름 측면에서 더 무질서하므로 실행할 수는 있지만 성공적으로 컴파일 할 수는 없습니다.

이전 버전의 Java를 사용하는 경우 컴파일 오류, 특히 클래스 이름과 관련하여 현재 hello.java가 컴파일되지 않습니다. 따라서 java hello.java를 호출하는 것은 컴파일되지 않기 때문에 코드를 컴파일하는 방법은 절대 없습니다.

java 명령을 실행할 때 이전에 컴파일 된 코드를 실행했을 가능성이 큽니다.


예, 그러나 당신이 의미하는 방식은 아닙니다.

javac명령을 사용하여 .java 파일을 .class 파일로 컴파일 할 때 출력은 바이트 코드입니다. 바이트 코드는 Java Virtual Machine 사양을 기반으로하는 이론적 CPU의 시스템 코드 (기본 명령)입니다.

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)

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


This feature provides the ability to run a Java single-file source code directly without any compilation, avoiding tedious steps that involved previously to run just a simple hello world program.

Java 11+ Launch Single-File Source-Code Programs 

Why you need this If you recall the old days just before Java SE 11 (JDK 11), say you have a HelloUniverse.java source file that contains a class definition and a static main method which prints out as a single line of text to the terminal like the following:

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

Normally to run this class, first, you would need to compile it using a Java compiler (javac), which would result in a HelloUniverse.class file:

$ javac HelloUniverse.java
Then you would use a java virtual machine (interpreter) command to run the resulting class file:

$ java HelloUniverse
Hello InfoQ Universe

This starts up the JVM, loads the class, and executes the code.

But what if you want to quickly test a piece of code and want to experiment. Those two steps in the process may seem like a bit of heavy lifting. In Java SE 11, you get the option to launch a single source code file directly, without intermediate compilation.

참고URL : https://stackoverflow.com/questions/58086412/does-the-java-command-compile-java-programs

반응형