一个最简单的例子:
例子
当经过编译为.class文件时,使用javap -v 的到它的字节码的近汇编码,javap的使用方法看:javap命令简述
得到返汇编后的字节码:
Classfile /home/zhida/soot/test.class
Last modified 2019-8-9; size 428 bytes
MD5 checksum d7a1b61cbddf920eda42f6a2c460f0f8
Compiled from "test.java"
public class test
SourceFile: "test.java"
minor version: 0
major version: 46
flags: ACC_PUBLIC, ACC_SUPER
Classfile /home/zhida/soot/test.class
Last modified 2019-8-9; size 428 bytes
MD5 checksum d7a1b61cbddf920eda42f6a2c460f0f8
Compiled from "test.java"
public class test
SourceFile: "test.java"
minor version: 0
major version: 46
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = NameAndType #23:#26 // out:Ljava/io/PrintStream;
#2 = Utf8 ([Ljava/lang/String;)V
#3 = Utf8 java/lang/Object
#4 = Utf8 <init>
#5 = NameAndType #4:#9 // "":()V
#6 = Class #3 // java/lang/Object
#7 = Class #18 // java/io/PrintStream
#8 = Methodref #7.#25 // java/io/PrintStream.println:(I)V
#9 = Utf8 ()V
#10 = Class #22 // java/lang/System
#11 = Utf8 Code
#12 = Utf8 main
#13 = Class #24 // test
#14 = Fieldref #10.#1 // java/lang/System.out:Ljava/io/PrintStream;
#15 = Utf8 SourceFile
#16 = Utf8 (I)V
#17 = Utf8 test.java
#18 = Utf8 java/io/PrintStream
#19 = Utf8 println
#20 = Methodref #6.#5 // java/lang/Object."":()V
#21 = Utf8 LineNumberTable
#22 = Utf8 java/lang/System
#23 = Utf8 out
#24 = Utf8 test
#25 = NameAndType #19:#16 // println:(I)V
#26 = Utf8 Ljava/io/PrintStream;
{
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=1, args_size=1
0: getstatic #14 // Field java/lang/System.out:Ljava/io/PrintStream;
3: iconst_1
4: iconst_2
5: iadd
6: invokevirtual #8 // Method java/io/PrintStream.println:(I)V
9: return
LineNumberTable:
line 6: 0
line 3: 3
line 4: 4
line 5: 5
line 6: 6
line 6: 9
public test();
flags: ACC_PUBLIC
Code: LineNumberTable
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #20 // Method java/lang/Object."":()V
4: return
LineNumberTable:
line 1: 0
line 1: 0
line 1: 1
line 1: 4
LineNumberTable:
line 1: 0
line 1: 1
line 1: 4
}
转换为BAF时,则先将最前面的那些关于常量池的定义和类与引用的定义给去掉,再将其中的无用解释码给去掉(就是 LineNumberTable,和局部变量表这种)仅仅保留反汇编码:
得到
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=1, args_size=1
0: getstatic #14 // Field java/lang/System.out:Ljava/io/PrintStream;
3: iconst_1
4: iconst_2
5: iadd
6: invokevirtual #8 // Method java/io/PrintStream.println:(I)V
9: return
public test();
flags: ACC_PUBLIC
Code: LineNumberTable
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #20 // Method java/lang/Object."":()V
4: return
可以在进一步简化,得到:
public class test {
public static void main(java.lang.String[]);
Code:
0: getstatic #14 // Field java/lang/System.out:Ljava/io/PrintStream;
3: iconst_1 取出声明的int型变量,压入操作数栈
4: iconst_2 取出声明的int型变量,压入操作数栈
5: iadd 从操作数栈中,将操作数取出,进行相加,将结果入栈
6: invokevirtual #8 // Method java/io/PrintStream.println:(I)V
9: return 赋返回
public test();
Code:
0: aload_0 从本地变量表中引用0的变量值,即this的引用,压入栈中
1: invokespecial #20 // Method java/lang/Object."":()V
4: return
}
然后,经过栈编译器直接转化:
0: getstatic word r0; r0 := @parameter0: java.lang.String[];
staticget <java.lang.System: java.io.PrizzntStream out>;
3: iconst_1 push 1;
4: iconst_2 push 2;
5: iadd add.i;
6: invokevirtual #8 virtualinvoke <java.io.PrintStream: void println(int)>;
9: return return;
将对test类对象初始化,转换为()
0: aload_0 word r0;
r0 := @this: test; load.r r0;
1: invokespecial #20 specialinvoke <java.lang.Object: void <init>()>;
4: return return;
得到BAF文件:
.baf