虚拟机中内存管理

什么是Heap(堆)

在Dalvik虚拟机中,堆实际上就是一块匿名共享内存. 一个mspace(libc中的概念),可以通过libc提供的函数create_mspace_with_base创建一个mspace,然后再通过mspace_开头的函数管理该mspace。例如,我们可以通过mspace_malloc和mspace_bulk_free来在指定的mspace中分配和释放内存。

函数dvmAllocRegion所做的事情就是调用函数ashmem_create_region来创建一块匿名共享内存,一段连续的内存,大小是gDvm.heapMaximumSize.

libc中的内存管理函数

dlmalloc使用了两套API.一套对应默认的mspace,以dl前缀开头,如dlmalloc, dlrealloc等.如果创建了自定义的mspace,则使用mspace开头的API,如mspace_malloc, mspace_realloc

/* create_mspace_with_base uses the memory supplied as the initial base
  of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this
  space is used for bookkeeping, so the capacity must be at least this
  large. (Otherwise 0 is returned.) When this initial space is
  exhausted, additional memory will be obtained from the system.
  Destroying this space will deallocate all additionally allocated
  space (if possible) but not the initial base.*/
  
mspace create_mspace_with_base(void* base, size_t capacity, int locked);

/*
  malloc_footprint_limit();
  Returns the number of bytes that the heap is allowed to obtain from
  the system, returning the last value returned by
  malloc_set_footprint_limit, or the maximum size_t value if
  never set. The returned value reflects a permission. There is no
  guarantee that this number of bytes can actually be obtained from
  the system.  */
  size_t mspace_footprint_limit(mspace msp);
size_t mspace_set_footprint_limit(mspace msp, size_t bytes);
  
void *dvmAllocRegion(size_t byteCount, int prot, const char *name) {
    void *base;
    int fd, ret;
 
    byteCount = ALIGN_UP_TO_PAGE_SIZE(byteCount);
    fd = ashmem_create_region(name, byteCount);
    if (fd == -1) {
        return NULL;
    }
    base = mmap(NULL, byteCount, prot, MAP_PRIVATE, fd, 0);
    ret = close(fd);
    if (base == MAP_FAILED) {
        return NULL;
    }
    if (ret == -1) {
        munmap(base, byteCount);
        return NULL;
    }
    return base;
}

dvmHeapSourceStartup调用函数createMspace将前面得到的匿名共享内存块封装为一个mspace
mspace的起始大小为Java堆的起始大小。后面我们动态地调整这个mspace的大小,使得它可以使用更多的内存,但是不能超过Java堆的最大值。

static mspace createMspace(void* begin, size_t morecoreStart, size_t startingSize)
{
    // Clear errno to allow strerror on error.
    errno = 0;
    // Allow access to inital pages that will hold mspace.
    mprotect(begin, morecoreStart, PROT_READ | PROT_WRITE);
    // Create mspace using our backing storage starting at begin and with a footprint of
    // morecoreStart. Don't use an internal dlmalloc lock. When morecoreStart bytes of memory are
    // exhausted morecore will be called.
    mspace msp = create_mspace_with_base(begin, morecoreStart, false /*locked*/);
    if (msp != NULL) {
        // Do not allow morecore requests to succeed beyond the starting size of the heap.
        mspace_set_footprint_limit(msp, startingSize);
    } else {
        ALOGE("create_mspace_with_base failed %s", strerror(errno));
    }
    return msp;
}
堆的作用

虚拟机要解决的问题之一就是帮助应用程序自动分配和释放内存。
虚拟机在启动的时候向操作系统申请一大块内存当作对象堆。之后当应用程序创建对象时,虚拟机就会在堆上分配合适的内存块。而当对象不再使用时,虚拟机就会将它占用的内存块归还给堆。

Active堆和一个Zygote堆

应用程序进程是由Zygote进程fork出来的。

应用程序进程和Zygote进程共享了同一个用来分配对象的堆。然而,当Zygote进程或者应用程序进程对该堆进行写操作时,内核就会执行真正的拷贝操作,使得Zygote进程和应用程序进程分别拥有自己的一份拷贝。

不利因素:
拷贝是一件费时费力的事情。因此,为了尽量地避免拷贝,Dalvik虚拟机将自己的堆划分为两部分。

Dalvik虚拟机的堆最初是只有一个的。也就是Zygote进程在启动过程中创建D

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值