我試圖以編程方式運行JDB。與任何理智的調試器不同,JDB使用類名稱而不是源文件名引用源代碼。我假設它涉及具有存儲在多個.class文件,而不是單個文件字節碼(你所期望的編譯與-g
標誌產生一些參考源文件,但讓事情容易是不是Java的方式.. 。)在內部和匿名類的方法,加多寶
當加多寶指的是類我通常可以做一些字符串操作,並期待在源文件名找出哪些源文件聲明相關的類。當我需要爲斷點提供一個類名時,我可以讀取該文件以獲取包名,使用文件名作爲類名並以此方式生成完整的類名。這兩種情況我讓他們工作。
的問題開始與內部類和匿名類。它們駐留在它們自己的類文件中,並且它們的名稱是包含它們的類的損壞版本。爲了在那裏設置一個斷點,我需要重名的名字。
例如 - 這是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.class
和Main$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文件中提取信息,或質疑加多寶這件事,甚至使加多寶使用源文件名像任何理智的語言,任何理智的調試器...