2016-12-12 1 views
0

내 클래스 파일을 분해하면,자바 LineNumberTable : 항목 설명

LineNumberTable: 
    line 204: 0 
    line 205: 9 
    line 208: 57 
    line 209: 63 
    line 210: 72 
    line 211: 75 
    line 212: 78 
    line 213: 87 
    line 216: 90 
    line 218: 118 
    line 221: 126 
    line 222: 131 
    line 223: 138 
    line 224: 143 
    line 227: 150 
    line 230: 157 
    line 231: 160 
    line 232: 170 
    line 235: 194 
    line 237: 228 
    line 240: 249 
    line 241: 259 
    line 243: 266 
    line 245: 269 
    line 246: 292 
    line 248: 295 
    line 249: 301 
    line 250: 308 
    line 251: 315 
    line 252: 322 
    line 253: 329 

내가이 테이블 디버그 정보가 포함되어 있음을 알고있는 형태의 LineNumberTables 내가 얻을 첫 번째 항목은 클래스의 위치에 어떤 종류의 것을 -file이고, 두 번째 것은 소스 코드의 위치입니다. 나는 알고 싶다 :

  1. 소스 코드의 라인 번호는 상대적인가 절대인가? 만약 내가 그것들을 절대적으로 해석한다면, 어떤 것은 이상하게 보이는 여러 줄 주석의 중간을 지적한다.

  2. 동일한 소스 코드의 두 가지 다른 컴파일은 한 바이트 만 다릅니다. "216 : 90"항목이 "215 : 90"입력란으로 바뀝니다. 나는 이것이 무엇을 할 수 있는지 알아 내려고 노력한다. 어떤 생각?

+0

[이 링크] (https://docs.oracle.com/javase/specs/jvms/se6/html/ClassFile.doc.html#22856) - 인터넷 검색에서 첫 번째 페이지의 일부인 "java line number table ". – TripeHound

+0

고맙습니다 - 이미 그 페이지를 읽었습니다. –

+0

죄송합니다 (그런 페이지를 읽었을 지 모르겠지만) 광산과 같은 주석을 멈출 수 있습니다 :-) 첫 번째 숫자는 바이트 코드에 대한 오프셋이고 두 번째 숫자는 "원본 소스 파일의 줄 번호입니다 ". 또한 (가능하면 여러 개의) 테이블에있는 항목이 소스 행과 일대일 관계 일 필요는 없다고 말합니다. 행 번호가 여러 줄로 된 주석의 중간에 있어야하는 것처럼 들리지는 않지만 말입니다. 추측을 어렵게하는 것은 _other_ 클래스가 다시 컴파일 되었기 때문에 나타나는 불일치를 나타낼 수 있습니까? (해당 페이지의 섹션 4.9의 두 번째 참조)? – TripeHound

답변

2

읽고있는 내용에 상식을 적용하십시오. 사양을 올바르게 읽는 동안, 즉 LineNumberTable 속성 배열에 저장된 첫 번째 숫자는 바이트 코드 오프셋이고 두 번째 숫자는 줄 번호입니다. 사용중인 디스어셈블러도이 순서로 인쇄됩니다.

주문이

  1. 제 번호 전에 인쇄 단어 "선"이 첫 번째 숫자는 행 번호
  2. 첫 번째 숫자 범위가 있음을 시사 존재를 교환 한 개의 지표있다 204에서 253으로, 이는 클래스 선언의 어딘가에있는 메소드의 소스 코드 라인에 대해 합리적입니다. 반면에 두 번째 숫자는 0에서 329까지입니다. 이는 0으로 시작하는 메소드 내의 바이트 코드 오프셋에 적당합니다.

    반면에 소스 코드는 보통 packageimport 선언으로 시작하므로 메서드에서 0으로 시작하는 줄 번호는 보이지 않습니다. 또한 메소드 코드의 첫 203 바이트에 연관된 소스 코드 행이없는 경우 (이는 불가능하지는 않지만) 드문 경우입니다.

두 표시기는 매우 강하다. 그러면, 관찰 된 변화는 아주 그럴듯하다. 분명히 생성 된 코드는 변경되지 않았습니다. 그러나 줄 번호와 생성 된 코드가 어떻게 연관되어 있는지에 대한 표준이 없기 때문에 컴파일러 버전에 따라 미묘한 차이가있을 수 있습니다. 표현식이 여러 행에 걸쳐 있지만 하나의 명령 만 생성하거나 컴파일러가 너무 많은 행 번호 테이블을 피하려고 할 때.

예. 그 명령과 연관 두 라인의 어느 (foo()static 인 경우)이 정의되지 년대 코드

foo(
); 

단지 하나의 명령을 생성한다. 인스턴스 메소드 인 경우에는 두 개의 명령어로 구성되지만, 서로 다른 행 번호로 표시하는 것은 논쟁의 여지가 있습니다. 디버깅하는 동안 단계적으로 수행하면 도움이되지 않기 때문입니다. 그러나 컴파일러의 결정입니다.또한 스택에 상수 인수 각각 추진

foo(
    null, 
    1, 
    true 
); 

와 명령어 당 다른 4 바이트를 요구 지시 각각 별개의 라인 번호를 대응하는 반면, 명령 시퀀스에서 한 바이트를 필요로한다. 이 상수를 푸시하는 것은 실패하지 않을 것이므로 추적을하는 것은 거의 이해가되지 않을 것입니다. 컴파일러는 전체 시퀀스를 호출 명령의 유일한 행 번호와 연관 시키기로 결정할 수 있습니다. 이 결정은 실제 컴파일러와 현재의 구성에 달려 있기 때문에 다시 컴파일하면 연결이 변경 될 수 있습니다.

다른 차이점은 컴파일러가 브리지 메소드 및 내부 클래스 접근 자와 같은 합성 메소드를 처리하는 방법입니다. 나는 지금까지 주변 클래스 선언의 시작 부분과 그들이 위임 한 실제 대상 멤버의 시작 부분과 함께 단지 0과 관련되어있는 것을 보아왔다.