您的位置:首页 > 移动开发 > Android开发

Android安全学习笔记2-Dalvik虚拟机

2018-02-22 00:47 309 查看

Dalvik虚拟机学习

一、Dalvik虚拟机特点:

1)体积小,占用内存小

2)使用DEX可执行文件,执行速度快

3)常量池32位,寻址类方法名、字段、常量更快

4)基于寄存器,并拥有完整的指令系统

5)提供对象生命周期、堆栈、线程、安全、异常、垃圾回收等重要功能

6)每个Android程序对应一个Dalvik虚拟机实例

与JAVA虚拟机的区别

1)Dalvik字节码与JAVA字节码的不同

2)dx工具对class文件中方法签名、常量池等进行压缩精简

实验

构造这样的代码:

public class Java_Dalvik_Byte_Code_Compare{
public int foo(int a, int b){
return (a+b)*(a-b);
}
public static void main(String[] args) {
Java_Dalvik_Byte_Code_Compare first = new Java_Dalvik_Byte_Code_Compare();
System.out.println(first.foo(5, 3));
}
}


使用
javac xxx.java
编译生成class文件

使用
dx --dex --output=xxx.dex xxx.class
生成dex文件

使用
javap -c xxx.class
反编译Java字节码

Compiled from "Java_Dalvik_Byte_Code_Compare.java"
public class Java_Dalvik_Byte_Code_Compare {
public Java_Dalvik_Byte_Code_Compare();
Code:
0: aload_0
1: invokespecial #1                  // Method java/lang/Object."<init>":()V
4: return

public int foo(int, int);
Code:
0: iload_1
1: iload_2
2: iadd
3: iload_1
4: iload_2
5: isub
6: imul
7: ireturn

public static void main(java.lang.String[]);
Code:
0: new           #2                  // class Java_Dalvik_Byte_Code_Compare
3: dup
4: invokespecial #3                  // Method "<init>":()V
7: astore_1
8: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
11: aload_1
12: iconst_5
13: iconst_3
14: invokevirtual #5                  // Method foo:(II)I
17: invokevirtual #6                  // Method java/io/PrintStream.println:(I)V
20: return
}


使用
dexdump.exe -d xxx.dex
反编译dex文件

Processing '.\Java_Dalvik_Byte_Code_Compare.dex'...
Opened '.\Java_Dalvik_Byte_Code_Compare.dex', DEX version '035'
Class #0            -
Class descriptor  : 'LJava_Dalvik_Byte_Code_Compare;'
Access flags      : 0x0001 (PUBLIC)
Superclass        : 'Ljava/lang/Object;'
Interfaces        -
Static fields     -
Instance fields   -
Direct methods    -
#0              : (in LJava_Dalvik_Byte_Code_Compare;)
name          : '<init>'
type          : '()V'
access        : 0x10001 (PUBLIC CONSTRUCTOR)
code          -
registers     : 1
ins           : 1
outs          : 1
insns size    : 4 16-bit code units
00014c:                                        |[00014c] Java_Dalvik_Byte_Code_Compare.<init>:()V
00015c: 7010 0400 0000                         |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0004
000162: 0e00                                   |0003: return-void
catches       : (none)
positions     :
0x0000 line=1
locals        :
0x0000 - 0x0004 reg=0 this LJava_Dalvik_Byte_Code_Compare;

#1              : (in LJava_Dalvik_Byte_Code_Compare;)
name          : 'main'
type          : '([Ljava/lang/String;)V'
access        : 0x0009 (PUBLIC STATIC)
code          -
registers     : 5
ins           : 1
outs          : 3
insns size    : 17 16-bit code units
000164:                                        |[000164] Java_Dalvik_Byte_Code_Compare.main:([Ljava/lang/String;)V
000174: 2200 0100                              |0000: new-instance v0, LJava_Dalvik_Byte_Code_Compare; // type@0001
000178: 7010 0000 0000                         |0002: invoke-direct {v0}, LJava_Dalvik_Byte_Code_Compare;.<init>:()V // method@0000
00017e: 6201 0000                              |0005: sget-object v1, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0000
000182: 1252                                   |0007: const/4 v2, #int 5 // #5
000184: 1233                                   |0008: const/4 v3, #int 3 // #3
000186: 6e30 0100 2003                         |0009: invoke-virtual {v0, v2, v3}, LJava_Dalvik_Byte_Code_Compare;.foo:(II)I // method@0001
00018c: 0a00                                   |000c: move-result v0
00018e: 6e20 0300 0100                         |000d: invoke-virtual {v1, v0}, Ljava/io/PrintStream;.println:(I)V // method@0003
000194: 0e00                                   |0010: return-void
catches       : (none)
positions     :
0x0000 line=6
0x0005 line=7
0x0010 line=8
locals        :

Virtual methods   -
#0              : (in LJava_Dalvik_Byte_Code_Compare;)
name          : 'foo'
type          : '(II)I'
access        : 0x0001 (PUBLIC)
code          -
registers     : 5
ins           : 3
outs          : 0
insns size    : 6 16-bit code units
000198:                                        |[000198] Java_Dalvik_Byte_Code_Compare.foo:(II)I
0001a8: 9000 0304                              |0000: add-int v0, v3, v4
0001ac: 9101 0304                              |0002: sub-int v1, v3, v4
0001b0: b210                                   |0004: mul-int/2addr v0, v1
0001b2: 0f00                                   |0005: return v0
catches       : (none)
positions     :
0x0000 line=3
locals        :
0x0000 - 0x0006 reg=2 this LJava_Dalvik_Byte_Code_Compare;

source_file_idx   : 3 (Java_Dalvik_Byte_Code_Compare.java)


对比两边foo()函数的代码,可以很明显看出基于寄存器的Dalvik虚拟机执行步骤相较于基于栈的JVM精简了很多。

另外注意,Dalvik反编译的汇编中参数顺序与入栈顺序一致。

Dalvik虚拟机执行程序流程

Zygote

系统启动

init进程运行

读取inic.rc并启动重要孵化器进程Zygote

Zygote初始化Dalvik虚拟机

启动system_server并进入Zygote模式,通过socket等待命令

当执行应用程序时,system_server通过socket通知Zygote,Zygote立刻fork自身创建一个Dalvik虚拟机实例来执行目标程序的入口函数。

Dalvik

Dalvik虚拟机运行loadClassFromDec()完成类装载,类数据结构为ClassObject

使用gDvm.loadedClasses全局哈希表来存储/查询装载进来的类

字节码验证器使用dvmVerifyCodeFlow()函数对载入的代码进行校验

调用FindClass()函数查找并装载main方法类

调用dvmInterpret()初始化解释器并执行字节码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: