art
adb shell getprop |grep vm 
指定虚拟机运行方式:使用libart.so
[persist.sys.dalvik.vm.lib.2]: [libart.so]
    Dalvik虚拟机与Java虚拟机的最显著区别是它们分别具有不同的类文件格式以及指令集。Dalvik虚拟机使用的是dex(Dalvik Executable)格式的类文件,而Java虚拟机使用的是class格式的类文件。一个dex文件可以包含若干个类,而一个class文件只包括一个类。由于一个dex文件可以包含若干个类,因此它就可以将各个类中重复的字符串和其它常数只保存一次,从而节省了空间,这样就适合在内存和处理器速度有限的手机系统中使用。一般来说,包含有相同类的未压缩dex文件稍小于一个已经压缩的jar文件。
    Dalvik虚拟机使用的指令是基于寄存器的,而Java虚拟机使用的指令集是基于堆栈的。基于堆栈的指令很紧凑,例如,Java虚拟机使用的指令只占一个字节,因而称为字节码。基于寄存器的指令由于需要指定源地址和目标地址,因此需要占用更多的指令空间,例如,Dalvik虚拟机的某些指令需要占用两个字节。基于堆栈和基于寄存器的指令集各有优劣,一般而言,执行同样的功能,前者需要更多的指令(主要是load和store指令),而后者需要更多的指令空间。需要更多指令意味着要多占用CPU时间,而需要更多指令空间意味着数据缓冲(d-cache)更易失效。
    此外,还有一种观点认为,基于堆栈的指令更具可移植性,因为它不对目标机器的寄存器进行任何假设。然而,基于寄存器的指令由于对目标机器的寄存器进行了假设,因此,它更有利于进行AOT(ahead-of-time)优化。 所谓AOT,就是在解释语言程序运行之前,就先将它编译成本地机器语言程序。AOT本质上是一种静态编译,它是相对于JIT而言的,也就是说,前者是在程序运行前进行编译,而后者是在程序运行时进行编译。运行时编译意味着可以利用运行时信息来得到比较静态编译更优化的代码,同时也意味不能进行某些高级优化,因为优化过程太耗时了。另一方面,运行前编译由于不占用程序运行时间,因此,它就可以不计时间成本来优化代码。无论AOT,还是JIT,最终的目标都是将解释语言编译为本地机器语言,而本地机器语言都是基于寄存器来执行的,因此,在某种程度来讲,基于寄存器的指令更有利于进行AOT编译以及优化。
art虚拟机都在尽最大的努力来优化自身,这些措施包括:
        1. 将多个类文件收集到同一个dex文件中,以便节省空间;
        2. 使用只读的内存映射方式加载dex文件,以便可以多进程共享dex文件,节省程序加载时间;
        3. 提前调整好字节序(byte order)和字对齐(word alignment)方式,使得它们更适合于本地机器,以便提高指令执行速度;
        4. 尽量提前进行字节码验证(bytecode verification),提高程序的加载速度;
        5. 需要重写字节码的优化要提前进行。
        6. AOT预编译方式
 一. 内存管理
    Dalvik虚拟机的内存大体上可以分为Java Object Heap、Bitmap Memory和Native Heap三种。
    Java Object Heap是用来分配Java对象的,也就是我们在代码new出来的对象都是位于Java Object Heap上的。Dalvik虚拟机在启动的时候,可以通过-Xms和-Xmx选项来指定Java Object Heap的最小值和最大值
mutian@mutian:~/share$ adb shell getprop |grep -i heapsize
[dalvik.vm.heapsize]: [256m]
public class ActivityManager { ...... /** * Return the approximate per-application memory class of the current * device. This gives you an idea of how hard a memory limit you should * impose on your application to let the overall system work best. The * returned value is in megabytes; the baseline Android memory class is * 16 (which happens to be the Java heap limit of those devices); some * device with more memory may return 24 or even higher numbers. */ public int getMemoryClass() { return staticGetMemoryClass(); } /** @hide */ static public int staticGetMemoryClass() { // Really brain dead right now -- just take this from the configured // vm heap size, and assume it is in megabytes and thus ends with "m". String vmHeapSize = SystemProperties.get("dalvik.vm.heapsize", "16m"); return Integer.parseInt(vmHeapSize.substring(0, vmHeapSize.length()-1)); } ...... }
这个Java Object Heap的最大值也就是我们平时所说的Android应用程序进程能够使用的最大内存。这里必须要注意的是,Android应用程序进程能够使用的最大内存指的是能够用来分配Java Object的堆。
在HoneyComb以及更高的版本中,Bitmap Memory就直接是在Java Object Heap中分配了,这样就可以直接接受GC的管理。
Native Heap就是在Native Code中使用malloc等分配出来的内存,这部分内存是不受Java Object Heap的大小限制的,也就是它可以自由使用,当然它是会受到系统的限制。但是有一点需要注意的是,
不要因为Native Heap可以自由使用就滥用,因为滥用Native Heap会导致系统可用内存急剧减少,从而引发系统采取激进的措施来Kill掉某些进程,用来补充可用内存,这样会影响系统体验。
为了避免出现内存问题,在Android系统内部的C++代码,大量地使用了智能指针来自动管理对象的生命周期。
JIT是相对AOT而言的,即JIT是在程序运行的过程中进行编译的,而AOT是在程序运行前进行编译的.
/dalvikvm(9050): GC_CONCURRENT freed 2049K, 65% free 3571K/9991K, external 4703K/5261K, paused 2ms+2ms  
GC_CONCURRENT表示GC原因,2049K表示总共回收的内存,3571K/9991K表示Java Object Heap统计,即在9991K的Java Object Heap中,有3571K是正在使用的,
4703K/5261K表示External Memory统计,即在5261K的External Memory中,有4703K是正在使用的,2ms+2ms表示垃圾收集造成的程序中止时间。
    一般来说,虚拟机的进程和线程都是与目标机器本地操作系统的进程和线程一一对应的,这样做的好处是可以使本地操作系统来调度进程和线程。进程和线程调度是操作系统的核心模块,它的实现是非常复杂的,特别是考虑到多核的情况,因此,就完全没有必要在虚拟机中提供一个进程和线程库。
    Dalvik虚拟机运行在Linux操作系统之上。我们知道,Linux操作系统并没有纯粹的线程概念,只要两个进程共享同一个地址空间,那么就可以认为它们同一个进程的两个线程。Linux操作系统提供了两个fork和clone两个调用,其中,前者就是用来创建进程的,而后者就是用来创建线程的。
Zygote进程在启动过程中创建Dalvik虚拟机的时候,只有一个堆。但是当Zygote进程在fork第一个应用程序进程之前,会将已经使用了的那部分堆内存划分为一部分,还没有使用的堆内存划分为另外一部分。前者就称为Zygote堆,后者就称为Active堆。以后无论是Zygote进程,还是应用程序进程,当它们需要分配对象的时候,都在Active堆上进行。这样就可以使得Zygote堆尽可能少地被执行写操作,因而就可以减少执行写时拷贝的操作。在Zygote堆里面分配的对象其实主要就是Zygote进程在启动过程中预加载的类、资源和对象了。这意味着这些预加载的类、资源和对象可以在Zygote进程和应用程序进程中做到长期共享。这样既能减少拷贝操作,还能减少对内存的需求。
http://blog.csdn.net/luoshengyang/article/details/41338251
                    
                
                
            
        
浙公网安备 33010602011771号