다음 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.class
는 0x03
바이트로 대체됩니다 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"
줄 바꿈 수에 관계없이 프로그램이 항상 인쇄 합니다.
답변
디버깅을위한 행 번호 세부 정보뿐만 아니라 매니페스트에도 빌드 시간과 날짜가 저장 될 수 있습니다. 컴파일 할 때마다 자연스럽게 다릅니다.