我在更新调试器以使用Java 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));
}
}正如预期的那样,Java 8将lambda编译成如下所示:
> 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调试器接口(JDI)来拦截程序的每一步。出错的第一件事是当我处理与lambda类对应的ClassPrepareEvent event时。询问event.referenceType()会给我一些类似于Lam$$Lambda$1.1464642111的东西,这很酷。但是,在.allLineLocations()上调用.referenceType()会给出一个AbsentInformationException,这似乎与编译文件中的LineNumberTable不一致。
它看起来像是在Java8 是可能的中跨过lambda主体。但是,有谁知道如何在JDI中做到这一点呢?
更新:
.allLineLocations类上调用Lam时,它确实反映了所有这些行号。Event时(例如,从单步执行),位置的.sourceName()抛出一个AbsentInformationException。jdk.internal.org.objectweb.asm.*正在做一些与复制lambda有关的事情因此,我的工作假设是,当在运行时创建lambda类时,JDI需要做一些事情来识别新类的字节码来自旧类的字节码(反过来来自Lam.java)。我对java.lang.Class或com.sun.jdi.ClassType的内部表示不太了解,不知道从哪里开始。
我为什么要这么做
发布于 2014-03-31 21:03:25
您似乎混淆了编译后的类和运行时生成的lambda类。后者只包含将函数接口与编译器类lambda方法中的实现连接起来的胶水--这里没有任何您想要通过的东西,可能只是没有源的方法名。因为没有源,所以lambda类没有sourceName。ASM代码正在构建生成的lambda类。从字节码位置到源行的映射在类文件中。
https://stackoverflow.com/questions/22735872
复制相似问题