2016-10-20 85 views
0

我正在嘗試使用ASMifier來正確理解我的.class文件中的內容。問題在於該工具省略了某些mv.visitXXX。例如,它不會顯示行聲明標籤的mv.visitLabel(標籤)。ASMifier無法顯示足夠的空間

它是有道理的,因爲ASMifier只顯示創建類所需的mv.visit,但我想以不同的方式使用它。

有無論如何要求工具顯示它訪問的所有內容嗎?

回答

1

ASMifier與源代碼行關聯的標籤沒有條件處理,換句話說,如果ClassReader報告它們,ASMifier會顯示它們。

對於這項工作,兩個條件必須滿足:

  1. 的方法必須具有其Code屬性相關聯的LineNumberTable屬性(普通類,這是通過生成時所使用的編譯器選項從動.class文件)。

  2. 當使用javac你不能指定SKIP_DEBUG到的ClassReader

accept方法中,存在或不存在的調試信息由-g選項控制。默認值是生成LineNumberTable屬性,因此未指定-g選項已足夠。所以,下面的程序

package bytecodetests; 

import java.io.IOException; 
import java.io.PrintWriter; 
import org.objectweb.asm.ClassReader; 
import org.objectweb.asm.util.ASMifier; 
import org.objectweb.asm.util.TraceClassVisitor; 

public class BytecodeTests { 

    public static void main(String[] args) throws IOException { 
    new ClassReader(BytecodeTests.class.getResourceAsStream("BytecodeTests.class")) 
     .accept(new TraceClassVisitor(null, new ASMifier(), new PrintWriter(System.out)), 0); 
    } 

} 

會產生

package asm.bytecodetests; 
import java.util.*; 
import org.objectweb.asm.*; 
public class BytecodeTestsDump implements Opcodes { 

public static byte[] dump() throws Exception { 

ClassWriter cw = new ClassWriter(0); 
FieldVisitor fv; 
MethodVisitor mv; 
AnnotationVisitor av0; 

cw.visit(52, ACC_PUBLIC + ACC_SUPER, "bytecodetests/BytecodeTests", null, "java/lang/Object", null); 

cw.visitSource("BytecodeTests.java", null); 

{ 
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); 
mv.visitCode(); 
Label l0 = new Label(); 
mv.visitLabel(l0); 
mv.visitLineNumber(9, l0); 
mv.visitVarInsn(ALOAD, 0); 
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); 
mv.visitInsn(RETURN); 
Label l1 = new Label(); 
mv.visitLabel(l1); 
mv.visitLocalVariable("this", "Lbytecodetests/BytecodeTests;", null, l0, l1, 0); 
mv.visitMaxs(1, 1); 
mv.visitEnd(); 
} 
{ 
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, new String[] { "java/io/IOException" }); 
mv.visitCode(); 
Label l0 = new Label(); 
mv.visitLabel(l0); 
mv.visitLineNumber(12, l0); 
mv.visitTypeInsn(NEW, "org/objectweb/asm/ClassReader"); 
mv.visitInsn(DUP); 
mv.visitLdcInsn(Type.getType("Lbytecodetests/BytecodeTests;")); 
mv.visitLdcInsn("BytecodeTests.class"); 
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Class", "getResourceAsStream", "(Ljava/lang/String;)Ljava/io/InputStream;", false); 
mv.visitMethodInsn(INVOKESPECIAL, "org/objectweb/asm/ClassReader", "<init>", "(Ljava/io/InputStream;)V", false); 
mv.visitTypeInsn(NEW, "org/objectweb/asm/util/TraceClassVisitor"); 
mv.visitInsn(DUP); 
mv.visitInsn(ACONST_NULL); 
mv.visitTypeInsn(NEW, "org/objectweb/asm/util/ASMifier"); 
mv.visitInsn(DUP); 
mv.visitMethodInsn(INVOKESPECIAL, "org/objectweb/asm/util/ASMifier", "<init>", "()V", false); 
mv.visitTypeInsn(NEW, "java/io/PrintWriter"); 
mv.visitInsn(DUP); 
mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); 
mv.visitMethodInsn(INVOKESPECIAL, "java/io/PrintWriter", "<init>", "(Ljava/io/OutputStream;)V", false); 
mv.visitMethodInsn(INVOKESPECIAL, "org/objectweb/asm/util/TraceClassVisitor", "<init>", "(Lorg/objectweb/asm/ClassVisitor;Lorg/objectweb/asm/util/Printer;Ljava/io/PrintWriter;)V", false); 
mv.visitInsn(ICONST_0); 
Label l1 = new Label(); 
mv.visitLabel(l1); 
mv.visitLineNumber(13, l1); 
mv.visitMethodInsn(INVOKEVIRTUAL, "org/objectweb/asm/ClassReader", "accept", "(Lorg/objectweb/asm/ClassVisitor;I)V", false); 
Label l2 = new Label(); 
mv.visitLabel(l2); 
mv.visitLineNumber(14, l2); 
mv.visitInsn(RETURN); 
Label l3 = new Label(); 
mv.visitLabel(l3); 
mv.visitLocalVariable("args", "[Ljava/lang/String;", null, l0, l3, 0); 
mv.visitMaxs(8, 1); 
mv.visitEnd(); 
} 
cw.visitEnd(); 

return cw.toByteArray(); 
} 
} 

注意

Label l0 = new Label(); 
mv.visitLabel(l0); 
mv.visitLineNumber(12, l0); 
… 
Label l1 = new Label(); 
mv.visitLabel(l1); 
mv.visitLineNumber(13, l1); 
… 
Label l2 = new Label(); 
mv.visitLabel(l2); 
mv.visitLineNumber(14, l2); 
… 

電話爲main方法的存在。


當從命令行運行ASMifier,它確實默認使用SKIP_DEBUG標誌,除非-debug選項已經給出第一個參數。

+0

謝謝我通過命令行使用ASMifier工具:java -cp「asm-all-5.1.jar」org.objectweb.asm.util.ASMifier Foo.class> Foo.asm但是您的解決方案非常適合我的需求。 –

相關問題