在JDB中的内部和匿名类的方法中设置断点

时间:2014-05-14 12:23:26

标签: name-mangling jdb

我正在尝试以编程方式操作JDB。与任何理智的调试器不同,JDB使用类名而不是源文件名来引用源代码。我假设它与将字节码存储在多个.class文件而不是单个文件有关(您希望使用-g标志进行编译以产生对源文件的一些引用,但是使事情变得简单不是Java方式......)

当JDB引用类时,我通常可以进行一些字符串操作并查看源文件名,以确定哪个源文件声明了相关的类。当我需要为断点提供类名时,我可以读取该文件以获取包名,使用文件名作为类名并以此方式生成完整的类名。这两个案例我让他们工作。

问题始于内部类和匿名类。它们驻留在它们自己的类文件中,它们的名称是包含它们的类的损坏版本。要在那里设置断点,我需要修改名称。

例如 - 这是Main.java(+行号):

1: public class Main{
2:    public static void main(String[] args){
3:        new Object(){
4:            @Override public String toString(){
5:                System.out.println("hi");
6:                return "";
7:            }
8:        }.toString();
9:    }
10:}

我使用javac -g Main.java进行编译,得到Main.classMain$1.class。我正在运行jdb

Initializing jdb ...
> stop on Main.main
Deferring breakpoint Main.main.
It will be set after the class is loaded.
> run Main
run  Main
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
> 
VM Started: Set deferred breakpoint Main.main

Breakpoint hit: "thread=main", Main.main(), line=3 bci=0
3               new Object(){

(我需要加载Main.class的部分 - 否则我只是得到“它将在加载类后设置。”用于所有断点设置尝试。)

如果我为第8行设置断点,它可以正常工作:

main[1] stop at Main:8
Set breakpoint Main:8

如果我为第5行设置断点 - 这是匿名类的一部分 - 我收到错误:

main[1] stop at Main:5
Unable to set breakpoint Main:5 : No code at line 5 in Main

第5行显然包含代码 - 问题是代码没有编译成Main.class - 它被编译成Main$1.class,所以我需要编写代码:

main[1] stop at Main$1:5
Deferring breakpoint Main$1:5.
It will be set after the class is loaded.

现在,Java将字节码拆分为.class文件的方式是确定性的,在这个简单的例子中,很容易弄清楚什么在哪里 - 当你用人眼检查它时 - 但是我需要一种方法来计算错误的类以编程方式(使用VimScript)命名真实世界源文件。尝试在语法上分析源文件并找出哪个是太复杂的任务 - 应该有一个更简单的方法。

也许从.class文件中提取信息,或者向JDB提问它,甚至让JDB使用源文件名,就像任何理智的调试器一样使用任何理智的语言......

1 个答案:

答案 0 :(得分:0)

我遇到了同样的问题。作为一个quickfix,我只是在所有Main $ [x] .class中为类名(在你的情况下为Object)进行了grep。

如果你发现其中很多,你必须使用它们在源文件中出现的顺序索引。