Programing

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

lottogame 2020. 5. 6. 20:47
반응형

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

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

There may be more than one LineNumberTable attribute per line of a source file in the attributes table of a Code attribute. That is, LineNumberTable attributes may together represent a given line of a source file, and need not be one-to-one with source lines.


The assumption that "Java ignores blank lines" is wrong. Here is a code snippet that behaves differently depending on the number of empty lines before the method 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]);
  }
}

If there are no empty lines before main, it prints "foo", but with one empty line before main, it prints "bar".

Since the runtime behavior is different, the .class files must be different, regardless of any timestamps or other metadata.

This holds for every language that has access to the stack frames with line numbers, not only for Java.

Note: if it's compiled with -g:none (without any debugging information), then the line numbers will not be included, getLineNumber() always returns -1, and the program always prints "bar", regardless of the number of line breaks.


As well as any line number details for debugging, your manifest may also store the build time and date. This will naturally be different every time you compile.

참고URL : https://stackoverflow.com/questions/52625161/why-does-a-java-class-compile-differently-with-a-blank-line

반응형