编译一个.java在Android上运行并通过oatdump反汇编查看oat文件
我们有一个Java程序helloworld:
public class HelloWorld {
int add_call(int a,int b){
return a + b;
}
public static void main(String[] args) {
HelloWorld m = new HelloWorld();
int c = m.add_call(1, 2);
System.out.println("Hello xianlong");
}
}
通过javac将程序编译成class文件,helloworld.class
javac Helloworld.java
接下来将.class通过dx工具转换成dex文件
./dx --dex --output=HelloWorld.dex HelloWorld.class
这里要注意的是,我的dx文件使用的是之前系统源码中的prebuilts/sdk/tool
中的dx
。JDK
使用的是1.6。(1.8版本会出现错误)
之后将我们的HelloWorld.dex
通过adb push到手机中,接下来通过dalvikvm就可以运行该dex文件。
dalvikvm -cp HelloWorld.dex HelloWorld
(这里的-cp是指class path)
如果我们想dump一下oat文件,就要借助oatdump。
执行: oatdump --oat-file=HelloWorld.odex > dump.txt
就可以把dump结果保存到dump.txt中。
接下来我们打开该文件可以看到:(部分)
0: LHelloWorld; (offset=0x0000064c) (type_idx=1) (StatusInitialized) (OatClassSomeCompiled)
0: void HelloWorld.<init>() (dex_method_idx=0)
DEX CODE:
0x0000: 7010 0400 0000 | invoke-direct {v0}, void java.lang.Object.<init>() // method@4
0x0003: 7300 | return-void-no-barrier
OatMethodOffsets (offset=0x00000000)
code_offset: 0x00000000
OatQuickMethodHeader (offset=0x00000000)
vmap_table: (offset=0x00000000)
QuickMethodFrameInfo
frame_size_in_bytes: 0
core_spill_mask: 0x00000000
fp_spill_mask: 0x00000000
vr_stack_locations:
ins: v0[sp + #8]
method*: v1[sp + #0]
outs: v0[sp + #8]
CODE: (code_offset=0x00000000 size_offset=0x00000000 size=0)
NO CODE!
1: void HelloWorld.main(java.lang.String[]) (dex_method_idx=2)
DEX CODE:
0x0000: 2200 0100 | new-instance v0, HelloWorld // type@TypeIndex[1]
0x0002: 7010 0000 0000 | invoke-direct {v0}, void HelloWorld.<init>() // method@0
0x0005: 1211 | const/4 v1, #+1
0x0006: 1222 | const/4 v2, #+2
0x0007: e930 0b00 1002 | invoke-virtual-quick {v0, v1, v2}, // vtable@11
0x000a: 6200 0000 | sget-object v0, Ljava/io/PrintStream; java.lang.System.out // field@0
0x000c: 1a01 0100 | const-string v1, "Hello xianlong" // string@1
0x000e: e920 2c00 1000 | invoke-virtual-quick {v0, v1}, // vtable@44
0x0011: 7300 | return-void-no-barrier
OatMethodOffsets (offset=0x00000658)
code_offset: 0x00000000
OatQuickMethodHeader (offset=0x00001008)
vmap_table: (offset=0x000003a4)
quickened data
QuickMethodFrameInfo
frame_size_in_bytes: 0
core_spill_mask: 0x00000000
fp_spill_mask: 0x00000000
vr_stack_locations:
locals: v0[sp + #4294967280] v1[sp + #4294967284] v2[sp + #4294967288]
ins: v3[sp + #8]
method*: v4[sp + #0]
outs: v0[sp + #8] v1[sp + #12] v2[sp + #16]
CODE: (code_offset=0x00000000 size_offset=0x0000101c size=0)
NO CODE!
2: int HelloWorld.add_call(int, int) (dex_method_idx=1)
DEX CODE:
0x0000: 9000 0203 | add-int v0, v2, v3
0x0002: 0f00 | return v0
发现都是dex code没有code,看来我们需要手动编译才能AOT的生成机器码。(之后搞明白了会将手动AOT的方法添加在这个后边。)