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虚拟机实现中,是通过底层的bionicC库的malloc/free操作来分配/释放内存的。bionicC库的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 form 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 hap 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虚拟机的垃圾收集。

转载于:https://blog.51cto.com/caifly/1367895

davlik虚拟机内存管理之一——内存分配相关推荐

  1. 程序员交流平台_Java虚拟机所管理的内存到底有哪些?Java程序员必看栏目(上)...

    Java虚拟机所管理的内存将会包括以下几个运行时数据区域: 1,程序计数器Program Counter Register 一块较小的内存空间,非所有线程共享的区域,每个程序计数器,都会记录当前线程执 ...

  2. 【Linux 内核 内存管理】内存管理架构 ④ ( 内存分配系统调用过程 | 用户层 malloc free | 系统调用层 brk mmap | 内核层 kmalloc | 内存管理流程 )

    文章目录 一.内存分配系统调用过程 ( 用户层 | 系统调用 | 内核层 ) 二.内存管理流程 一.内存分配系统调用过程 ( 用户层 | 系统调用 | 内核层 ) " 堆内存 " ...

  3. Linux内存管理:内存分配:slab分配器

    <linux内核之slob.slab.slub> <Linux内核:kmalloc()和SLOB.SLAB.SLUB内存分配器> <Linux内存管理:内存分配:slab ...

  4. 【Linux 内核 内存管理】物理分配页 ⑨ ( __alloc_pages_slowpath 慢速路径调用函数源码分析 | retry 标号代码分析 )

    文章目录 一.retry 标号代码分析 二.retry 标号完整代码 在 [Linux 内核 内存管理]物理分配页 ② ( __alloc_pages_nodemask 函数参数分析 | __allo ...

  5. 【Linux 内核 内存管理】物理分配页 ⑦ ( __alloc_pages_slowpath 慢速路径调用函数源码分析 | 判断页阶数 | 读取 mems_allowed | 分配标志位转换 )

    文章目录 一.__alloc_pages_slowpath 慢速路径调用函数 二.判断页阶数 三.读取进程 mems_allowed 成员 四.分配标志位转换 五.__alloc_pages_slow ...

  6. 【Linux 内核 内存管理】物理分配页 ⑧ ( __alloc_pages_slowpath 慢速路径调用函数源码分析 | 获取首选内存区域 | 异步回收内存页 | 最低水线也分配 | 直接分配 )

    文章目录 一.获取首选内存区域 二.异步回收内存页 三.最低水线也分配 四.直接分配内存 在 [Linux 内核 内存管理]物理分配页 ② ( __alloc_pages_nodemask 函数参数分 ...

  7. 内存管理-动态分区分配方式模拟

    内存管理 - 动态分区分配方式模拟 操作系统第二次课程作业 - 动态分区分配方式模拟 项目需求 假设初始态下,可用内存空间为640K,并有下列请求序列,请分别用首次适应算法和最佳适应算法进行内存块的分 ...

  8. 内存管理:内存的分配与回收

    内存管理:内存的分配与回收 1 内存的分配与回收 1.1 连续分配 1.1.1 单一连续分配 1.1.2 固定分区分配 1.1.3 动态分区分配 1.2 非连续分配 1.2.1 分段存储管理 1.2. ...

  9. Linux内存管理:内存寻址之分段机制与分页机制

    目录 Linux 内存寻址之分段机制 前言 分段到底是怎么回事? 实模式的诞生(16位处理器及寻址) 保护模式的诞生(32位处理器及寻址) IA32的内存寻址机制 寻址硬件 IA32的三种地址 MMU ...

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

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

最新文章

  1. The C10K problem原文翻译
  2. python 描述器_python 描述器
  3. linux查看硬件信息
  4. 一文了解OOM及解决方案
  5. red hat linux挂载u盘,请问怎样在Red Hat 9.0中使用U盘?
  6. c语言使用正则,C语言中使用正则表达式
  7. Java编译器优化与运行期优化技术浅析
  8. poj 3181 Dollar Dayz (整数划分问题---递归+DP)
  9. HCI实验之问卷设计
  10. Securable 测不准
  11. 3DMax VRay 渲染笔记
  12. JavaWeb 图书推荐
  13. 怎么证明根号2是无理数,我们来推导和计算,还有逼格极高的算法
  14. Counting Liars
  15. 报错解决:Reason: Failed to determine a suitable driver class
  16. 苹果cms v10模板 海螺模板V15 已去授权 源码+安装教程 长期更新
  17. 程序设计-在校整理-06 最常公共子序列与子串+2048小游戏+KNN简单实例
  18. maven中无法下载ojdbc
  19. Android的RemoteViews
  20. 软件测试行业发展前景分析

热门文章

  1. 第15届Pwn2Own大赛确定目标和奖金
  2. 被利用达数百万次、瞄准 Linux 系统的 Top 15漏洞
  3. 研究员公开Razer 0day,插入鼠标即可获得Windows管理员权限
  4. 猎洞20年老兵的经验之谈
  5. 这个漏洞能换几杯星巴克?在线等,挺急的
  6. C语言利用栈计算算式(表达式)
  7. jetbrains全家桶中好用的快捷键插件:Key Promoter X
  8. 以Chef和Ansible为例快速入门服务器配置
  9. 艰苦的编译boost python (失败)
  10. 吴恩达创建deeplearning.ai讲授AI课程 ,向全世界普及深度学习知识