2014-03-29 4 views
11

내가 예를 들어 다음과 같은 프로그램을 고려 자바 (8)와 함께 작동하도록 디버거를 업데이트하는 몇 가지 문제가 있어요 :자바 디버그 인터페이스, 람다 및 라인 번호

예상대로
public class Lam { 
    public static void main(String[] args) { 
     java.util.function.Function<Integer, Integer> square = 
      x -> { 
      int result = 0; 
      for (int i=0; 
       i<x; 
       i++) 
       result++; 
      return result; 
     }; 
     System.out.println(square.apply(5)); 
    } 
} 

는, 자바 (8)은 같은 것으로 람다를 컴파일을 이 :

> javap -c -p -v -s -constants Lam 
Classfile Lam.class 
... 
    private static java.lang.Integer lambda$main$0(java.lang.Integer); 
... 
Code: 
    stack=2, locals=3, args_size=1 
    0: iconst_0 
    1: istore_1 
... 
LineNumberTable: 
    line 5: 0 
    line 6: 2 
    line 7: 4 
    line 9: 12 
    line 8: 15 
    line 10: 21 

정상적인 코드와 매우 비슷합니다. 그러나 Java Debugger Interface (JDI)를 사용하여 프로그램의 모든 단계를 인터셉트하려고합니다. 문제가되는 주먹은 λ 클래스에 해당하는 ClassPrepareEvent event을 처리 할 때입니다. event.referenceType()에게 질문하면 시원한 Lam$$Lambda$1.1464642111과 같은 것을 얻을 수 있습니다. 그런 다음 에 .allLineLocations()을 호출하면 AbsentInformationException이 발생하며 컴파일 된 파일의 LineNumberTable과 확연히 구분됩니다.

Java에서 람다 본문을 단계적으로 실행하는 것처럼 보입니다. JDI에서 어떻게 할 수 있는지 아는 사람이 있습니까? 업데이트

:

.allLineLocationsLam 클래스라고
  • , 그것은 않습니다 다음 줄 번호를 모두 반영합니다.
  • JDI Event는 람다 클래스 내에서 발생
  • (예 : 스테핑에서), 위치의 .sourceName()는를 슬로우 AbsentInformationException
  • jdk.internal.org.objectweb.asm.*
  • 가 난 람다 복사와 관련된 물건의 무리를하고있는 것 같습니다 확실하지 바이트 코드에 소스 라인에서지도는 자바에서, 또는에 보관되어있는 경우 JDI

그래서 내 작업 가설은 람다의 클래스가 런타임에 생성 될 때 JDI는 것을 인식 뭔가를 할 필요가 있다는 것입니다 새 클래스의 바이트 코드가 이전 클래스의 바이트 코드에서옵니다 (w hich는 Lam.java에서 온 것입니다.) 어디서부터 시작해야 할지를 알기 위해 java.lang.Class 또는 com.sun.jdi.ClassType의 내부 표현에 대해 충분히 알지 못합니다.

이유는이을하려고 오전 :

답변

7

작업을 업데이트하는 런타임에 컴파일 된 클래스는 람다 클래스를 생성 혼란 것으로 보인다. 후자에는 함수 인터페이스와 컴파일러 클래스 lambda 메서드의 구현을 연결하는 접착제 만 포함되어 있습니다. 여기에는 소스가없는 메서드 이름을 제외하고 단계별로 수행 할 항목이 없습니다. 소스가 없으므로 람다 클래스의 sourceName은 없습니다. ASM 코드는 생성 된 람다 클래스를 생성합니다. 바이트 코드 위치에서 소스 행으로의 맵핑은 클래스 파일에 있습니다.

+0

이것은 도움이되었고 무슨 일이 일어나고 있는지 다시 생각하게되었습니다. 나는 이전에 "접근 $"방법을 숨기기 위해 사용했던 제목에 "$"가 붙은 방법을 사용하지 않고 목욕탕으로 아기를 던졌습니다. 이제는 그것을 고쳤습니다. http://goo.gl/VwFzIN – daveagp