[java] ‘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 명령을 실행할 때 이전에 컴파일 된 코드를 실행했을 가능성이 큽니다.


답변

이 오류가 발생한 이유에 답하려면 파일의 클래스 이름이 파일의 클래스 이름과 일치해야합니다 basename.

이 코드를 전통적으로 작동시키는 두 가지 옵션이 있습니다 javac. java순서:

  1. 수업 이름을 public class Hello또는

  2. 로 이름 hello.java을 바꾸십시오 myclass.java.

java자바 (11)에 대한 인터프리터는이 요구 사항을 부과하지 않습니다. 포함 된 클래스 main는 파일에서 첫 번째 클래스 인 한 아무 이름이나 가질 수 있습니다. 이것은 주로 초보자를위한 학습 과정을 용이하게하고 shebang과 함께 “java scripting”을 허용하기위한 것입니다 ( ref. ).


답변

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

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

이 가상 CPU 사양은 사양 작성 당시에 일반적으로 사용 된 평균 CPU 유형의 일종입니다. 이 때문에 여러 CPU 유형에 가깝기 때문에 여러 CPU 유형에서 동일한 Java .class 파일을 더 쉽게 실행할 수 있습니다.

Java가 처음 시작될 때 java명령은 .class 파일을 읽고 바이트 코드 명령을 한 번에 하나씩 해석 한 다음 실제로 실행중인 CPU에 대한 동등한 기본 명령에 맵핑합니다. 이것은 효과가 있었지만 특히 빠르지는 않았습니다. 이를 개선하기 위해 JIT (Just In Time) 컴파일이 Java 런타임에 추가되었습니다.

JIT를 사용하면 java명령이 바이트 코드를 가져 와서 실행중인 CPU의 기본 명령어로 다시 컴파일합니다. 최신 Java 런타임은 백그라운드에서 JIT 컴파일 중 바이트 코드 해석을 시작하고 준비가되면 컴파일 된 기본 명령어로 전환하고 실행중인 응용 프로그램을 프로파일 링 한 다음 다른 최적화로 바이트 코드를 다시 컴파일하여 최상의 성능을 얻습니다.

수정 (다운 유권자를 달래기 위해) :

따라서 특정 경우 (v11보다 최신 버전의 JRE를 실행할 때) 코드는 (적어도) 두 번 컴파일됩니다

  1. 바이트 코드에 단일 .java 파일로
  2. JIT 컴파일러를 통해 바이트 코드를 해석 할 때 (helloWorld의 경우 실제로 컴파일 된 기본 코드를 실행하는 데 시간이 걸리지 않을 수 있음)

답변