头图

Dalvik 和 Java 字节码的比较

以下博客文章描述了 Dalvik 和 Java 字节码的主要异同。这对于了解 Dalvik 和 Java 的不同之处尤为重要,以便能够了解 Android 应用程序的特征和恶意行为。

Android 应用程序通常用 Java 语言编写,并在Dalvik 虚拟机 (DVM) 中执行,这与经典的Java 虚拟机 (JVM) 不同。DVM 由 Google 开发,针对移动操作系统(尤其是 Android 平台)的特性进行了优化。在 Dalvik 中运行的字节码通过使用转换工具 dx 翻译 Java .class 文件从传统的 JVM 字节码转换为 dex 格式. 与 DVM 不同,JVM 使用纯 Java 类文件。如果你想逆向一个Android应用程序,需要了解Dalvik字节码格式,以及你需要深入的静态和动态检测知识。威廉·恩克等作者在他们的论文《Android 应用程序安全性研究》中总结了 JVM 和 DVM 字节码之间的差异如下:

  1. 安卓应用架构

JVM 字节码由一个或多个 .class 文件组成(每个文件包含一个 Java 类)。在运行时,JVM 将从相应的 .class 文件中动态加载每个类的字节码。而 Dalvik 字节码仅由一个.dex文件组成,包含应用程序的所有类。下图展示了 .dex 文件的生成过程。Java 编译器创建 JVM 字节码后,Dalvik dx编译器删除所有 .class 文件并将它们重新编译为 Dalvik 字节码。之后dx将它们合并为一个.dex 文件。这个过程包括对应用程序基本元素(常量池、类定义和数据段)的翻译、重构和解释。常量池描述了所有常量,包括引用、方法名称和数字常量。类定义包括访问标志、类名等。 数据段包括目标 VM 执行的所有函数代码以及类和函数的相关信息(例如 DVM 使用的寄存器数量、局部变量列表、操作数堆栈大小)和实例变量。

image.png

  1. 寄存器结构

DVM 是基于寄存器的,而 JVM 是基于栈的。在 JVM 字节码中,局部变量会被列在局部变量列表中,然后被压入堆栈供操作码操作。此外,JVM 还可以直接在堆栈上工作,而无需将局部变量显式存储到变量列表中。在 Dalvik 字节码中,局部变量将分配给 16 个可用寄存器中的任何一个(原文216 个寄存器,疑似有误)。Dalvik 操作码不访问堆栈中的元素。相反,它们直接对寄存器进行操作。

  1. 指令集

Dalvik 有 218 个操作码,它们与 Java 中的 200 个操作码有本质的不同。例如,有十几种操作码用于在堆栈和局部变量列表之间传输数据,而在 Dalvik 中完全没有。Dalvik 中的指令比 Java 中的要长,因为它们中的大多数都包含寄存器的源地址和目标地址。有关 Dalvik 操作码的全面概述,请参阅 Gabor PallerAndroid 开发人员的博客文章

  1. 常量池结构

JVM 字节码需要从所有 .class 文件中循环迭代出了全部常量的常量池,例如引用的函数名称。通过为 Dalvik 中所有类的引用提供一个常量池,dx 编译器消除了迭代。此外,dx 通过使用内联技术删除了一些常量。因此,在 dx 编译期间,整数、长整数以及单浮点数和双浮点数常量都消失了。

  1. 模糊的原始类型

在 JVM 中,整数和单浮点常量的操作码是不同的,长整数和双浮点常量也是如此。相对应的 Dalvik 为整数和浮点常量实现了相同的操作码。

  1. 空引用

Dalvik 字节码没有特定的Null类型。相反,Dalvik 使用 0 值常量。因此,应正确区分常数 0 的含糊含义。

  1. 对象引用

JVM 字节码使用不同的操作码进行对象引用比较和空类型比较,而 Dalvik 将它们简化为一个操作码。因此,在反编译过程中必须恢复比较对象的类型信息。

  1. 原始类型数组的存储

Dalvik 使用不确定的操作码对数组进行操作,而 JVM 使用定义的操作码。必须恢复数组类型信息才能正确转换。

[链接]

12.6k 声望
4.7k 粉丝
0 条评论
推荐阅读
从原生 JavaScript 到 React
React 是一个用于构建用户界面的 JavaScript 框架。它可用于通过动态操作页面内容来创建 JavaScript 应用程序。浏览器已经提供了在页面中创建元素的 API,即 DOM,所以新手可能想知道 React 带来了什么以及它与 D...

Yujiaao7阅读 3.4k

Java 领域概念:JDK、JRE、JVM
JVM 全称 Java Virtual Mechinal,即 Java 虚拟机。JVM 是驻留于内存中的抽象计算机,可以理解为一个虚拟的计算机,它是通过在真实计算机上仿真模拟各种计算机功能来实现的,具有处理器、堆栈、寄存器等完善的硬...

千猫阅读 2.2k

jvm垃圾回收机制
主要分为Eden、From、To三个区域,其中,默认内存占用比例为8:1:1存活对象进入年轻代的条件:新产生的对象优先分配到老年代(除大对象,大对象会优先分配到老年代)

Smile3k阅读 828

面试八股文(五)--类的加载和双亲委派机制
答:java时分两步的,编译和运行,类的加载指的是将编译生成的类的class文件读入内存,并为之创建一个java.lang.Class对象。类的加载过程是由类加载器来完成,而类加载器由JVM提供。

原来是小袁呐阅读 763

常量池、常量、静态变量
虚拟机把描述类的class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的数据类型,这就是虚拟机的类加载机制。

KerryWu阅读 735

有了HotSpot JVM为什么还需要OpenJ9?
OpenJ9是一个致力于构建更小内存使用,更快启动速度和更高吞吐量的独立实现的Java虚拟机。项目由IBM发起,并在之后开源并捐赠给Eclipse基金会。

骑牛上青山2阅读 308

大厂敲门砖,Github霸榜的顶级并发编程宝典被我搞到手了!
并发编程的目的是为了提高程序的执行速度,但是并不意味着启动更多的线程会达到更好的并发效果,并发编程还会引起死锁 , 上下文频繁切换 , 线程不安全等问题。并发编程作为Java程序员最重要的技能之一,也是最难...

Java架构师阅读 622

[链接]

12.6k 声望
4.7k 粉丝
宣传栏