2013-12-12 21 views
0

我寫了一個Java類asm.jar,它會轉儲字節碼文件命名SimpleDynamicInvoker.class如何ASM添加行屬性的Java類,以便它可以支持調試

沒有其他第三依賴,除了JDK,是必須的。在eclipse中,正在執行的SimpleDynamicInvoker與我所期望的相同。

問題是,當我想調試SimpleDynamicInvoker.class(沒有它的源代碼,因爲它正在執行我的類的結果)。我想檢查如何調用jdk庫。然後我在java.lang.MethodHandle.java中添加了斷點。我相信當SimpleDynamicInvoker啓動時,會調用它的一些函數。

但是,當我調試SimpleDynamicInvokerin日食,它彈窗消息:

無法安裝斷點.....由於缺少行號屬性

此錯誤消息是常見的Eclipse和我在stackoverflow中找到類似的解決方案,但我的情況是不同的。

因此,我的問題如何添加行信息與asm,以便它可以支持debeg?感謝 生成SimpleDynamicInvoker字節碼是這樣的:

Classfile /C:/sxu/workspace/DynamicExample/bin/sxu/xxx/test/SimpleDynamicInvoker.class 
Last modified Dec 12, 2013; size 472 bytes 
MD5 checksum c50eca7b8806f93154318a72a52ada22 
public class sxu.xxx.test.SimpleDynamicInvoker 
BootstrapMethods: 
    0: #17 invokestatic sxu/xxx/test/invoke/DynamicLinkageExample.bootstrapDynamic:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; 
    Method arguments: 
minor version: 0 
major version: 51 
flags: ACC_PUBLIC, ACC_SUPER 
Constant pool: 
    #1 = Utf8    sxu/xxx/test/SimpleDynamicInvoker 
    #2 = Class    #1    // sxu/xxx/test/SimpleDynamicInvoker 
    #3 = Utf8    java/lang/Object 
    #4 = Class    #3    // java/lang/Object 
    #5 = Utf8    <init> 
    #6 = Utf8    ()V 
    #7 = NameAndType  #5:#6   // "<init>":()V 
    #8 = Methodref   #4.#7   // java/lang/Object."<init>":()V 
    #9 = Utf8    main 
    #10 = Utf8    ([Ljava/lang/String;)V 
    #11 = Utf8    sxu/xxx/test/invoke/DynamicLinkageExample 
    #12 = Class    #11   // sxu/xxx/test/invoke/DynamicLinkageExample 
    #13 = Utf8    bootstrapDynamic 
    #14 = Utf8    (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; 
    #15 = NameAndType  #13:#14  // bootstrapDynamic:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; 
    #16 = Methodref   #12.#15  // sxu/xxx/test/invoke/DynamicLinkageExample.bootstrapDynamic:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; 
    #17 = MethodHandle  #6:#16   // invokestatic sxu/xxx/test/invoke/DynamicLinkageExample.bootstrapDynamic:(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite; 
    #18 = Utf8    helloWorld 
    #19 = NameAndType  #18:#6   // helloWorld:()V 
    #20 = InvokeDynamic  #0:#19   // #0:helloWorld:()V 
    #21 = Utf8    Code 
    #22 = Utf8    BootstrapMethods 
    { 
     public sxu.xxx.test.SimpleDynamicInvoker(); 
     flags: ACC_PUBLIC 
Code: 
    stack=1, locals=1, args_size=1 
    0: aload_0 
    1: invokespecial #8     // Method java/lang/Object."<init>":()V 
    4: return 

    public static void main(java.lang.String[]); 
    flags: ACC_PUBLIC, ACC_STATIC 
    Code: 
     stack=0, locals=1, args_size=1 
     0: invokedynamiC#20, 0    // InvokeDynamiC#0:helloWorld:()V 
     5: return 
    } 
+0

您可以得到一個Eclipse的ASM插件,它顯示了您編譯的類的ASMifier結果。這是一種很好的方法來模擬可以從Java產生的任何東西,包括調試信息。 –

+0

謝謝@PeterLawrey。我的問題是如何使用asm庫添加行屬性。我沒有問題來查看字節碼文件。 –

+0

然後,您可以查看帶有調試信息的類的字節碼/ ASM代碼,並將其用作示例。 –

回答

0

如果該消息顯示就意味着有exsits沒有提到在目標類中的行號。這意味着使用ASM你當任:

  • 根本不
  • 添加行號加錯了行號

用一個例子類Test

package test; 
public class Test { 
    public Test() { 
    super(); 
    } 
} 

我得到以下字節碼

public <init>()V 
    L0 
    LINENUMBER 4 L0 
    ALOAD 0 
    INVOKESPECIAL java/lang/Object.<init>()V 
    RETURN 
    L1 
    LOCALVARIABLE this Ltest/Test; L0 L1 0 
    MAXSTACK = 1 
    MAXLOCALS = 1 

正如您從字節碼中看到的那樣,超級構造函數調用的指定行4在字節代碼中被明確引用,這就是爲什麼調試器可以識別您的斷點位置的原因。

請注意,使用ASM,您需要手動添加行,調用MethodVisitor#visitLine方法,該方法需要Label來標記引用的代碼部分。

相關問題