davlik虚拟机内存管理之一——内存分配
转载自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虚拟机内存管理之一——内存分配的更多相关文章
- Java内存管理-JVM内存模型以及JDK7和JDK8内存模型对比总结(三)
勿在流沙住高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 上一篇分享了JVM及其启动流程,今天介绍一下JVM内部的一些区域,以及具体的区域在运行 ...
- SAP专家培训之Netweaver ABAP内存管理和内存调优最佳实践
培训者:SAP成都研究院开发人员Jerry Wang 1. Understanding Memory Objects in ABAP Note1: DATA itab WITH HEADER LINE ...
- 【深入理解Java虚拟机】自动内存管理机制——内存区域划分
Java与C++之间有一堵有内存动态分配和垃圾收集技术所围成的"高墙",墙外面的人想进去,墙里面的人却想出来.C/C++程序员既拥有每一个对象的所有权,同时也担负着每一个对象生 ...
- JVM堆内存管理与自定义分配参数详解
堆内存模型: 在Java中,堆被划分成两个不同的区域:新生代(Young),老年代(Old).而Permanent属于永久代(方法区),不属于堆内存.新生代又被分为了三个区域:Eden,from s ...
- STL内存管理器的分配策略
STL提供了很多泛型容器,如vector,list和map.程序员在使用这些容器时只需关心何时往容器内塞对象,而不用关心如何管理内存,需要用多少内存,这些STL容器极大地方便了C++程序的编写.例如可 ...
- java的内存管理 对象的分配与释放
分配 程序员通过new为每个对象申请内存空间(基本类型除外),所有对象都在堆中分配空间:释放:对象的释放是由垃圾回收机制决定和执行的. Java内存分为两种:栈内存和堆内存 (1)在函数中定义的基本类 ...
- Android 之 内存管理-查看内存泄露(三)
概述 在android的开发中,要时刻主要内存的分配和垃圾回收,因为系统为每一个dalvik虚拟机分配的内存是有限的,在google的G1中,分配的最大堆大小只有16M,后来的机器一般都为24M,实在 ...
- JVM自动内存管理-Java内存区域与内存溢出异常
摘要: JVM内存的划分,导致内存溢出异常的可能区域. 1. JVM运行时内存区域 JVM在执行Java程序的过程中会把它所管理的内存划分为以下几个区域: 1.1 程序计数器 程序计数器是一块较小的内 ...
- Delphi的内存管理及内存泄露问题 FastMM4
这几天因为一个程序长时间运行出现比较严重的内存泄露问题,开始关注了一下内存管理方面的东西,以前也注意内存管理,创建了对象及时释放,但总有忘了处理的情况. 在Delphi中没有自动回收机制,所以一定要及 ...
随机推荐
- struts2 拦截器 interceptor
struts2 拦截器详解:http://struts2.group.iteye.com/group/wiki/1397-deep-into-struts2-interceptors
- eclipse 连接 mysql
1.下载驱动. 2.eclipse->add extend jars -> 添加驱动. 3.测试: 在mysql 建立数据库和表,在eclipse 里对数据库进行操作. 代码: mysql ...
- 使用OpenGL ES绘制3D图形
如果应用定义的顶点不在同一个平面上,并且使用三角形把合适的顶点连接起来,就可以绘制出3D图形了. 使用OpenGL ES绘制3D图形的方法与绘制2D图形的步骤大致相同,只是绘制3D图形需要定义更多的 ...
- [Jquery]滑动门效果
$(function(){ var $box=$("#box"); var $img=$box.find("img"); var imgWid ...
- [Js]缓冲运动
一.运动框架 1.在开始运动时,关闭已有定时器(否则会不断有新的定时器执行) 2.把运动和停止隔开(if/else) 二.缓冲运动 逐渐变慢,最后停止(距离越远速度越大) 速度=(目标值-当前值)/缩 ...
- HDU 3533 Escape bfs 难度:1
http://acm.hdu.edu.cn/showproblem.php?pid=3533 一道普通的bfs,但是由于代码实现出了bug还是拖了很久甚至对拍了 需要注意的是: 1.人不能经过炮台 2 ...
- wScratchPad 实现刮刮卡效果
插件网址http://wscratchpad.websanova.com/
- struts2 ModelDriven 和 Preparable 拦截器
Struts2 运行流程图-1
- (三)获取iphone的IMSI
今天的任务是 iPhone上怎样获取 imsi 信息 来判断所属运营商,资料找了很久!总体有两种方案,但是其中一种好像不行 这里我都记录下来吧: 1: 这是使用coreTelephony.framew ...
- IIS6的session丢失问题
解决办法: a IIS6中相比IIS5增加了一个应用程序池,默认是使用DefaultAppPool. b 先为站点建立一个应用程序池,打开IIS管理器,右键点击应用程序池-新建 ...