版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
ART运行时CompactingGC堆创建过程分析引进了CompactingGC之后,ART运行时的堆空间结构就发生了变化。这是由于CompactingGC和Mark-SweepGC的算法不同,要求底层的堆具有不同的空间结构。同时,即使是原来的Mark-SweepGC,由于需要支持新的同构空间压缩特性(HomogeneousSpaceCompact),也使得它们要具有与原来不一样的堆空间结构。本文就对这些堆空间创建过程进行详细的分析。从前面一文可以知道,在没有CompactingGC之前,Mark-SweepGC的堆由ImageSpace、ZygoteSpace、AllocationSpace和LargeObjectSpace四种Space组成。其中,AllocationSpace是从ZygoteSpace中分离出来的,它们都是一种DlMallocSpace。引入CompactingGC之后,ImageSpace和LargeObjectSpace没有发生根本性的变化,但是ZygoteSpace和AllocationSpace就发生了很大的变化。因此,接下来我们就结合CompactingGC以及其它的一些新特性来分析ZygoteSpace和AllocationSpace都发生了哪些变化。从前面一文可以知道,用来分配对象的空间可以是一种DlMallocSpace,也可以是一种RosAllocSpace,因此,堆空间发生的第一个变化是用来分配对象的空间有可能是一个DlMallocSpace,也有可能是一个RosAllocSpace。从前面一文还可以知道,Semi-SpaceGC需要两个BumpPointerSpace,GenerationalSemi-SpaceGC需要两个BumpPointerSpace和一个PromoteSpace,Mark-CompactGC需要一个BumpPointerSpace。因此,我们需要增加一种类型为BumpPointer的Space,以及一个PromoteSpace。此外,我们还需要一个Non-MovingSpace。由于在CompactingGC中,涉及到对象的移动,但是有些对象,例如类对象(Class)、类方法对象(ArtMethod)和类成员变量对象(ArtField),它们一经加载后,基本上就会一直存在。因此,频繁对此类对象进行移动是无益的,我们需要将它们分配在一个不能移动的Space中,以减少在CompactingGC需要处理的对象的数量。所谓的同构空间压缩特性(HomogeneousSpaceCompact),是针对Mark-SweepGC而言的。一个Space需要有Main和Backup之分。执行同构空间压缩时,将MainSpace的对象移动至BackupSpace中去,再将MainSpace和BackupSpace进行交换,这样就达到压缩空间,即减少内存碎片的作用。综合前面的分析,我们就列出ART运行时支持的各种GC的堆空间结构,如下三个图所示:接下来,我们将结构源代码来详细分析上述三个图各个Space的创建过程,这样就可以更好理解这三个图所表达的意思。从前面一文可以知道,堆的创建是从在ART运行时内部创建一个Heap对象开始的,如下所示:[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片boolRuntime::Init(constRuntimeOptions&raw_options,boolignore_unrecognized){heap_=newgc::Heap(options->heap_initial_size_,options->heap_growth_limit_,options->heap_min_free_,options->heap_max_free_,options->heap_target_utilization_,options->foreground_heap_growth_multiplier_,options->heap_maximum_size_,options->heap_non_moving_space_capacity_,options->image_,options->image_isa_,options->collector_type_,options->background_collector_type_,options->parallel_gc_threads_,options->conc_gc_threads_,options->low_memory_mode_,options->long_pause_log_threshold_,options->long_gc_log_threshold_,options->ignore_max_footprint_,options->use_tlab_,options->verify_pre_gc_heap_,options->verify_pre_sweeping_heap_,options->verify_post_gc_heap_,options->verify_pre_gc_rosalloc_,options->verify_pre_sweeping_rosalloc_,options->verify_post_gc_rosalloc_,options->use_homogeneous_space_compaction_for_oom_,options->min_interval_homogeneous_space_compaction_by_oom_);}这个函数定义在文件art/runtime/runtime.cc中。创建堆所需要的一般性参数的含义可以参考前面一文,这里我们只解释几个与CompactingGC相关的参数:options->heap_non_moving_space_capacity_:Non-MovingSpace的大小,可以通过ART运行时启动选项-XX:NonMovingSpaceCapacity来指定,默认大小为kDefaultNonMovingSpaceCapacity(64MB)。options->collector_type_:ForegroundGC的类型,可以通过ART运行时启动选项-Xgc指定。如果没有指定,在编译ART运行时时,可以通过ART_DEFAULT_GC_TYPE_IS_CMS、ART_DEFAULT_GC_TYPE_IS_SS和ART_DEFAULT_GC_TYPE_IS_GSS这三个宏分别默认为ConcurrentMark-SweepGC、Semi-SpaceGC或者GenerationalSemi-SpaceGC。options->background_collector_type_:BackgroundGC的类型,可以通过ART运行时启动选项-XX:BackgroundGC指定。如果没有指定,在编译ART运行时时,可以通过ART_USE_HSPACE_COMPACT宏指定为Homogeneous-Space-Compact。如果没有指定ART_USE_HSPACE_COMPACT宏,默认就与ForegroundGC一样。options->use_homogeneous_space_compaction_for_oom_:是否在OOM时执行Homogeneous-Space-Compact,可以通过ART运行时启动选项-XX:EnableHSpaceCompactForOOM和-XX:DisableHSpaceCompactForOOM来设置为支持和不支持。如果没有指定,默认不支持。options->min_interval_homogeneous_space_compaction_by_oom_:OOM时执行Homogeneous-Space-Compact的最小时间间隔,可以在OOM时频繁地执行Homogeneous-Space-Compact,固定为100秒。Heap对象的创建和初始化过程如下所示:[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片Heap::Heap(size_tinitial_size,size_tgrowth_limit,size_tmin_free,size_tmax_free,doubletarget_utilization,doubleforeground_heap_growth_multiplier,size_tcapacity,size_tnon_moving_space_capacity,conststd::string&image_file_name,constInstructionSetimage_instruction_set,CollectorTypeforeground_collector_type,CollectorTypebackground_collector_type,size_tparallel_gc_threads,size_tconc_gc_threads,boollow_memory_mode,size_tlong_pause_log_threshold,size_tlong_gc_log_threshold,boolignore_max_footprint,booluse_tlab,boolverify_pre_gc_heap,boolverify_pre_sweeping_heap,boolverify_post_gc_heap,boolverify_pre_gc_rosalloc,boolverify_pre_sweeping_rosalloc,boolverify_post_gc_rosalloc,booluse_homogeneous_space_compaction_for_oom,uint64_tmin_interval_homogeneous_space_compaction_by_oom)byte*requested_alloc_space_begin=nullptr;if(!image_file_name.empty()){std::stringerror_msg;space::ImageSpace*image_space=space::ImageSpace::Create(image_file_name.c_str(),image_instruction_set,&error_msg);if(image_space!=nullptr){AddSpace(image_space);//Oatfilesreferencedbyimagefilesimmediatelyfollowtheminmemory,ensureallocspace//isn'tgoingtogetinthemiddlebyte*oat_file_end_addr=image_space->GetImageHeader().GetOatFileEnd();requested_alloc_space_begin=AlignUp(oat_file_end_addr,kPageSize);}}boolsupport_homogeneous_space_compaction=background_collector_type_==gc::kCollectorTypeHomogeneousSpaceCompact||use_homogeneous_space_compaction_for_oom;//Wemayusethesamespacethemainspaceforthenonmovingspaceifwedon'tneedtocompact//fromthemainspace.//Thisisnotthecaseifwesupporthomogeneouscompactionorhaveamovingbackground//collectortype.boolseparate_non_moving_space=is_zygote||support_homogeneous_space_compaction||IsMovingGc(foreground_collector_type_)||IsMovingGc(background_collector_type_);if(foreground_collector_type==kCollectorTypeGSS){separate_non_moving_space=false;}std::unique_ptr<MemMap>main_mem_map_1;std::unique_ptr<MemMap>main_mem_map_2;byte*request_begin=requested_alloc_space_begin;if(request_begin!=nullptr&&separate_non_moving_space){request_begin+=non_moving_space_capacity;}std::unique_ptr<MemMap>non_moving_space_mem_map;if(separate_non_moving_space){//Reservethenonmovingmemmapbeforetheothertwosinceitneedstobeataspecific//address.non_moving_space_mem_map.reset(MemMap::MapAnonymous("nonmovingspace",requested_alloc_space_begin,non_moving_space_capacity,PROT_READ|PROT_WRITE,true,&error_str));//Trytoreservevirtualmemoryataloweraddressifwehaveaseparatenonmovingspace.request_begin=reinterpret_cast<byte*>(300*MB);}//Attempttocreate2memmapsatoraftertherequestedbegin.main_mem_map_1.reset(MapAnonymousPreferredAddress(kMemMapSpaceName[0],request_begin,capacity_,PROT_READ|PROT_WRITE,&error_str));if(support_homogeneous_space_compaction||background_collector_type_==kCollectorTypeSS||foreground_collector_type_==kCollectorTypeSS){main_mem_map_2.reset(MapAnonymousPreferredAddress(kMemMapSpaceName[1],main_mem_map_1->End(),capacity_,PROT_READ|PROT_WRITE,&error_str));}//Createthenonmovingspacefirstsothatbitmapsdon'ttakeuptheaddressrange.if(separate_non_moving_space){//Nonmovingspaceisalwaysdlmallocsincewecurrentlydon'thavesupportformultiple//activerosallocspaces.constsize_tsize=non_moving_space_mem_map->Size();non_moving_space_=space::DlMallocSpace::CreateFromMemMap(non_moving_space_mem_map.release(),"zygote/nonmovingspace",kDefaultStartingSize,initial_size,size,size,false);non_moving_space_->SetFootprintLimit(non_moving_space_->Capacity());AddSpace(non_moving_space_);}//CreateotherspacesbasedonwhetherornotwehaveamovingGC.if(IsMovingGc(foreground_collector_type_)&&foreground_collector_type_!=kCollectorTypeGSS){//Createbumppointerspaces.//WeonlytocreatethebumppointeriftheforegroundcollectorisacompactingGC.//TODO:Placebump-pointerspacessomewheretominimizesizeofcardtable.bump_pointer_space_=space::BumpPointerSpace::CreateFromMemMap("Bumppointerspace1",main_mem_map_1.release());AddSpace(bump_pointer_space_);temp_space_=space::BumpPointerSpace::CreateFromMemMap("Bumppointerspace2",main_mem_map_2.release());AddSpace(temp_space_);}else{CreateMainMallocSpace(main_mem_map_1.release(),initial_size,growth_limit_,capacity_);AddSpace(main_space_);if(!separate_non_moving_space){non_moving_space_=main_space_;}if(foreground_collector_type_==kCollectorTypeGSS){//Createbumppointerspacesinsteadofabackupspace.main_mem_map_2.release();bump_pointer_space_=space::BumpPointerSpace::Create("Bumppointerspace1",kGSSBumpPointerSpaceCapacity,nullptr);AddSpace(bump_pointer_space_);temp_space_=space::BumpPointerSpace::Create("Bumppointerspace2",kGSSBumpPointerSpaceCapacity,nullptr);AddSpace(temp_space_);}elseif(main_mem_map_2.get()!=nullptr){constchar*name=kUseRosAlloc?kRosAllocSpaceName[1]:kDlMallocSpaceName[1];main_space_backup_.reset(CreateMallocSpaceFromMemMap(main_mem_map_2.release(),initial_size,growth_limit_,capacity_,name,true));//Addthespacesoitsaccountedforintheheap_beginandheap_end.AddSpace(main_space_backup_.get());}}}这个函数定义在文件art/runtime/gc/heap.cc中。由于底层堆的空间结构要兼顾到上层的各种GC,因此堆创建过程中涉及到逻辑是比较复杂的,我们将上述函数涉及到的代码分段来解读。第一段代码是关于ImageSpace的创建的,如下所示:[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片byte*requested_alloc_space_begin=nullptr;if(!image_file_name.empty()){std::stringerror_msg;space::ImageSpace*image_space=space::ImageSpace::Create(image_file_name.c_str(),image_instruction_set,&error_msg);if(image_space!=nullptr){AddSpace(image_space);//Oatfilesreferencedbyimagefilesimmediatelyfollowtheminmemory,ensureallocspace//isn'tgoingtogetinthemiddlebyte*oat_file_end_addr=image_space->GetImageHeader().GetOatFileEnd();requested_alloc_space_begin=AlignUp(oat_file_end_addr,kPageSize);}}关于ImageSpace的创建过程,可以参考前面一文。从前面一文可以知道,紧跟在ImageSpace后面的是一个boot.art@classes.oat文件。而紧跟在boot.art@classes.oat文件末尾的ZygoteSpace,这个地址记录在本地变量requested_alloc_space_begin中。第二段代码是关于Non-MovingSpace的,如下所示:[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片boolsupport_homogeneous_space_compaction=background_collector_type_==gc::kCollectorTypeHomogeneousSpaceCompact||use_homogeneous_space_compaction_for_oom;//Wemayusethesamespacethemainspaceforthenonmovingspaceifwedon'tneedtocompact//fromthemainspace.//Thisisnotthecaseifwesupporthomogeneouscompactionorhaveamovingbackground//collectortype.boolseparate_non_moving_space=is_zygote||support_homogeneous_space_compaction||IsMovingGc(foreground_collector_type_)||IsMovingGc(background_collector_type_);if(foreground_collector_type==kCollectorTypeGSS){separate_non_moving_space=false;}std::unique_ptr<MemMap>main_mem_map_1;std::unique_ptr<MemMap>main_mem_map_2;byte*request_begin=requested_alloc_space_begin;if(request_begin!=nullptr&&separate_non_moving_space){request_begin+=non_moving_space_capacity;}std::unique_ptr<MemMap>non_moving_space_mem_map;if(separate_non_moving_space){//Reservethenonmovingmemmapbeforetheothertwosinceitneedstobeataspecific//address.non_moving_space_mem_map.reset(MemMap::MapAnonymous("nonmovingspace",requested_alloc_space_begin,non_moving_space_capacity,PROT_READ|PROT_WRITE,true,&error_str));//Trytoreservevirtualmemoryataloweraddressifwehaveaseparatenonmovingspace.request_begin=reinterpret_cast<byte*>(300*MB);}这段代码的逻辑是判断是否需要给Non-MovingSpace一个独立的地址空间。Non-MovingSpace总是存在的,现在需要判断的是要给它一个独立的地址空间,还是要与其它Space共享同一个地址空间,主要是考虑到GenerationalSemi-SpaceGC。从前面一文可以知道,GenerationalSemi-SpaceGC需要一个PromoteSpace来保存那些经过若干轮GC后仍然存活下来的对象,而且这些对象在以后的GenerationalSemi-SpaceGC中不需要进行移动。这个PromoteSpace就是一个DlMallocSpace或者RosAllocSpace。PromoteSpace起到的作用与Non-MovingSpace类似,因为保存在它们里面的对象都是不可以移动的。因此,在GenerationalSemi-SpaceGC的情况下,将PromoteSpace和Non-MovingSpace合在一起共享同一个地址空间。Non-MovingSpace是相对MovingSpace而言的,也就是说,只要存在MovingSpace,就需要给Non-MovingSpace一个独立的地址空间,使得在Non-MovingSpace和MovingSpace的对象在GC中可以区别对待处理。那么,在什么情况下存在MovingSpace呢?最直觉地,只要我们使用到了CompactingGC,那么就需要MovingSpace,因为CompactingGC需要移动对象。因此,上述代码段会调用Heap类的成员函数IsMovingGc判断指定的ForegroundGC(foreground_collector_type_)和BackgroundGC(background_collector_type_)是否是CompactingGC,也就是是否是Semi-SpaceGC、GenerationalSemi-SpaceGC和Mark-CompactGC之一。如果是的话,那么就将本地变量separate_non_moving_space设置为true,表示需要给Non-MovingSpace一个独立的地址空间。除了CompactingGC的情况,还有两种情况也是涉及到MovingSpace的。第一种情况是应用程序运行在Zygote模式中,即本地变量is_zygote等于true的情况下。应用程序运行在Zygote模式时,它们的进程都是由Zygote进程fork出来的,这样做的目的是为了让Zygote进程和应用程序进程共享内存。Zygote进程在fork第一个应用程序进程之前,为了有效地和应用程序进程共享内存,会对堆空间进行一次压缩处理。这个压缩处理实际上就是执行一次Semi-SpaceGC。因此,在这种情况下,即本地变量is_zygote等于true时,也需要将本地变量separate_non_moving_space设置为true,表示需要给Non-MovingSpace一个独立的地址空间。第二种情况ART运行时支持Homogeneous-Space-Compact特性。Homogeneous-Space-Compact特性意味我们要将MainSpace上的对象移动到BackupSpace上去。这个移动过程实际上也是通过执行一次Semi-SpaceGC来完成的。因此,在这种情况下,即本地变量support_homogeneous_space_compaction等于true时,也需要将本地变量separate_non_moving_space设置为true,表示需要给Non-MovingSpace一个独立的地址空间。那么,什么情况下ART运行时需要支持Homogeneous-Space-Compact特性呢?有两种情况需要支持。第一种情况是BackgroundGC(background_collector_type_)被指定为Homogeneous-Space-CompactGC,这可以通过ART运行时启动选项-XX:BackgroundGC进行指定。第二种情况是在分配对象遇到OOM时,需要将MainSpace上的对象移动到BackupSpace上去,然后再将这两个Space进行交换,并且再次尝试在MainSpace上进行分配,以便可以解决由内存碎片引发的OOM问题。我们可以通过ART运行时启动选项-XX:EnableHSpaceCompactForOOM和-XX:DisableHSpaceCompactForOOM来启用和禁用这种行为,体现在这里就是参数use_homogeneous_space_compaction_for_oom的值是等于true还是false。一旦决定给Non-MovingSpace一个独立的地址空间,那么就会调用MemMap类的静态成员函数MapAnonymous创建一块匿名共享内存non_moving_space_mem_map,以便接下来可以用来创建Non-MovingSpace。注意,这块匿名共享内存的起始地址紧接着在boot.art@classes.oat的末尾。同时,其它的Space的起始地址request_begin被修改为300MB地址处,即它们不再是紧跟着Non-MovingSpace的末尾。第三段代码用来创建另外两块匿名共享内存,如下所示:[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片//Attempttocreate2memmapsatoraftertherequestedbegin.main_mem_map_1.reset(MapAnonymousPreferredAddress(kMemMapSpaceName[0],request_begin,capacity_,PROT_READ|PROT_WRITE,&error_str));if(support_homogeneous_space_compaction||background_collector_type_==kCollectorTypeSS||foreground_collector_type_==kCollectorTypeSS){main_mem_map_2.reset(MapAnonymousPreferredAddress(kMemMapSpaceName[1],main_mem_map_1->End(),capacity_,PROT_READ|PROT_WRITE,&error_str));}第一块匿名共享内存main_mem_map_1用来创建CompactingGC的FromBumpPointerSpace或者Mark-SweepGC的MainSpace。第二块匿名共享内存main_mem_map_2用来创建Semi-SpaceGC的ToBumpPointerSpace或者Mark-SweepGC的BackupSpace。注意,第二块匿名共享内存main_mem_map_2紧跟在第一块匿名共享内存main_mem_map_1的末尾。第四段代码用来创建Non-MovingSpace,如下所示:[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片//Createthenonmovingspacefirstsothatbitmapsdon'ttakeuptheaddressrange.if(separate_non_moving_space){//Nonmovingspaceisalwaysdlmallocsincewecurrentlydon'thavesupportformultiple//activerosallocspaces.constsize_tsize=non_moving_space_mem_map->Size();non_moving_space_=space::DlMallocSpace::CreateFromMemMap(non_moving_space_mem_map.release(),"zygote/nonmovingspace",kDefaultStartingSize,initial_size,size,size,false);non_moving_space_->SetFootprintLimit(non_moving_space_->Capacity());AddSpace(non_moving_space_);}只有在本地变量separate_non_moving_space等于true的情况下,也就是要给Non-MovingSpace一块独立的地址空间的情况下,这里才会将前面创建的匿名共享内存non_moving_space_mem_map封装成一个DlMallocSpace,作为一块独立的Non-MovingSpace使用。第五段代码用来为CompactingGC创建BumpPointerSpace或者为Mark-SweepGC创建MainSpace和BackupSpace,如下所示:[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片//CreateotherspacesbasedonwhetherornotwehaveamovingGC.if(IsMovingGc(foreground_collector_type_)&&foreground_collector_type_!=kCollectorTypeGSS){//Createbumppointerspaces.//WeonlytocreatethebumppointeriftheforegroundcollectorisacompactingGC.//TODO:Placebump-pointerspacessomewheretominimizesizeofcardtable.bump_pointer_space_=space::BumpPointerSpace::CreateFromMemMap("Bumppointerspace1",main_mem_map_1.release());AddSpace(bump_pointer_space_);temp_space_=space::BumpPointerSpace::CreateFromMemMap("Bumppointerspace2",main_mem_map_2.release());AddSpace(temp_space_);}else{CreateMainMallocSpace(main_mem_map_1.release(),initial_size,growth_limit_,capacity_);AddSpace(main_space_);if(!separate_non_moving_space){non_moving_space_=main_space_;}if(foreground_collector_type_==kCollectorTypeGSS){//Createbumppointerspacesinsteadofabackupspace.main_mem_map_2.release();bump_pointer_space_=space::BumpPointerSpace::Create("Bumppointerspace1",kGSSBumpPointerSpaceCapacity,nullptr);AddSpace(bump_pointer_space_);temp_space_=space::BumpPointerSpace::Create("Bumppointerspace2",kGSSBumpPointerSpaceCapacity,nullptr);AddSpace(temp_space_);}elseif(main_mem_map_2.get()!=nullptr){constchar*name=kUseRosAlloc?kRosAllocSpaceName[1]:kDlMallocSpaceName[1];main_space_backup_.reset(CreateMallocSpaceFromMemMap(main_mem_map_2.release(),initial_size,growth_limit_,capacity_,name,true));//Addthespacesoitsaccountedforintheheap_beginandheap_end.AddSpace(main_space_backup_.get());}}当ForegroundGC是CompactingGC,但是不是GenerationalSemi-SpaceGC时,分别是用前面创建的匿名共享内存main_mem_map_1和main_mem_map_2创建两个BumpPointerSpace,并且保存在Heap类的成员变量bump_pointer_space_和temp_space_中。当ForegroundGC是Mark-SweepGC或者GenerationalSemi-SpaceGC时,首先是调用Heap类的成员函数CreateMainMallocSpace创建一个MainSpace,这个MainSpace是一块DlMallocSpace或者RosAllocSpace,并且由Heap类的成员变量main_space_指向。如果ForegroundGC是GenerationalSemi-SpaceGC,上面创建的MainSpace实际上是作为PromoteSpace来使用的。同时由前面的分析可以知道,本地变量separate_non_moving_space的值这时候等于false,这意味着Non-MovingSpace与上述PromoteSpace共享的是同一个地址空间。也就是此时ART运行时的Non-MovingSpace(non_moving_space_)与GenerationalSemi-SpaceGC的PromoteSpace(main_space_)指向的是一个Space。接下来,上述代码还会继续为GenerationalSemi-SpaceGC创建一个FromBumpPointerSpace和一个ToBumpPointerSpace。这两个BumpPointerSpace是通过封装两块新创建的匿名共享内存得到的。如果ForegroundGC是Mark-SweepGC,则它们所需要的MainSpace前面已经创建完毕,现在只需要再创建一个BackupSpace即可。通过调用Heap类的成员函数CreateMallocSpaceFromMemMap即可创建一个DlMallocSpace或者RosAllocSpace,以作为BackupSpace使用,并且由Heap类的成员变量main_space_backup_指向。接下来我们继续分析Heap类的成员函数CreateMainMallocSpace的实现,以便可以了解MainSpace的创建过程,而且从中也可以看到用来创建BackupSpace的Heap类的成员函数CreateMallocSpaceFromMemMap的实现,如下所示:[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片voidHeap::CreateMainMallocSpace(MemMap*mem_map,size_tinitial_size,size_tgrowth_limit,size_tcapacity){//Isbackgroundcompactionisenabled?boolcan_move_objects=IsMovingGc(background_collector_type_)!=IsMovingGc(foreground_collector_type_)||use_homogeneous_space_compaction_for_oom_;//Ifwearethezygoteanddon'tyethaveazygotespace,itmeansthatthezygoteforkwill//happeninthefuture.IfthishappensandwehavekCompactZygoteenabledwewishtocompact//fromthemainspacetothezygotespace.Ifbackgroundcompactionisenabled,alwayspassin//thatwecanmoveobjets.if(kCompactZygote&&Runtime::Current()->IsZygote()&&!can_move_objects){//Afterthezygotewewantthistobefalseifwedon'thavebackgroundcompactionenabledso//thatgettingprimitivearrayelementsisfaster.//WeneverhavehomogeneouscompactionwithGSSanddon'tneedaspacewithmovableobjects.can_move_objects=!have_zygote_space_&&foreground_collector_type_!=kCollectorTypeGSS;}if(collector::SemiSpace::kUseRememberedSet&&main_space_!=nullptr){RemoveRememberedSet(main_space_);}constchar*name=kUseRosAlloc?kRosAllocSpaceName[0]:kDlMallocSpaceName[0];main_space_=CreateMallocSpaceFromMemMap(mem_map,initial_size,growth_limit,capacity,name,can_move_objects);SetSpaceAsDefault(main_space_);VLOG(heap)<<"Createdmainspace"<<main_space_;}这个函数定义在文件art/runtime/runtime.cc中。一般来说,在以下两种情况下,MainSpace的对象可以移动:1.ForegroundGC和BackgroundGC不同时为CompactingGC或者Mark-SweepGC。这是因为当发生ForegroundGC和BackgroundGC切换时,如果ForegroundGC和BackgroundGC不同时为CompactingGC或者Mark-SweepGC时,需要将对象从MainSpace移动到BumpPointerSpace,或者从BumpPointerSpace移动到MainSpace。2.ART运行时分配对象发生OOM时支持Homogeneous-Space-Compact特性。这时候需要将MainSpace的对象移动到BackupSpace。还有一种特殊情况,要求MainSpace上的对象是可以移动的。前面提到,Zygote进程在fork第一个应用程序进程之前,会对堆进行一次Semi-SpaceGC。取决于当前的ForegroundGC是CompactingGC还是Mark-SweepGC,这次Semi-SpaceGC的FromSpace即为CompactingGC当前使用的BumpPointerSpace或者Mark-SweepGC的MainSpace。不过这样的Semi-SpaceGC是要在常量kCompactZygote设置为true的情况下才会执行。根据前面的分析,在ForegroundGC是GenerationalSemi-SpaceGC的情况下,这里创建的MainSpace同时也作为GenerationalSemi-SpaceGC的PromoteSpace,这就要求MainSpace是不能移动对象的。有了这些背景知识后,就可以很容易理解Heap类的成员函数CreateMallocSpaceFromMemMap的实现了。首先,语句IsMovingGc(background_collector_type_)!=IsMovingGc(foreground_collector_type_)就是用来判断ForegroundGC和BackgroundGC不同时为CompactingGC或者Mark-SweepGC的。其次,use_homogeneous_space_compaction_for_oom_代表ART运行时分配对象发生OOM时支持Homogeneous-Space-Compact特性。如果经过上面的处理之后,本地变量can_move_objects的值仍然为false,并且当前是运行在Zygote模式中(Runtime::Current()->IsZygote()等于true)、常量kCompactZygote为true,那么就会接着判断当前是否处于Zygote进程fork第一个应用程序进程之前,即Heap类的成员变量have_zygote_space_等于false。如果是的话,那么就会在当前的ForegroundGC不是GenerationalSemi-SpaceGC的情况下,将本地变量can_move_objects修改为true,以便接下来调用Heap类的成员函数CreateMallocSpaceFromMemMap创建一个DlMallocSpace或者RosAllocSpace,如下所示:[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片space::MallocSpace*Heap::CreateMallocSpaceFromMemMap(MemMap*mem_map,size_tinitial_size,size_tgrowth_limit,size_tcapacity,constchar*name,boolcan_move_objects){space::MallocSpace*malloc_space=nullptr;if(kUseRosAlloc){//Createrosallocspace.malloc_space=space::RosAllocSpace::CreateFromMemMap(mem_map,name,kDefaultStartingSize,initial_size,growth_limit,capacity,low_memory_mode_,can_move_objects);}else{malloc_space=space::DlMallocSpace::CreateFromMemMap(mem_map,name,kDefaultStartingSize,initial_size,growth_limit,capacity,can_move_objects);}if(collector::SemiSpace::kUseRememberedSet){accounting::RememberedSet*rem_set=newaccounting::RememberedSet(std::string(name)+"rememberedset",this,malloc_space);CHECK(rem_set!=nullptr)<<"Failedtocreatemainspacerememberedset";AddRememberedSet(rem_set);}CHECK(malloc_space!=nullptr)<<"Failedtocreate"<<name;malloc_space->SetFootprintLimit(malloc_space->Capacity());returnmalloc_space;}这个函数定义在文件art/runtime/runtime.cc中。如果常量kUseRosAlloc的值等于true,那么就Heap类的成员函数CreateMallocSpaceFromMemMap创建的是一个RosAllocSpace;否则的话,创建的是一个DlMallocSpace。同时,如果常量collector::SemiSpace::kUseRememberedSet的值等于true,那么就为前面创建的RosAllocSpace或者DlMallocSpace创建一个RememberedSet。RememberedSet与在前面这个系列文章提到的ModUnionTable的作用类似,都是用来记录被修改对象对指定目标空间的对象的引用情况的。回到Heap类的成员函数CreateMainMallocSpace中,调用Heap类的成员函数CreateMallocSpaceFromMemMap创建完成MainSpace之后,还会调用另外一个成员函数SetSpaceAsDefault将该MainSpace设置为当前Mark-SweepGC使用的MainSpace或者当前GenerationalSemi-SpaceGC使用的PromoteSpace,如下所示:[cpp]viewplaincopy在CODE上查看代码片派生到我的代码片voidHeap::SetSpaceAsDefault(space::ContinuousSpace*continuous_space){WriterMutexLockmu(Thread::Current(),*Locks::heap_bitmap_lock_);if(continuous_space->IsDlMallocSpace()){dlmalloc_space_=continuous_space->AsDlMallocSpace();}elseif(continuous_space->IsRosAllocSpace()){rosalloc_space_=continuous_space->AsRosAllocSpace();}}这个函数定义在文件art/runtime/runtime.cc中。如果前面创建的MainSpace是一个DlMallocSpace,那么就将它保存在Heap类的成员变量dlmalloc_space_中;否则的话,如果是一个RosAllocSpace,就保存在Heap类的成员变量rosalloc_space_中。设置好Heap类的成员变量dlmalloc_space_和rosalloc_space_之后,以后在分配对象时,就可
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026 年台风暴雨农村自建房安全隐患排查主题
- 2026生物质能热电联产项目收益率测算与碳排放交易增益模型构建报告
- 禁毒知识竞赛试题及答案
- 2026中国医疗器械技术供应产业分析供需形势投资评估规划发展总报告
- 2026软件和信息服务业市场发展现状政策分析咨询规划
- 2026汽车机油更换周期精密计算节约成本市场竞争品牌效果革命市场优化报告
- 2026中国智能汽车技术研究进展与发展政策规划分析
- 2026中国职业培训体系完善与发展规划分析研究报告
- 2026皮革加工行业市场竞争供需发展投资评估规划分析报告
- 2026中国电池管理芯片多串并方案与均衡算法优化
- 2026-2027学年第一学期学校1530安全教育记录
- 2026年北师大版小学六年级数学上册课时《数学建模》教案
- 2026秋小学英语外研版(三起)(孙有中)(新教材) 四年级上册教学计划附教学进度表
- 道路施工组织技术方案
- 未成年人保护法测试题一及答案
- 2026年高考生物(湖北卷)真题详细解读及评析
- 2026年浙江省金华市辅警协警招聘笔试参考题库及答案详解
- 追溯建军历史 铭记峥嵘岁月
- 2026浙江浙能电力股份限公司招聘140人易考易错模拟试题(共500题)试卷后附参考答案
- 《研学旅行研究意义及国内外文献综述(1500字)》
- ISO14001环境管理体系培训课件
评论
0/150
提交评论