[java] Java 클래스가 빈 줄과 다르게 컴파일되는 이유는 무엇입니까?

다음 Java 클래스가 있습니다

public class HelloWorld {
  public static void main(String []args) {
  }
}

이 파일을 컴파일하고 결과 클래스 파일에서 sha256을 실행하면

9c8d09e27ea78319ddb85fcf4f8085aa7762b0ab36dc5ba5fd000dccb63960ff  HelloWorld.class

다음으로 클래스를 수정하고 다음과 같이 빈 줄을 추가했습니다.

public class HelloWorld {

  public static void main(String []args) {
  }
}

다시 동일한 결과를 얻을 것으로 예상되는 출력에서 ​​sha256을 실행했지만 대신

11f7ad3ad03eb9e0bb7bfa3b97bbe0f17d31194d8d92cc683cfbd7852e2d189f  HelloWorld.class

이 TutorialsPoint 기사 에서 다음 을 읽었습니다 .

주석이 포함 된 공백 만 포함 된 행을 빈 행이라고하며 Java는이를 완전히 무시합니다.

그래서 내 질문은 Java가 빈 줄을 무시하기 때문에 컴파일 된 바이트 코드가 두 프로그램 모두 다른 이유는 무엇입니까?

즉, 바이트 에서의 차이 HelloWorld.class0x03바이트로 대체됩니다 0x04.



답변

기본적으로 줄 번호는 디버깅을 위해 유지되므로 소스 코드를 변경 한 경우 메소드가 다른 줄에서 시작되고 컴파일 된 클래스가 차이를 반영합니다.


답변

javap -v자세한 정보를 출력하는 을 사용하여 변경 사항을 볼 수 있습니다 . 이미 언급 한 바와 같이 차이점은 줄 번호에 있습니다.

$ javap -v HelloWorld.class > with-line.txt
$ javap -v HelloWorld.class > no-line.txt
$ diff -C 1 no-line.txt with-line.txt
*** no-line.txt 2018-10-03 11:43:32.719400000 +0100
--- with-line.txt       2018-10-03 11:43:04.378500000 +0100
***************
*** 2,4 ****
    Last modified 03-Oct-2018; size 373 bytes
!   MD5 checksum 058baea07fb787bdd81c3fb3f9c586bc
    Compiled from "HelloWorld.java"
--- 2,4 ----
    Last modified 03-Oct-2018; size 373 bytes
!   MD5 checksum 435dbce605c21f84dda48de1a76e961f
    Compiled from "HelloWorld.java"
***************
*** 50,52 ****
        LineNumberTable:
!         line 3: 0
        LocalVariableTable:
--- 50,52 ----
        LineNumberTable:
!         line 4: 0
        LocalVariableTable:

보다 정확하게 클래스 파일은 LineNumberTable섹션 에서 다릅니다 .

LineNumberTable 특성은 Code 특성 (§4.7.3)의 특성 테이블에있는 선택적 가변 길이 특성입니다. 디버거가 코드 배열의 어느 부분을 원본 소스 파일의 주어진 줄 번호에 해당하는지 확인하기 위해 사용할 수 있습니다.

Code 속성의 속성 테이블에 여러 LineNumberTable 속성이있는 경우 순서에 상관없이 나타날 수 있습니다.

코드 속성의 속성 테이블에서 소스 파일의 라인 당 둘 이상의 LineNumberTable 속성이있을 수 있습니다. 즉, LineNumberTable 속성은 소스 파일의 주어진 행을 함께 나타낼 수 있으며 소스 행과 일대일 일 필요는 없습니다.


답변

“자바는 빈 줄을 무시 한다 는 가정 이 잘못되었습니다. 다음은 메서드 앞의 빈 줄 수에 따라 다르게 동작하는 코드 스 니펫입니다 main.

class NewlineDependent {

  public static void main(String[] args) {
    int i = Thread.currentThread().getStackTrace()[1].getLineNumber();
    System.out.println((new String[]{"foo", "bar"})[((i % 2) + 2) % 2]);
  }
}

빈 줄이 없으면 main인쇄 "foo"되지만 빈 줄이 하나 있으면 main인쇄 "bar"됩니다.

런타임 동작이 다르므로 타임 스탬프 또는 기타 메타 데이터에 관계없이 .class파일 이 달라야 합니다 .

Java뿐만 아니라 줄 번호로 스택 프레임에 액세스 할 수있는 모든 언어에 적용됩니다.

참고 : -g:none디버깅 정보없이 컴파일 하면 줄 번호가 포함되지 않고 getLineNumber()항상을 반환 -1하며 "bar"줄 바꿈 수에 관계없이 프로그램이 항상 인쇄 합니다.


답변

디버깅을위한 행 번호 세부 정보뿐만 아니라 매니페스트에도 빌드 시간과 날짜가 저장 될 수 있습니다. 컴파일 할 때마다 자연스럽게 다릅니다.


답변