转载自http://www.miui.com/thread-74715-1-1.html

dalvik虚拟机是Google在Android平台上的Java虚拟机的实现,内存管理是dalvik虚拟机中的一个重要组件。

从概念上来说,内存管理的核心就是两个部分:分配内存和回收内存。Java语言使用new操作符来分配内存,但是与C/C++等语言不同的是,Java语言并没有提供任何操作来释放内存,而是通过一种叫做垃圾收集的机制来回收内存。对于内存管理的实现,我们通过三个方面来加以分析:内存分配,内存回收和内存管理调试。本文就是这一系列文章的第一篇,分析dalvik虚拟机是如何分配内存的。

1. 对象布局

内存管理的主要操作之一是为Java对象分配内存,Java对象在虚拟机中的内存布局如下:

所有的对象都有一个相同的头部clazz和lock。
(1)clazz:clazz指向该对象的类对象,类对象用来描述该对象所属的类,这样可以很容易的从一个对象获取该对象所属的类的具体信息。
(2)lock:是一个无符号整数,用以实现对象的同步。
(3)data:存放对象数据,根据对象的不同数据区的大小是不同的。

2. 堆

堆是dalvik虚拟机从操作系统分配的一块连续的虚拟内存。heapBase是堆的起始地址,heapLimit是堆的最大地址,堆大小的最大值可以通过-Xmx选项或dalvik.vm.heapsize指定。在原生系统中,一般dalvik.vm.heapsize值是32M,在MIUI中我们将其设为64M。

3. 堆内存位图

在虚拟机中维护了两个对应于堆内存的位图,称为liveBits和markBits。

在对象布局中,我们看到对象最小占用8个字节。在为对象分配内存时要求必须8字节对齐。这也就是说,对象的大小会调整为8字节的倍数。比如说一个对象的实际大小是13字节,但是在分配内存的时候分配16字节。因此所有对象的起始地址一定是8字节的倍数。堆内存位图就是用来描述堆内存的,每一个bit描述8个字节,因此堆内存位图的大小是堆的64分之一。对于MIUI的实现来说,这两个位图各占1M。

liveBits的作用是用来跟踪堆中已分配的内存,每分配一个对象时,对象的内存起始地址对应于位图中的位被设为1。在下一篇垃圾收集中我们会进一步的分析liveBits和markBits这两个位图的作用。

4. 堆的内存管理

在dalvik虚拟机实现中,是通过底层的bionic C库的malloc/free操作来分配/释放内存的。bionic C库的malloc/free操作是基于DougLea的实现(dlmalloc),这是一个被广泛使用,久经考验的C内存管理库,本文不展开dlmalloc的具体实现,有兴趣的读者请参考http://g.oswego.edu/dl/html/malloc.html

5. dvmAllocObject

在dalvik虚拟机中,new操作符最终对应dvmAllocObject这个C函数。下面通过伪码的形式列出dvmAllocObject的实现。
Object*dvmAllocObject(ClassObject *clazz, int flags) {
        n = get object size from class object clazz
        first try: allocate n bytes from heap
        if first try failed {
                run garbage collector without collecting soft references
                second try: allocate n bytes from heap
        }
        if second try failed {
                third try: grow the heap and allocate n bytes from heap
                (注释:堆是虚拟内存,一开始并未分配所有的物理内存,只要还没有达到虚拟内存的最大值,可以通过获取更多物理内存的方式来扩展堆)
        }
        if third try failed {
                run garbage collector with collecting soft references
                fourth try: grow the heap and allocate n bytes from heap
        }
        if fourth try failed, return null pointer, dalvik vm will abort
}

可以看出,为了分配内存,虚拟机尽了最大的努力,做了四次尝试。其中进行了两次垃圾收集,第一次不收集SoftReference,第二次收集SoftReference。从中我们也可以看出垃圾收集的时机,实质上在dalvik虚拟机实现中有3个时机可以触发垃圾收集的运行:
(1)程序员显式的调用System.gc()
(2)内存分配失败时
(3)如果分配的对象大小超过384KB,运行并发标记(concurrent mark),在下一篇文章中会介绍什么是并发标记

6.小结
在dalvik虚拟机中,内存分配操作的流程相对比较简单直观,从一个堆中分配可用内存,分配失败时触发垃圾收集,接下来的文章中我们仔细分析dalvik虚拟机的垃圾收集。

davlik虚拟机内存管理之一——内存分配的更多相关文章

  1. Java内存管理-JVM内存模型以及JDK7和JDK8内存模型对比总结(三)

    勿在流沙住高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 上一篇分享了JVM及其启动流程,今天介绍一下JVM内部的一些区域,以及具体的区域在运行 ...

  2. SAP专家培训之Netweaver ABAP内存管理和内存调优最佳实践

    培训者:SAP成都研究院开发人员Jerry Wang 1. Understanding Memory Objects in ABAP Note1: DATA itab WITH HEADER LINE ...

  3. 【深入理解Java虚拟机】自动内存管理机制——内存区域划分

      Java与C++之间有一堵有内存动态分配和垃圾收集技术所围成的"高墙",墙外面的人想进去,墙里面的人却想出来.C/C++程序员既拥有每一个对象的所有权,同时也担负着每一个对象生 ...

  4. JVM堆内存管理与自定义分配参数详解

    堆内存模型: 在Java中,堆被划分成两个不同的区域:新生代(Young),老年代(Old).而Permanent属于永久代(方法区),不属于堆内存.新生代又被分为了三个区域:Eden,from  s ...

  5. STL内存管理器的分配策略

    STL提供了很多泛型容器,如vector,list和map.程序员在使用这些容器时只需关心何时往容器内塞对象,而不用关心如何管理内存,需要用多少内存,这些STL容器极大地方便了C++程序的编写.例如可 ...

  6. java的内存管理 对象的分配与释放

    分配 程序员通过new为每个对象申请内存空间(基本类型除外),所有对象都在堆中分配空间:释放:对象的释放是由垃圾回收机制决定和执行的. Java内存分为两种:栈内存和堆内存 (1)在函数中定义的基本类 ...

  7. Android 之 内存管理-查看内存泄露(三)

    概述 在android的开发中,要时刻主要内存的分配和垃圾回收,因为系统为每一个dalvik虚拟机分配的内存是有限的,在google的G1中,分配的最大堆大小只有16M,后来的机器一般都为24M,实在 ...

  8. JVM自动内存管理-Java内存区域与内存溢出异常

    摘要: JVM内存的划分,导致内存溢出异常的可能区域. 1. JVM运行时内存区域 JVM在执行Java程序的过程中会把它所管理的内存划分为以下几个区域: 1.1 程序计数器 程序计数器是一块较小的内 ...

  9. Delphi的内存管理及内存泄露问题 FastMM4

    这几天因为一个程序长时间运行出现比较严重的内存泄露问题,开始关注了一下内存管理方面的东西,以前也注意内存管理,创建了对象及时释放,但总有忘了处理的情况. 在Delphi中没有自动回收机制,所以一定要及 ...

随机推荐

  1. 创建论坛Discuz

    下载discuz! mkdir /data/wwwcd /data/wwwwget  http://download.comsenz.com/DiscuzX/3.2/Discuz_X3.2_SC_GB ...

  2. 关于java中super()和this()

    在java中this表示当前类中的对象,super则表示父类中的对象.比如当前对象的某个方法,或当前对象的某个成员,你便可以利用this来实现这个目的,当然,this的另一个用途是调用当前对象的另一个 ...

  3. STM32之延时秒,毫秒,微秒

    #include "delay.h" #include "stdint.h" #include "stm32f10x.h" ; //us延时 ...

  4. JS 数组去重!!!

    var arr = [1,2,3,1,1,1,3,5,3,6,2]; var newArr=[]; for(var i = 0; i < arr.length-1; i++){ var onOf ...

  5. 知道创宇研发技能表v2.2

    知道创宇研发技能表v2.2 2014/3/9 发布 by @知道创宇(www.knownsec.com) @余弦 & 行之 知道创宇是国内Geek十足且普遍被认为特别有前途的互联网安全公司, ...

  6. Ubuntu 14.10 下Ganglia监控Hadoop集群

    前提是已经安装好Ganglia和Hadoop集群 1 Master节点配置hadoop-metrics2.properties # syntax: [prefix].[source|sink|jmx] ...

  7. 修复win8引导

    格式化那个350MB的分区(Win8安装盘启动之后挂载在c:之后,用Win8的安装U盘,进去修复模式,然后进入高级选项的命令行提示符模式.接着,转到安装现有Win8的分区(Win8安装盘启动之后挂载在 ...

  8. 2016-1-6第一个完整APP 私人通讯录的实现 4:编辑联系人

    一:建立编辑联系人的controller,并使其拥有模型contact,且有协议.代码如下 #import <UIKit/UIKit.h> #import "contact.h& ...

  9. ubuntu  输入时弹出剪切板候选项

    fcitx很坑的把这个功能的快捷键设置成了ctrl + ;结果我在用vim的时候怎么也 没法输入command 不知道是哪次更新引入的,简直是坑人! 我找了半天系统设置都没找到这个快捷键是在哪设置的. ...

  10. RFID Hacking②:PM3入门指南

    0×00 前言 Proxmark3是由Jonathan Westhues在做硕士论文中研究Mifare Classic时设计.开发的一款开源硬件,可以用于RFID中嗅探.读取以及克隆等相关操作,如:P ...