• davlik虚拟机内存管理之一——内存分配


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

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

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

    1. 对象布局

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

     

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

    2. 

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

    3. 堆内存位图

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

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

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

    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虚拟机的垃圾收集。

  • 相关阅读:
    websocket协议图
    go深浅拷贝
    nginx不匹配location前缀
    nginx localtion 的alias是一个目录别名的定义,root则是最上层目录的定义
    启动了多个redis,怎么知道哪个redisserver使用的是哪个配置文件?
    go打印地址
    Linux之pureftpd安装和使用
    Xtrabackup异机远程备份
    产品新版本发布前要做那些事呢
    2014年新的一年,新的起点。。。
  • 原文地址:https://www.cnblogs.com/frydsh/p/3735932.html
Copyright © 2020-2023  润新知