编译一个.java在Android上运行并通过oatdump反汇编查看oat文件

编译一个.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中的dxJDK使用的是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的方法添加在这个后边。)

posted @ 2019-11-12 17:40  zhangxianlong  阅读(91)  评论(0编辑  收藏