文章目录

  • 前言
  • 一、打包 Jar 文件和 Dex 文件
    • 1、示例代码
    • 2、打包 Jar 文件
    • 3、打包 Dex 文件
  • 二、反编译 Dex 文件
  • 三、分析 Dex 文件
    • 1、Student 类相关信息
    • 2、User 类相关信息

前言

Dalvik 虚拟机运行的是 Dex 文件 ; Dex 文件并不是最终 DVM 运行的文件 , Dex 文件还需要再次优化为 Odex 文件 , 这才是最终运行在 DVM 上的文件 ;

安装 APK 完毕后 , 运行时 , 或者 使用类加载器加载 Dex 文件时 , 才会生成 Odex 文件 ;

Odex 文件会存放在 /data/dalvik-cache 目录下 ;

一、打包 Jar 文件和 Dex 文件


Dalvik 虚拟机中运行的是 Dex 文件 , Java 虚拟机运行的是 Jar 文件 ;

1、示例代码

示例代码 :

  • 代码 111 :
public class Student {private String name;private int age;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public void ageIncrease(){synchronized(this) {this.age++;}}
}
  • 代码 222 :
public class User {private int age = 0;public synchronized void increase() {this.age++;}
}

2、打包 Jar 文件

打包 Jar 文件 :

使用如下命令 , 将 Class 字节码文件打成 Jar 包 :

jar cvf main.jar Student.class User.class

输出结果 :

D:\002_Project\004_Java_Learn\Main\out\production\Main>jar cvf main.jar Student.class User.class
已添加清单
正在添加: Student.class(输入 = 889) (输出 = 478)(压缩了 46%)
正在添加: User.class(输入 = 356) (输出 = 251)(压缩了 29%)

3、打包 Dex 文件

打包 Dex 文件 :

首先配置下环境变量 , 将编译工具目录配置到环境变量中 , 这里选择使用 30.0.3 版本的编译工具 ( build-tools ) ;

D:\001_Develop\001_SDK\Sdk\build-tools\30.0.3

配置到环境变量 Path 中 ;

执行

dx --dex --output main.dex main.jar

命令 , 打包 Dex 文件 , 命令行输出 :

打包后的 main.dex 文件 ;

二、反编译 Dex 文件


使用如下命令 , 反编译 Dex 文件 :

dexdump -d -l plain main.dex

输出 Dex 文件的内容 :

D:\002_Project\004_Java_Learn\Main\out\production\Main>dexdump -d -l plain main.dex
Processing 'main.dex'...
Opened 'main.dex', DEX version '035'
Class #0            -Class descriptor  : 'LStudent;'Access flags      : 0x0001 (PUBLIC)Superclass        : 'Ljava/lang/Object;'Interfaces        -Static fields     -Instance fields   -#0              : (in LStudent;)name          : 'age'type          : 'I'access        : 0x0002 (PRIVATE)#1              : (in LStudent;)name          : 'name'type          : 'Ljava/lang/String;'access        : 0x0002 (PRIVATE)Direct methods    -#0              : (in LStudent;)name          : '<init>'type          : '()V'access        : 0x10001 (PUBLIC CONSTRUCTOR)code          -registers     : 1ins           : 1outs          : 1insns size    : 4 16-bit code units
0001b8:                                        |[0001b8] Student.<init>:()V
0001c8: 7010 0800 0000                         |0000: invoke-direct {v0}, Ljava/lang/Object;.<init>:()V // method@0008
0001ce: 0e00                                   |0003: return-voidcatches       : (none)positions     :0x0000 line=1locals        :0x0000 - 0x0004 reg=0 this LStudent;Virtual methods   -#0              : (in LStudent;)name          : 'ageIncrease'type          : '()V'access        : 0x0001 (PUBLIC)code          -registers     : 2ins           : 1outs          : 0insns size    : 12 16-bit code units
0001d0:                                        |[0001d0] Student.ageIncrease:()V
0001e0: 1d01                                   |0000: monitor-enter v1
0001e2: 5210 0000                              |0001: iget v0, v1, LStudent;.age:I // field@0000
0001e6: d800 0001                              |0003: add-int/lit8 v0, v0, #int 1 // #01
0001ea: 5910 0000                              |0005: iput v0, v1, LStudent;.age:I // field@0000
0001ee: 1e01                                   |0007: monitor-exit v1
0001f0: 0e00                                   |0008: return-void
0001f2: 0d00                                   |0009: move-exception v0
0001f4: 1e01                                   |000a: monitor-exit v1
0001f6: 2700                                   |000b: throw v0catches       : 10x0001 - 0x000b<any> -> 0x0009positions     :0x0000 line=220x0001 line=230x0007 line=240x0008 line=250x0009 line=24locals        :0x0000 - 0x000c reg=1 this LStudent;#1              : (in LStudent;)name          : 'getAge'type          : '()I'access        : 0x0001 (PUBLIC)code          -registers     : 2ins           : 1outs          : 0insns size    : 3 16-bit code units
000204:                                        |[000204] Student.getAge:()I
000214: 5210 0000                              |0000: iget v0, v1, LStudent;.age:I // field@0000
000218: 0f00                                   |0002: return v0catches       : (none)positions     :0x0000 line=14locals        :0x0000 - 0x0003 reg=1 this LStudent;#2              : (in LStudent;)name          : 'getName'type          : '()Ljava/lang/String;'access        : 0x0001 (PUBLIC)code          -registers     : 2ins           : 1outs          : 0insns size    : 3 16-bit code units
00021c:                                        |[00021c] Student.getName:()Ljava/lang/String;
00022c: 5410 0100                              |0000: iget-object v0, v1, LStudent;.name:Ljava/lang/String; // field@0001
000230: 1100                                   |0002: return-object v0catches       : (none)positions     :0x0000 line=6locals        :0x0000 - 0x0003 reg=1 this LStudent;#3              : (in LStudent;)name          : 'setAge'type          : '(I)V'access        : 0x0001 (PUBLIC)code          -registers     : 2ins           : 2outs          : 0insns size    : 3 16-bit code units
000234:                                        |[000234] Student.setAge:(I)V
000244: 5901 0000                              |0000: iput v1, v0, LStudent;.age:I // field@0000
000248: 0e00                                   |0002: return-voidcatches       : (none)positions     :0x0000 line=180x0002 line=19locals        :0x0000 - 0x0003 reg=0 this LStudent;0x0000 - 0x0003 reg=1 age I#4              : (in LStudent;)name          : 'setName'type          : '(Ljava/lang/String;)V'access        : 0x0001 (PUBLIC)code          -registers     : 2ins           : 2outs          : 0insns size    : 3 16-bit code units
00024c:                                        |[00024c] Student.setName:(Ljava/lang/String;)V
00025c: 5b01 0100                              |0000: iput-object v1, v0, LStudent;.name:Ljava/lang/String; // field@0001
000260: 0e00                                   |0002: return-voidcatches       : (none)positions     :0x0000 line=100x0002 line=11locals        :0x0000 - 0x0003 reg=0 this LStudent;0x0000 - 0x0003 reg=1 name Ljava/lang/String;source_file_idx   : 7 (Student.java)Class #1            -Class descriptor  : 'LUser;'Access flags      : 0x0001 (PUBLIC)Superclass        : 'Ljava/lang/Object;'Interfaces        -Static fields     -Instance fields   -#0              : (in LUser;)name          : 'age'type          : 'I'access        : 0x0002 (PRIVATE)Direct methods    -#0              : (in LUser;)name          : '<init>'type          : '()V'access        : 0x10001 (PUBLIC CONSTRUCTOR)code          -registers     : 2ins           : 1outs          : 1insns size    : 7 16-bit code units
000264:                                        |[000264] User.<init>:()V
000274: 7010 0800 0100                         |0000: invoke-direct {v1}, Ljava/lang/Object;.<init>:()V // method@0008
00027a: 1200                                   |0003: const/4 v0, #int 0 // #0
00027c: 5910 0200                              |0004: iput v0, v1, LUser;.age:I // field@0002
000280: 0e00                                   |0006: return-voidcatches       : (none)positions     :0x0000 line=10x0003 line=2locals        :0x0000 - 0x0007 reg=1 this LUser;Virtual methods   -#0              : (in LUser;)name          : 'increase'type          : '()V'access        : 0x20001 (PUBLIC DECLARED_SYNCHRONIZED)code          -registers     : 2ins           : 1outs          : 0insns size    : 12 16-bit code units
000284:                                        |[000284] User.increase:()V
000294: 1d01                                   |0000: monitor-enter v1
000296: 5210 0200                              |0001: iget v0, v1, LUser;.age:I // field@0002
00029a: d800 0001                              |0003: add-int/lit8 v0, v0, #int 1 // #01
00029e: 5910 0200                              |0005: iput v0, v1, LUser;.age:I // field@0002
0002a2: 1e01                                   |0007: monitor-exit v1
0002a4: 0e00                                   |0008: return-void
0002a6: 0d00                                   |0009: move-exception v0
0002a8: 1e01                                   |000a: monitor-exit v1
0002aa: 2700                                   |000b: throw v0catches       : 10x0001 - 0x0007<any> -> 0x0009positions     :0x0000 line=50x0007 line=60x0009 line=5locals        :0x0000 - 0x000c reg=1 this LUser;source_file_idx   : 8 (User.java)D:\002_Project\004_Java_Learn\Main\out\production\Main>

三、分析 Dex 文件


1、Student 类相关信息

#0 号 Class 类 , 类描述符是 LStudent; , 父类 Ljava/lang/Object;

Processing 'main.dex'...
Opened 'main.dex', DEX version '035'
Class #0            -Class descriptor  : 'LStudent;'Access flags      : 0x0001 (PUBLIC)Superclass        : 'Ljava/lang/Object;'

该类中有 222 个字段 , 分别是 name 和 age ;

  Instance fields   -#0              : (in LStudent;)name          : 'age'type          : 'I'access        : 0x0002 (PRIVATE)#1              : (in LStudent;)name          : 'name'type          : 'Ljava/lang/String;'access        : 0x0002 (PRIVATE)

构造函数方法 :

  Direct methods    -#0              : (in LStudent;)name          : '<init>'type          : '()V'access        : 0x10001 (PUBLIC CONSTRUCTOR)code          -registers     : 1ins           : 1outs          : 1insns size    : 4 16-bit code units

增加年龄方法 :

    public void ageIncrease(){synchronized(this) {this.age++;}}

对应

  Virtual methods   -#0              : (in LStudent;)name          : 'ageIncrease'type          : '()V'access        : 0x0001 (PUBLIC)code          -registers     : 2ins           : 1outs          : 0insns size    : 12 16-bit code units

其它方法省略 ;

2、User 类相关信息

第 222 个类 编号 #1 , 是 User 类 , 类描述符 LUser; , 有 age 字段 ;

Class #1            -Class descriptor  : 'LUser;'Access flags      : 0x0001 (PUBLIC)Superclass        : 'Ljava/lang/Object;'Interfaces        -Static fields     -Instance fields   -#0              : (in LUser;)name          : 'age'type          : 'I'access        : 0x0002 (PRIVATE)

构造方法反编译内容如下 :

  Direct methods    -#0              : (in LUser;)name          : '<init>'type          : '()V'access        : 0x10001 (PUBLIC CONSTRUCTOR)code          -registers     : 2ins           : 1outs          : 1insns size    : 7 16-bit code units

void increase() 方法对应反编译内容 :

  Virtual methods   -#0              : (in LUser;)name          : 'increase'type          : '()V'access        : 0x20001 (PUBLIC DECLARED_SYNCHRONIZED)code          -registers     : 2ins           : 1outs          : 0insns size    : 12 16-bit code units

【Java 虚拟机原理】Dalvik 虚拟机 ( 打包 Jar 文件和 Dex 文件 | 反编译 Dex 文件 | 分析 Dex 文件反编译结果 )相关推荐

  1. android -------- java虚拟机和Dalvik虚拟机

    2019独角兽企业重金招聘Python工程师标准>>> java虚拟机 虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的.Java虚拟机有自己完善的硬体 ...

  2. Java虚拟机和Dalvik虚拟机的区别

    java虚拟机和Dalvik虚拟机的区别 该文章是本人转载的,觉得写的不错,和大家分享一下 Google于2007年底正式发布了Android SDK, 作为 Android系统的重要特性,Dalvi ...

  3. (Android)java虚拟机和Dalvik虚拟机的区别

    Google于2007年底正式发布了Android SDK, 作为 Android系统的重要特性,Dalvik虚拟机也第一次进入了人们的视野.它对内存的高效使用,和在低速CPU上表现出的高性能,确实令 ...

  4. java dalvik_Java虚拟机和Dalvik虚拟机的区别

    java虚拟机和Dalvik虚拟机的区别: java虚拟机 Dalvik虚拟机 java虚拟机基于栈. 基于栈的机器必须使用指令来载入和操作栈上数据,所需指令更多更多 dalvik虚拟机是基于寄存器的 ...

  5. dalvik虚拟机与Java区别_05 Android---java虚拟机跟dalvik虚拟机的区别(从01开始点点入门,视频+笔记)...

    大家好,我是森森 这节课我简单给大家介绍一下java虚拟机跟安卓系统虚拟机的区别.可能时间太晚了,有点不在状态,也有点紧张,大家见谅. 05java虚拟机跟dalvik虚拟机的区别 这篇文章重点写一写 ...

  6. Android Dalvik虚拟机之Dalvik虚拟机的特点

    Google于2007年底正式发布了Android SDK,Dalvik虚拟机也第一次进入了人们的视野.它的作者是丹.伯恩斯坦(Dan Bornstein).Dalvik虚拟机作为Android平台的 ...

  7. Android安全与逆向之Java虚拟机和Dalvik虚拟机的区别

    Google于2007年底正式发布了Android SDK, 作为 Android系统的重要特性,Dalvik虚拟机也第一次进入了人们的视野.它对内存的高效使用,和在低速CPU上表现出的高性能,确实令 ...

  8. JAVA虚拟机、Dalvik虚拟机和ART虚拟机

    从Android5.0开始废弃了Dalvik,全面推行ART. Dalvik与ART的区别 (1)在Dalvik下,应用每次运行都需要通过即时编译器(JIT)将字节码转换为机器码,即每次都要编译加运行 ...

  9. python虚拟机原理_pvm虚拟机基本原理

    零.绪论:特别鸣谢下文博客,自己博客是对这篇博客的学习笔记: 一.三种文件: 1.pyc文件:py文件编译后的二进制文件. 2.pyo文件:优化后的py编译的文件. 3.pyd文件:其他语言编程的py ...

  10. 【Android 逆向】APK 文件处理脚本 ApkTool.py ( 脚本简介 | 用法 | 分析 APK 文件 )

    文章目录 一.APK 文件处理脚本 ApkTool.py 二.ApkTool.py 脚本用法 三.ApkTool.py 脚本分析 APK 输出结果 一.APK 文件处理脚本 ApkTool.py Ap ...

最新文章

  1. (10)Spring Boot修改端口号【从零开始学Spring Boot】
  2. linux运行炉石传说,使用Lutris在Linux上玩炉石传说
  3. 基尼指数——基尼系数是指国际上通用的、用以衡量一个国家或地区居民收入差距的常用指标。基尼系数介于0-1之间,基尼系数越大,表示不平等程度越高。...
  4. ES6/7 异步编程学习笔记
  5. 微信授权(Net Mvc)
  6. php jquery 全选删除,jQuery+php简单实现全选删除的方法
  7. c#中的DefWndProc是Control类的虚函数
  8. 关于二维数组取地址加以或减一解引用问题
  9. 机器学习笔记(十二)——马尔科夫模型
  10. JVM第三节:垃圾回收算法与垃圾回收器
  11. Spring with multiple transaction managers
  12. PuTTY/PuttyGen介绍
  13. 训练集、测试集、验证集之间的区别及理解
  14. Yii2基本概念之——事件(Event)
  15. excel公式不执行。原因是设置问题:公式->计算选项->手动
  16. 双动道岔计算机控制系统,车站信号自动控制习题.doc
  17. 同事辞职了,我一个人做两个人的活,公司又不招人了,该怎么办?
  18. Android11编译导入PRODUCT_BOOT_JARS
  19. C1083: 无法打开包括文件: plugin.moc: No such file or directory
  20. 多线程下SOCKET编程

热门文章

  1. Java网络编程从入门到精通(2):创建InetAddress对象的四个静态方法
  2. 后盾网lavarel视频项目---lavarel使用模型进行增删改查操作
  3. Python机器学习基础教程-第2章-监督学习之K近邻
  4. 使用subprocessm模块管理进程
  5. nginx反向代理cas-server之2:生成证书,centOS下使用openssl生成CA证书(根证书、server证书、client证书)...
  6. 扩展js string 方法
  7. Tarjan 复习小结
  8. Eclipse java项目转换为web项目
  9. BCB中获得RichEdit 默认行间距
  10. struts2文件下载出现Can not find a java.io.InputStream with the name的错误