我在更新调试器以使用
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.referenceType()给我一些像Lam $$Lambda $1.1464642111这是很酷.但是,然后在.referenceType()上调用.allLineLocations()给出一个AbsentInformationException,这似乎与编译文件中的LineNumberTable不一致.
它看起来像在Java 8 is possible中跨越lambda体.但是有没有人知道如何在JDI中完成?
更新:
>当在Lam类上调用.allLineLocations时,它会反映所有这些行号.
>当JDI事件发生在lambda类内(例如从步进)时,位置的.sourceName()将抛出一个AbsentInformationException
>它看起来像jdk.internal.org.objectweb.asm.*正在做一些与复制lambda相关的东西
>我不知道从源代码行到字节码的地图是否保存在Java或JDI中
所以我的工作假设是当在运行时创建lambda类时,JDI需要做一些事情来认识到新类的字节码来自旧类的字节码(这又来自于Lam.java).我不知道java.lang.Class或com.sun.jdi.ClassType的内部表示,以知道从哪里开始.
为什么我试图这样做:
>更新Java Visualizer与羊羔一起工作