我们知道,java是一种编译+解释的语言。最主要的目的是跨平台,为了实现跨平台,就决定了不能像c,c++那样直接把源代码编译成可执行文件,因为不同cpu,不同操作系统的指令封装格式是不一样的。java编译成的字节码文件与硬件和操作系统无关,这是跨平台基础,然后具体执行,再用各自平台解释器,解释成本地机器码。其中:虚拟机的目的就是把java编译生成的字节码文件翻译成机器码,供机器执行。
本文对JVM、Dalvik、ART做一个简单的对比:
一、编译生成的字节码格式:
JVM:.class文件每个类或者接口单独占据一个class文件,每个类单独管理,没有交叉弊端:
1)内存占用大,不适合于移动端
2)堆栈的加载模式导致加载速度慢
3)文件IO操作多,类查找慢
DVM、ART:.dex文件
Android SDK中有一个叫dx的工具负责将Java字节码转换为Dalvik字节码dex,整个工程的类信息都存放在一个dex文件中(不考虑dex分包的情况下)
优势:
1)dex文件整合了类信息,将多个class文件中公有的部分统一存放,去除冗余信息,占用内存变小。(去除了类文件中的冗余,同时使用共享的、特定类型的常量池机制来节省内存)
2)寄存器加载模式提升加载速度
二、DVM、ART对dex文件的优化
Dvm和Art都是处理由dx工具针对class字节码优化过后的dex文件(这个文件包含了程序中所有的
类,文件更小,执行速度更快)。
DVM:JIT(Just-In-Time)运行时编译,Google在2.2版本添加了JIT编译器,当App运行时,每当遇
到一个新类,JIT编译器就会对这个类进行编译,经过编译后的代码,会被优化成相当精简的原生型
指令码(即native code),这样在下次执行到相同逻辑的时候,速度就会更快。当然使用JIT也不一
定加快执行速度,如果大部分代码的执行次数很少,那么编译花费的时间不一定少于执行dex的时
间。Google当然也知道这一点,所以JIT不对所有dex代码进行编译,而是只编译执行次数较多的dex
为本地机器码。有一点需要注意,那就是dex字节码翻译成本地机器码是发生在应用程序的运行过程
中的,并且应用程序每一次重新运行的时候,都要做重做这个翻译工作,所以这个工作并不是一劳
永逸,每次重新打开App,都需要JIT编译。
ART:OAT(Ahead-Of-Time)预编译,android4.4.推出art虚拟机,使用OAT编译,应用在第一次安
装的时候,字节码就会预先编译成机器码,使其成为真正的本地应用。之后打开App的时候,不需要
额外的翻译工作,直接使用本地机器码运行,因此运行速度提高。但是安装过程相对会更耗时,apk
占据的rom空间会更大(10%-20%)。简而言之:ART是一个执行本地机器指令的虚拟机。
三、垃圾回收
1 ART对比DVM 做了GC的优化:
DVM:
当gc被触发时:
1、去查找所有活动的对象,这个时候整个程序与虚拟机内部的所有线程就会挂起,这样目的是在较少
的堆栈里找到所引用的对象.需要注意的是这个回收动作和应用程序非并发。
2、gc对符合条件的对象进行标记
3、gc对标记的对象进行回收
4、恢复所有线程的执行现场继续运行
Dalvik这么做的好处是,当pause了之后,GC势必是相当快速的.但是如果出现GC频繁并且内存吃紧势必
会导致UI卡顿,掉帧.操作不流畅等。
ART:
改善了Dalvik这种GC方式 , 主要的改善点在将其非并发过程改变成了部分并发.还有就是对内存的重
新分配管理。
当gc被触发时:
1、GC将会锁住Java堆,扫描并进行标记
2、标记完毕释放掉Java堆的锁,并且挂起所有线程
3、GC对标记的对象进行回收
4、恢复所有线程的执行现场继续运行
5、重复2-4直到结束
可以看出整个过程做到了部分并发使得时间缩短.据官方测试数据说gc效率提高2倍
2 ART对比DVM 提高了内存使用率,减少了内存碎片化
网友评论