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


145

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

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

11
어떤 버전을 사용하고 있습니까? 나는 그들이 Java 9에 Java 콘솔을 도입했다고 생각합니다.
Matthieu

6
클래스 이름을 파일 이름과 일치시켜야합니다. 즉, Java 표준입니다. 파일 이름을로 변경 한 Myclass.java다음 명령 행에서 다음과 같이 컴파일 javac Myclass.java한 후 다음과 같이 실행하십시오 java Myclass.
unnsse

6
예, javac소스 코드를 배포하지 않거나 단일 파일 java
이상이있는

@Matthieu "java -version"의 출력은 다음과 같습니다. openjdk 버전 "12.0.2"2019-07-16 OpenJDK 런타임 환경 (빌드 12.0.2 + 10) OpenJDK 64 비트 서버 VM (빌드 12.0.2 + 10, 혼합) mode)
milad

1
@Milad-이것이 일어나는 일-Java javac소스를 JVM 고유의 해석 된 바이트 코드로 컴파일하고 java명령이 JVM의 ClassLoader 내에로드합니다.
unnsse

답변:


188

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 의 동기는 기존의 다른 용도를 변경하지 않고 "자바 학습의 초기 단계 및 소규모 유틸리티 프로그램 작성시"를 보다 쉽게 ​​만드는 것 입니다.



자세한 내용은 @CarlosHeuberger에게 감사합니다. Java 11에 도입되었음을 반영하기 위해 답변을 약간 수정했습니다.
kaan

7
자바 (8)의 @Spikatrix는 (그들은 감소 1.에를 1.8새 릴리스에서)
muru

1
왜 여전히 javac가 필요한지에 대한 답을 얻지 못했습니다 .java는 제공 한 단일 파일과 이전에 컴파일 된 파일에서만 작동한다고 생각합니다. 호출하는 파일에서 사용하려는 다른 모든 파일을 컴파일해야한다고 생각합니다.
Bill K

2
이 답변에서는이 새로운 방법으로 파일 이름 대 클래스 이름 오류가 발생하지 않는 이유를 설명하지 않습니다 javac.
sebrockm

52

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

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

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


당신을 감사합니다, 자바 버전은 다음과 같습니다 오픈 JDK 버전 "12.0.2"2019년 7월 16일 오픈 JDK 런타임 환경 (빌드 12.0.2 + 10) 오픈 JDK 64 비트 서버 VM (빌드 12.0.2 + 10, 혼합 모드)
밀라 드

5
확인 실행 단일 파일 소스 코드 프로그램 소스 파일 모드를 사용하여 명명 된 패키지의 유형은 이름이있는 파일에 존재한다는 것을, "컴파일러가 JLS ?? 7.6의 끝에서 정의 된 옵션 제한을 적용하지 않습니다 : 유형 이름과 .java 확장자로 구성됩니다. "
user85421

2
Java 스크립팅 API와 Java 단일 파일 소스 코드 프로그램 실행 ( JEP 330 )은 완전히 별개이며 전혀 관련이 없습니다.
David Conrad

@DavidConrad, 그에 따라 verbiage가 업데이트되었습니다. 감사.
Evan

@TJCrowder 입력을 감사하십시오. 그러나 나는 그것을 그대로 쓰는 것을 확신합니다. 또한 귀하의 링크에서 두 번째 정의 : 무차별은 다양한 다른 것을 포함합니다.
Evan

6

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

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

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

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

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


5

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

사용할 때 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의 경우 실제로 컴파일 된 기본 코드를 실행하는 데 시간이 걸리지 않을 수 있음)

7
이것은 질문에 대답하지 않습니다.
David Conrad

2
@DavidConrad하지만 그렇습니다! " 'java'명령이 Java 프로그램을 컴파일합니까?" hardlib가 제공하는 이유 때문에 "예"라는 소리가 들립니다. 바이트 코드를 적시에 기본 명령어로 컴파일합니다 (일반 설정이 아닌 사소한 프로그램의 경우).
복직 자 Monica

컴파일은 이제 필수입니까? 역사적으로 Java 바이트 코드는 해석 될 수있었습니다. JIT 컴파일은 선택 사항입니다.
MSalters

JIT는 mixed-mode버전 출력에서 ​​알 수 있듯이 요즘 기본적으로 켜져 있습니다 (매우 오랫동안)
hardillb
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.