Dalvik 分析之准备篇

Dalvik 分析 - Class加载 Java 源代码经过编译后会生成后缀为class文件,也即字节码文件。然后在Android中使用dx工具将其转换为后缀为jar 的dex类型文件Dalvik 虚拟机负责解释并执行编译后的字节码。在解释执行字节码之前,当然要读取文件分析文件的内容,得到字节码,然后才能解释执行之。在整个的加载过程中,最为重要的就是对Class的加载– Class包含Method,Method 又包含code。通过对Class的加载,我们即可获得所需执行的字节码。本文从dexfile 文件分析Class加载中的数据结构入 阅读详情

前言:dalvik Android 的重要组成部分 ,掌握其运行机制对理解整个Android系统有着相当之大的帮助。本文将介绍GDB单步调试和Dexdump工具的使用,期望为探索dalvik打下一定的基础

 

1. Dalvik 之编译

为了能够更方便的调试dalvik,我们需要编译一个在X86上运行的dalvik和相关工具。编译步骤如下:

  1. 首先进入到Android 源码根目录
  2. source build/envsetup.sh (不是网上有些文章写的只输入 build/envsetup.sh)
  3. lunch 2  在此之后可以看到TARGET_PRODUCT simTARGET_ARCHx86
  4. make  或者 make dalvikvm make dexdump   (make 为编译所有程序,比较耗时,有时甚至某些模块编译不过,如为节省时间,可使用make dalvikvm直接编译dalvik, make dexdump直接编译dexdump)

 

2. Gdb调试dalvik之准备工作

在用gdb启动dalvik时,需要设置一些环境,比较繁琐,这里创建一个脚本来简化这些过程,脚本名为grund.sh,放于Android源码根目录。下面为脚本内容。

 

#!/bin/sh

base=`pwd`

root=$base/out/debug/host/linux-x86/pr/sim/system

export ANDROID_ROOT=$root

bootpath=$root/framework

export BOOTCLASSPATH=$bootpath/core.jar:$bootpath/ext.jar:$bootpath/framework.jar:$bootpath/android.police.jar

export ANDROID_DATA=/tmp/dalvik_test

mkdir -p $ANDROID_DATA/dalvik-cache

exec gdb $root/bin/dalvikvm 

 

3. Gdb 调试 dalvik

  1. 准备一个简单的java 程序,如hello.java,编译后将hello.jar拷贝至Android 源码根目录。 hello.javamakefile见附录)
  2. 进入到Android 源码根目录
  3. ./grund.sh  (执行上述脚本,之后会看到gdb提示符)
  4. gdb提示符后输入 “set args –cp hello.jar hello”
  5. 这个时候就可以设置断点,单步跟踪了!如有对gdb不熟的同学,请google之。 main()函数为入口函数,先在main.c 212行设置断点(在gdb提示符后输入 “b 212”
  6. gdb提示符后输入”r” OK,我们会看到dalvikgdb启动执行,然后停于212行,执行JNI_CreateJavaVM函数前先看看gDvm的内容(输入p gDvm)。 然后执行JNI_CreateJavaVM函数(输入“n”),再看看gDvm的内容。对比执行前后的变化,可大概知道JNI_CreateJavaVM函数所做的事情。
  7. main.c 249 行代码用于加载hello.class,在249行设置断点。在此中断后,看下slashClass的内容(输入“p slashClass)slashClass正是”hello”字符串。接下来单步进入执行之(输入”s”),然后查看下函数调用栈(输入”bt”)。可知现在正在执行的是jni.c 中的FindClass函数。通过此方法,可知函数指针指向的是何函数。
  8. main.c 255行代码用于取得hello.java main函数编译后的字节码。类似于g步骤,可知此时执行的函数为jni.c中的GetStaticMethodID函数
  9. main.c 273行代码执行main函数编译后的字节码,类似于g步骤,可知此时执行的函数为jni.c 中的2681行。此处为宏定义,不容易找到。但通过gdb调试,可以准确的定位。如此时继续运行程序,”hello world” 就会出现在我们的眼前!

 

此处只做简单分析,为抛砖引玉用,各位同学可以藉此探究自己感兴趣的内容。在接下来的文章中会详细分析class加载与字节码的执行。

 

4.  dexdump查看jar文件

 

Dexdump 可执行文件放于out目录下, 可使用”find out/ -name dexdump”命令来找到dexdump

“dexdump –f  hello.jar” 命令可打印jar文件的头部信息。

“dexdump –d hello.jar” 可打印所编译的字节码。

 

头部信息如下:

Opened 'hello.jar', DEX version '035'

DEX file header:

magic               : 'dex

035'

checksum            : f2f85a9c

signature           : 0404...7831

file_size           : 740

header_size         : 112

link_size           : 0

link_off            : 0 (0x000000)

string_ids_size     : 14

string_ids_off      : 112 (0x000070)

type_ids_size       : 7

type_ids_off        : 168 (0x0000a8)

field_ids_size      : 1

field_ids_off       : 232 (0x0000e8)

method_ids_size     : 4

method_ids_off      : 240 (0x0000f0)

class_defs_size     : 1

class_defs_off      : 272 (0x000110)

data_size           : 436

data_off            : 304 (0x000130)

 

 

其中string_idstype_idsfield_idsmethod_ids class_defs皆可理解为索引。通过这些索引,可以查到真正的数据存放位置。Data_off为真正的数据存放位置。

 

 

字节码如下:

    #1              : (in Lhello;)

      name          : 'main'

      type          : '([Ljava/lang/String;)V'

      access        : 0x0009 (PUBLIC STATIC)

      code          -

      registers     : 3

      ins           : 1

      outs          : 2

      insns size    : 10 16-bit code units

000148:                                        |[000148] hello.main:([Ljava/lang/String;)V

000158: 6200 0000                              |0000: sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0000

00015c: 1a01 0900                              |0002: const-string v1, "hello world" // string@0009

000160: 6e20 0200 1000                         |0004: invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0002

000166: 2a00 0000 0000                         |0007: goto/32 #00000000

      catches       : (none)

      positions     :

        0x0000 line=4

        0x0007 line=5

      locals        :

 

  Virtual methods   -

  source_file_idx   : 10 (hello.java)

 

 

附录:

Hello.java :

public class hello{

      public static void main(String args[]) {

                  System.out.println("hello world");

                  while(true) {}

      }

}

 

Makefile:

ANDROID_SRC_DIR := /android/platform_sim

 

android_dir_dx = $(ANDROID_SRC_DIR)/out/host/linux-x86/bin/dx

 

all:

      javac hello.java

      $(android_dir_dx) --dex --output=hello.jar hello.class

clean:

      @rm *.jar *.class

 

 

后续dalvik分析之Class 加载篇请参阅:http://blog.csdn.net/VirtualPower/archive/2010/07/06/5715277.aspx

 

 

Android Dalvik虚拟机的启动过程源码分析 从前面的调用过程可以知道,参数array指向的是全局变量gRegJNI所描述的一个JNI方法注册函数表,其中,每一个表项都用一个RegJNIRec对象来描述,而每一个RegJNIRec对象都有一个成员变量mProc,指向一个JNI方法注册函数。这一步执行完成之后,Dalvik虚拟机的创建和初始化工作就完成了,回到前面,即AndroidRuntime类的成员函数start中,接下来就会调用AndroidRuntime类的另外一个成员函数startReg来注册Android核心类的JNI方法。 阅读详情

相关推荐

dalvik虚拟机运行过程分析

dalvik虚拟机运行过程分析,详细介绍了dalvik虚拟机

Android Dalvik、ART及APK编译过程

原文链接:https://www.jianshu.com/p/92227738f270 一、什么是Dalvik虚拟机 Dalvik是Google公司自己设计用于Android平台的Java虚拟机,它是Android平台的重要组成部分,支持dex格式(Dalvik Executable)的Java应用程序的运行。dex格式是专门为Dalvik设计的一种压缩格式,适合内存和处理器速度有限的系统。Google对其进行了特定的优化,使得Dalvik具有高效、简洁、节省资源的特点。从Android系统架构图知,Dal

u013750244的博客 4726

Dalvik 虚拟机工作流程:

Dalvik 虚拟机工作流程: 1、sdk编译 .Java文件生成.class文件,经dx工具将工程的.class文件们生成dalvik可以执行的 classes.dex文件。在了解dalvik虚拟机怎样工作的之前,先了解下.dex文件的构成。它的构成数据结构在DexFile.h中可以找到。 /*  * Direct-mapped "map_list".  */ struct DexM

wsh的专栏 2175

Dalvik虚拟机的运行过程分析

在前面一文章中,我们分析Dalvik虚拟机在Zygote进程中的启动过程Dalvik虚拟机启动完成之后,也就是在各个子模块初始化完成以及加载了相应的Java核心类库之后,就是可以执行Java代码了。当然,Dalvik虚拟机除了可以执行Java代码之外,还可以执行Native代码,也就是C和C++代码。在本文中,我们就将继续以Zygote进程的启动过程为例,来分析Dalvi...

weixin_30432579的博客 420

dalvik虚拟机执行流程_Dalvik解释器源码到VMP分析

本文为看雪论坛优秀文章看雪论坛作者ID:glider菜鸟前言学习这块的主要目的还是想知道vmp是如何实现的,如何与系统本身的虚拟机配合工作,所以简单的学习了Dalvik的源码并对比分析了数字公司的解释器。笔记结构如下:1、dalvik解释器分析dalvik解释器解释指令前的准备工作dalvik解释器的模型invoke-super指令实例分析2、数字壳解释器分析解释器解释指令前的准备工作解释器的模型...

weixin_34030345的博客 667

GitHub已标星81,深入剖析原理

注册服务(addService) 获取服务(getService) Framework 层分析 如何使用 Binder 如何使用 AIDL Binder 总结 Binder 面试题全解析 第二章: 深入解析Handler 相信大家都有这样的感受:网上分析 Handler 机制原理的文章那么多, 为啥还要画蛇添足整理这份笔记呢?不是说前人们写的文章不好,我就是觉得他们写的不细, 有些点不讲清楚,逻辑很难通顺的,每次我学个什么东西时遇到这种情况都贼难受。 本章先宏观..

m0_66264699的博客 189

dalvik VM的解释器分析

以KK的dalvik源码为基础来解析。 使用的源码基于https://github.com/AOKP/dalvik, 可以从https://github.com/AOKP/dalvik/archive/kitkat.zip 下载。 我是在linux下,使用vim + ctags做分析的。 由于ARM架构是使用最多也是最频繁的架构,所以我分析的重点是ARM的汇编如何实现解释器的。所以我在分

doon的专栏 4111

Android ART运行时无缝替换Dalvik虚拟机过程分析

Android 4.4发布了一个ART运行时,准备用来替换掉之前一直使用的Dalvik虚拟机,希望籍此解决饱受诟病的性能问题。老罗不打算分析ART的实现原理,只是很有兴趣知道ART是如何无缝替换掉原来的Dalvik虚拟机的。毕竟在原来的系统中,大量的代码都是运行在Dalvik虚拟机里面的。开始觉得这个替换工作是挺复杂的,但是分析了相关代码之后,发现思路是很清晰的。本来就详细分析这个无缝的替换过程

老罗的Android之旅 9万+

dalvik启动过程

从Zygote进程启动过程分析过程中,我们知道,dalvik虚拟机的启动过程是从AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)函数开始的,详细时序图如下: 下面我们来逐步详细地分析一下每个步骤。 1.startVm(AndroidRuntime.cpp) /* * Start the Dalvik Virtual

成长的记忆 3768

Dalvik 调试分析

前言:dalvikAndroid 的重要组成部分 ,掌握其运行机制对理解整个Android系统有着相当之大的帮助。本文将介绍GDB单步调试和Dexdump工具的使用,期望为探索dalvik打下一定的基础。   1. Dalvik编译 为了能够更方便的调试dalvik,我们需要编译一个在X86上运行的dalvik和相关工具。编译步骤如下: 首先进入到Android 源码根目录

darling757267的专栏 1641

Dalvik解释器源码到VMP分析

前言 学习这块的主要目的还是想知道vmp是如何实现的,如何与系统本身的虚拟机配合工作,所以简单的学习了Dalvik的源码并对比分析了数字公司的解释器。笔记结构如下: dalvik解释器分析 dalvik解释器解释指令前的准备工作 dalvik解释器的模型 invoke-super指令实例分析 数字壳解释器分析 解释器解释指令前的准备工作 解释器的模型 invoke-s...

omnispace的博客 736
上一篇: Android Makefile and build system 分析
下一篇: Dalvik 分析 - Class加载篇
VirtualPower
博客等级 码龄16年 31粉丝 5原创
评论 13
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值