博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ART的堆内存布局
阅读量:7044 次
发布时间:2019-06-28

本文共 9046 字,大约阅读时间需要 30 分钟。

ART堆内存由若干个space组成,map表中的space的布局如下:

00000000'12c00000-00000000'12e68fff rw-         0    269000  /dev/ashmem/dalvik-main space (deleted)    00000000'12e69000-00000000'22bfffff ---    269000   fd97000  /dev/ashmem/dalvik-main space (deleted)    00000000'32c00000-00000000'32c00fff rw-         0      1000  /dev/ashmem/dalvik-main space 1 (deleted)    00000000'32c01000-00000000'42bfffff ---      1000   ffff000  /dev/ashmem/dalvik-main space 1 (deleted)    00000000'6f064000-00000000'6feb5fff rw-         0    e52000  /data/dalvik-cache/arm64/system@framework@boot.art    00000000'6feb6000-00000000'7232efff r--         0   2479000  /data/dalvik-cache/arm64/system@framework@boot.oat    00000000'7232f000-00000000'74825fff r-x   2479000    a36000  /data/dalvik-cache/arm64/system@framework@boot.oat    00000000'74826000-00000000'74826fff rw-   4970000      1000  /data/dalvik-cache/arm64/system@framework@boot.oat    00000000'74827000-00000000'749a6fff rw-         0    180000  /dev/ashmem/dalvik-zygote space (deleted)    00000000'749a7000-00000000'749a7fff rw-         0      1000  /dev/ashmem/dalvik-non moving space (deleted)    00000000'749a8000-00000000'749b9fff rw-      1000     12000  /dev/ashmem/dalvik-non moving space (deleted)    00000000'749ba000-00000000'78027fff ---     13000   366e000  /dev/ashmem/dalvik-non moving space (deleted)    00000000'78028000-00000000'78826fff rw-   3681000    7ff000  /dev/ashmem/dalvik-non moving space (deleted)    00000000'78827000-00000000'98826fff rw-         0  20000000  /dev/ashmem/dalvik-free list large object space (deleted)

非等比例图如下:

如上图,可分为如下几种space:main space、image space、zygote space、non moving space、large object space。

这些space是在art::gc::Heap类的构造函数中被创建出来,其调用流程如下:

main()@frameworks/base/cmds/app_process/app_main.cpp    android::AndroidRuntime::startVm()@frameworks/base/core/jni/AndroidRuntime.cpp        JNI_CreateJavaVM()@art/runtime/java_vm_ext.cc            art::Runtime::Create()@art/runtime/runtime.cc                art::Runtime::Init()@art/runtime/runtime.cc                    art::gc::Heap::Heap()@art/runtime/gc/heap.cc

构建space的代码如下:

Heap::Heap(...) {  ...  if (!image_file_name.empty()) {    std::string error_msg;    //加载boot.art和boot.oat,构建image space    auto* image_space = space::ImageSpace::Create(image_file_name.c_str(), image_instruction_set, &error_msg);    if (image_space != nullptr) {      AddSpace(image_space);      uint8_t* oat_file_end_addr = image_space->GetImageHeader().GetOatFileEnd();      requested_alloc_space_begin = AlignUp(oat_file_end_addr, kPageSize);    }   }  bool separate_non_moving_space = is_zygote || support_homogeneous_space_compaction || IsMovingGc(foreground_collector_type_) || IsMovingGc(background_collector_type_);  std::unique_ptr
main_mem_map_1; std::unique_ptr
main_mem_map_2; uint8_t* request_begin = requested_alloc_space_begin; if (separate_non_moving_space) { const char* space_name = is_zygote ? kZygoteSpaceName: kNonMovingSpaceName; //zygote space的map,起始地址紧挨着boot.oat,大小为64M non_moving_space_mem_map.reset(MemMap::MapAnonymous(space_name, requested_alloc_space_begin, non_moving_space_capacity, PROT_READ | PROT_WRITE, true, false, &error_str)); request_begin = reinterpret_cast
(300 * MB); } if (foreground_collector_type_ != kCollectorTypeCC) { if (separate_non_moving_space) { // main space 1的map main_mem_map_1.reset(MapAnonymousPreferredAddress(kMemMapSpaceName[0], request_begin, capacity_/*512M*/, &error_str)); } } if (support_homogeneous_space_compaction || background_collector_type_ == kCollectorTypeSS ||foreground_collector_type_ == kCollectorTypeSS) { //main space 2的map main_mem_map_2.reset(MapAnonymousPreferredAddress(kMemMapSpaceName[1], main_mem_map_1->End(), capacity_, &error_str)); } if (separate_non_moving_space) { const size_t size = non_moving_space_mem_map->Size(); // 构建zygote space non_moving_space_ = space::DlMallocSpace::CreateFromMemMap(non_moving_space_mem_map.release(), "zygote / non moving space", kDefaultStartingSize, initial_size, size, size, false); non_moving_space_->SetFootprintLimit(non_moving_space_->Capacity()); AddSpace(non_moving_space_); } if (foreground_collector_type_ == kCollectorTypeCC) { ... } else if (IsMovingGc(foreground_collector_type_) && foreground_collector_type_ != kCollectorTypeGSS) { } else { //构建main space 1 CreateMainMallocSpace(main_mem_map_1.release(), initial_size/*2M*/, growth_limit_/*256M*/, capacity_/*512M*/); AddSpace(main_space_); if (foreground_collector_type_ == kCollectorTypeGSS) { ... } else if (main_mem_map_2.get() != nullptr) { const char* name = kUseRosAlloc ? kRosAllocSpaceName[1] : kDlMallocSpaceName[1]; //构建main space 2 main_space_backup_.reset(CreateMallocSpaceFromMemMap(main_mem_map_2.release(), initial_size, growth_limit_, capacity_, name, true)); AddSpace(main_space_backup_.get()); } } //构建large object space if (large_object_space_type == space::LargeObjectSpaceType::kFreeList) { large_object_space_ = space::FreeListSpace::Create("free list large object space", nullptr, capacity_); } ... if (large_object_space_ != nullptr) { AddSpace(large_object_space_); }}

 

【image space】

根据boot.art这个内存镜像文件创建的space,映射地址是boot.art里指定的。

这块有系统的java类,其内存不会被释放,所以也不需要有堆管理模块。加载image space的同时会加载boot.oat文件。

 

【main space】

从300M的地址也就是0x12c00000开始的大小为512M的内存区域,绝大部分的object都利用这段空间。它的堆管理模块是RocAlloc。

有一个相同大小的备用main space区域,暂时不清楚其用途。

 

【zygote(non moving) space】

紧挨着boot.oat的内存区域,大小为64M,zygote启动时是以non moving space的形式存在,

主要用于non moving的object:主要是non moving的class或者从其他non moving区域里拷贝出来的对象,比如image space就是non moving区域。

它的堆栈管理块是Dlmalloc。

 

【large object space】

紧挨着non moving spage的区域,申请大于等于12k的基本类型或者string类型的数组时会用到这部分内存,

根据配置可分为FreeListSpace和LargeObjectMapSpace。

其中LargeObjectMapSpace是次alloc和free都会调用系统的mmap和munmap,管理模块逻辑简单,但效率低。

FreeListSpace会一次性mmap一块512M内存,用一个相对复杂点的(相对于RocAlloc和Dlmalloc简单的多)逻辑管理这块内存,效率高比LargeObjectMapSpace高。

一般系统默认用FreeListSpace作为large object space。

 

在虚拟机初始化完成前,也就是fork第一个进程(system server)前,调用art::gc::Heap::PreZygoteFork()函数进行一次调整,其调用栈为:

main()@frameworks/base/cmds/app_process/app_main.cpp    com.android.internal.os.ZygoteInit.main()@frameworks/base/core/java/com/android/internal/os/ZygoteInit.java        com.android.internal.os.ZygoteInit.startSystemServer@frameworks/base/core/java/com/android/internal/os/ZygoteInit.java            com.android.internal.os.Zygote.forkSystemServer()@frameworks/base/core/java/com/android/internal/os/Zygote.java                dalvik.system.ZygoteHooks.preFork()@libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java                    dalvik.system.ZygoteHooks.nativePreFork()@libcore/dalvik/src/main/java/dalvik/system/ZygoteHooks.java                        art::ZygoteHooks_nativePreFork()@art/runtime/native/dalvik_system_ZygoteHooks.cc                            art::Runtime::PreZygoteFork()@art/runtime/runtime.cc                                art::gc::Heap::PreZygoteFork()@art/runtime/gc/heap.cc

调整的目的是将虚拟机初始化阶段生成的main space和non moving space里的对象,合并成一块儿内存,

这部分内存之在虚拟机初始化完成后不会被改变,将他们统一成一个区域,可以共享给所有zygote fork出来的进程,既节省内存,也方便gc管理。

void Heap::PreZygoteFork() {  ...  if (kCompactZygote) {    ...    ZygoteCompactingCollector zygote_collector(this);    //找到non_moving_space_中的空闲区域,用于插入man_space_里的对象    zygote_collector.BuildBins(non_moving_space_);    ...    bool reset_main_space = false;    if (IsMovingGc(collector_type_)) {      ...    } else {      zygote_collector.SetFromSpace(main_space_);      reset_main_space = true;    }    zygote_collector.SetToSpace(&target_space);    zygote_collector.SetSwapSemiSpaces(false);    //将main_space_中的对象插入到non_moving_space_中    zygote_collector.Run(kGcCauseCollectorTransition, false);    if (reset_main_space) {      //重新构建main space      main_space_->GetMemMap()->Protect(PROT_READ | PROT_WRITE);      madvise(main_space_->Begin(), main_space_->Capacity(), MADV_DONTNEED);      MemMap* mem_map = main_space_->ReleaseMemMap();      RemoveSpace(main_space_);      space::Space* old_main_space = main_space_;      CreateMainMallocSpace(mem_map, kDefaultInitialSize, std::min(mem_map->Size(), growth_limit_), mem_map->Size());      delete old_main_space;      AddSpace(main_space_);    } else {      ...    }    ...    non_moving_space_->SetEnd(target_space.End());    non_moving_space_->SetLimit(target_space.Limit());  }  ChangeCollector(foreground_collector_type_);  space::MallocSpace* old_alloc_space = non_moving_space_;  RemoveSpace(old_alloc_space);  //原先的non moving space被拆分为zygote space和新non moving space  zygote_space_ = old_alloc_space->CreateZygoteSpace(kNonMovingSpaceName, low_memory_mode_, &non_moving_space_);  delete old_alloc_space;  AddSpace(zygote_space_);  non_moving_space_->SetFootprintLimit(non_moving_space_->Capacity());  AddSpace(non_moving_space_);  ...}

合并前main_space_的管理模块是RosAlloc,而non_moving_space_的管理模块是Dlmalloc。

由于合并后的内存是不会被释放的,也就不需要管理模块,所以这种合并是可行的。

 

space的继承关系如下:

 

转载于:https://www.cnblogs.com/YYPapa/p/6851299.html

你可能感兴趣的文章
[GIt] 团队工作效率分析工具gitstats
查看>>
写给新人的面向对象的基本思维
查看>>
关于分部视图(Partial View)
查看>>
DNS污染——domain name的解析被劫持了返回无效的ip
查看>>
一步一步写一个简单通用的makefile(二)
查看>>
sunspot使用
查看>>
Zombie.js Insanely fast, headless full-stack testing using Node.js
查看>>
POJ2406-Power Strings(kmp循环节)
查看>>
BCM路由全智能固件升级软件tftp,一键刷路由及常用固件下载
查看>>
个人认识:直接断电和发送复位信号给主板有啥区别?
查看>>
测试体会:WAYOS新架构(即二代QOS)的新功能解释
查看>>
UVA 10169 Urn-ball Probabilities !
查看>>
每日一例,练就编程高手
查看>>
no argument specified with option "/LIBPATH:"错误的解决【转载】
查看>>
初涉c#设计模式-Factory Pattern
查看>>
android 广播复杂参数
查看>>
EmbossMaskFilter BlurMaskFilter
查看>>
android中XML文件解析遇到“not well-formed (invalid token)”解决办法
查看>>
JRuby——Java和Ruby的强强联合
查看>>
ipcs和ipcrm用法简介
查看>>