ART Runtime创建(三)--Heap的创建

Heap的创建位于/art/runtime/runtime.ccRuntime::Init方法中

bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
  ...
  //-Xgc
  XGcOption xgc_option = runtime_options.GetOrDefault(Opt::GcOption);
  heap_ = new gc::Heap(runtime_options.GetOrDefault(Opt::MemoryInitialSize),//-Xms:8m
                       //-XX:HeapGrowthLimit:256m
                       runtime_options.GetOrDefault(Opt::HeapGrowthLimit),
                       //-XX:HeapMinFree:512k
                       runtime_options.GetOrDefault(Opt::HeapMinFree),
                       //-XX:HeapMaxFree:8m
                       runtime_options.GetOrDefault(Opt::HeapMaxFree),
                       //-XX:HeapTargetUtilization:0.75
                       runtime_options.GetOrDefault(Opt::HeapTargetUtilization),
                       //-XX:ForegroundHeapGrowthMultiplier
                       runtime_options.GetOrDefault(Opt::ForegroundHeapGrowthMultiplier),
                       //-Xmx:512m
                       runtime_options.GetOrDefault(Opt::MemoryMaximumSize),
                       //-XX:NonMovingSpaceCapacity
                       runtime_options.GetOrDefault(Opt::NonMovingSpaceCapacity),
                       //-Ximage:/system/framework/boot.art
                       runtime_options.GetOrDefault(Opt::Image),
                       //imgaeinstructionset,是一个extra_info,用来hook: null
                       runtime_options.GetOrDefault(Opt::ImageInstructionSet),
                       //-Xgc:kuseReadBarrier ? gc::kCollectorTypeCC : gc::kCollectorTypeDefault
                       xgc_option.collector_type_,
                       //-XX:BackgroundGC
                       runtime_options.GetOrDefault(Opt::BackgroundGc),
                       //-XX:LargeObjectSpace
                       runtime_options.GetOrDefault(Opt::LargeObjectSpace),
                       //-XX:LargeObjectThreshold
                       runtime_options.GetOrDefault(Opt::LargeObjectThreshold),
                       //-XX:ParallelGCThreads:0u
                       runtime_options.GetOrDefault(Opt::ParallelGCThreads),
                       //-XX:ConcGCThreads
                       runtime_options.GetOrDefault(Opt::ConcGCThreads),
                       //-XX:LowMemoryMode:false
                       runtime_options.Exists(Opt::LowMemoryMode),
                       //-XX:LongPauseLogThreshold
                       runtime_options.GetOrDefault(Opt::LongPauseLogThreshold),
                       //-XX:LongGCLogThreshold
                       runtime_options.GetOrDefault(Opt::LongGCLogThreshold),
                       //-XX:IgnoreMaxFootprint
                       runtime_options.Exists(Opt::IgnoreMaxFootprint),
                       //-XX:UseTLAB
                       runtime_options.GetOrDefault(Opt::UseTLAB),
                       //default false
                       xgc_option.verify_pre_gc_heap_,
                       //default kIsDebugBuild
                       xgc_option.verify_pre_sweeping_heap_, 
                       //default false
                       xgc_option.verify_post_gc_heap_, 
                       //default kIsDebugBuild
                       xgc_option.verify_pre_gc_rosalloc_, 
                       // default false
                       xgc_option.verify_pre_sweeping_rosalloc_,
                       //default false
                       xgc_option.verify_post_gc_rosalloc_,
                       //default false
                       xgc_option.gcstress_,
                       //-XX:EnableHSpaceCompactForOOM
                       runtime_options.GetOrDefault(Opt::EnableHSpaceCompactForOOM),
                       //-XX:HspaceCompactForOOMMinIntervalMs
                       runtime_options.GetOrDefault(Opt::HSpaceCompactForOOMMinIntervalsMs));
  ...
}

一. 相关知识预热

1.1 Garbage Collection Type

垃圾回收的算法有多种,如MarkSweep-标记清楚算法,MarkCompact-标记整理算法,Copying-复制算法等等,之前的Dalvik一直使用的是MarkSweep算法,ART则在MarkSweep的基础上添加了对其他垃圾回收算法的支持,具体的算法可以通过-Xgc指定,如果没有特别指定,则使用默认指定的:

// /art/smdline/cmdline_types.h
gc::CollectorType collector_type_ =  kUseReadBarrier ?
                                           // If RB is enabled (currently a build-time decision),
                                           // use CC as the default GC.
                                           gc::kCollectorTypeCC :
                                           gc::kCollectorTypeDefault;                                           

kUseReadBarrier定义在/art/runtime/globals.h

#ifdef USE_BAKER_READ_BARRIER
static constexpr bool kUseBakerReadBarrier = true;
#else
static constexpr bool kUseBakerReadBarrier = false;
#endif

#ifdef USE_BROOKS_READ_BARRIER
static constexpr bool kUseBrooksReadBarrier = true;
#else
static constexpr bool kUseBrooksReadBarrier = false;
#endif

#ifdef USE_TABLE_LOOKUP_READ_BARRIER
static constexpr bool kUseTableLookupReadBarrier = true;
#else
static constexpr bool kUseTableLookupReadBarrier = false;
#endif

static constexpr bool kUseBakerOrBrooksReadBarrier = kUseBakerReadBarrier || kUseBrooksReadBarrier;
static constexpr bool kUseReadBarrier =
    kUseBakerReadBarrier || kUseBrooksReadBarrier || kUseTableLookupReadBarrier;

kUseReadBarrier根据三个编译宏决定true或false,只要这个三个编译宏中有一个存在,则kUseReadBarrier=true

gc::kCollectorTypeCCgc::kCollectorTypeDefault定义在/art/runtime/gc/collector_type.h

enum CollectorType {
  // No collector selected.
  kCollectorTypeNone,
  //普通Mark-Sweep
  kCollectorTypeMS,
  // 并发Mark-Sweep.
  kCollectorTypeCMS,
  // Semi-space和Mark-Sweep的混合
  kCollectorTypeSS,
  // Generational Semi-space
  kCollectorTypeGSS,
  // Mark compact
  kCollectorTypeMC,
  // Heap trimming collector, doesn't do any actual collecting.
  kCollectorTypeHeapTrim,
  // A (mostly) concurrent copying collector.
  kCollectorTypeCC,
  // Instrumentation critical section fake collector.
  kCollectorTypeInstrumentation,
  // Fake collector for adding or removing application image spaces.
  kCollectorTypeAddRemoveAppImageSpace,
  // A homogeneous space compaction collector used in background transition
  // when both foreground and background collector are CMS.
  kCollectorTypeHomogeneousSpaceCompact,
  // Class linker fake collector.
  kCollectorTypeClassLinker,
};

static constexpr CollectorType kCollectorTypeDefault =
#if ART_DEFAULT_GC_TYPE_IS_CMS
    kCollectorTypeCMS
#elif ART_DEFAULT_GC_TYPE_IS_SS
    kCollectorTypeSS
#elif ART_DEFAULT_GC_TYPE_IS_GSS
    kCollectorTypeGSS
#else
    kCollectorTypeCMS
#error "ART default GC type must be set"
#endif

从代码中的定义可以看到,如果kUseReadBarrier=true,则垃圾回收算法使用Concurrent-Copying,否则默认算法,默认算法根据编译宏选择,没有特别指定的情况下使用Concurrent Mark-Sweep

二. Heap::Heap()

2.1 构造函数声明

Heap(size_t initial_size,//堆的初始大小
      size_t growth_limit,//堆的增长上限
      size_t min_free,//堆的最小空闲值
      size_t max_free,//堆的最大空闲值
      double target_utilization,//堆的目标利用率
      double foreground_heap_growth_multiplier,//前台堆增长因子(乘数)
      size_t capacity,//堆的容量
      size_t non_moving_space_capacity,//存储不可移动对象的space的容量
      const std::string& original_image_file_name,//image文件路径
      InstructionSet image_instruction_set,//指令集
      CollectorType foreground_collector_type,//前台回收器类型
      CollectorType background_collector_type,//后台回收器类型
      space::LargeObjectSpaceType large_object_space_type,//存储大对象的space类型
      size_t large_object_threshold,//大对象数量的阈值
      size_t parallel_gc_threads,//GC暂停阶段用于同时执行GC任务的线程数
      size_t conc_gc_threads,//并行GC的线程数
      bool low_memory_mode,//是否是low memory mode
      size_t long_pause_threshold,//GC造成应用程序暂停的时间阀值,超过则输出log
      size_t long_gc_threshold,//GC时间阀值,超过则输出log
      bool ignore_max_footprint,//不对堆的增长进行限制,堆可以增长到它的最大容量
      bool use_tlab,//是否开启TLAB选项
      bool verify_pre_gc_heap,//是否在开始GC前验证堆
      bool verify_pre_sweeping_heap,//是否在GC执行清扫前验证堆
      bool verify_post_gc_heap,//是否在GC完成清扫后验证堆
      bool verify_pre_gc_rosalloc,//是否在开始GC前验证RosAllocSpace
      bool verify_pre_sweeping_rosalloc,//是否在GC执行清扫前验证RosAllocSpace
      bool verify_post_gc_rosalloc,//是否在GC完成清扫后验证RosAllocSpace
      bool gc_stress_mode,
      bool use_homogeneous_space_compaction,//是否使用homogeneous space compaction来避免OOM
      uint64_t min_interval_homogeneous_space_compaction_by_oom);//两次OOM引起homogeneous space compaction时间间隔

2.2 构造函数实现

2.2.1 字段初始化

Heap::Heap(...) :
      //space::MallocSpace*,存放不可移动对象
      non_moving_space_(nullptr),
      //kAllocatorTypeROSAlloc space
      rosalloc_space_(nullptr),
      //kAllocatorTypeDlMalloc space
      dlmalloc_space_(nullptr),
      //GC操作的主要space,这个space不是dlmalloc_space_就是rosalloc_space_
      main_space_(nullptr),
      //回收器类型
      collector_type_(kCollectorTypeNone),
      //前台回收器类型
      foreground_collector_type_(foreground_collector_type),
      //后台回收器类型
      background_collector_type_(background_collector_type),
      //希望的回收器类型,如果它!=collector_type_, heap trimming daemon会transitions堆
      desired_collector_type_(foreground_collector_type_),
      //Mutex*
      pending_task_lock_(nullptr),
      //GC暂停阶段用于同时执行GC任务的线程数
      parallel_gc_threads_(parallel_gc_threads),
      //concurrent gc线程数
      conc_gc_threads_(conc_gc_threads),
      //是否是低内存模式
      low_memory_mode_(low_memory_mode),
      //GC造成应用程序暂停的时间阀值,超过则输出log
      long_pause_log_threshold_(long_pause_log_threshold),
      //GC时间阀值,超过则输出log
      long_gc_log_threshold_(long_gc_log_threshold),
      //是否对堆的增长不限制
      ignore_max_footprint_(ignore_max_footprint),
      //zygote space创建时的锁, Mutex
      zygote_creation_lock_("zygote creation lock", kZygoteCreationLock),
      //space::ZygoteSpace 在zygote space创建之前不会包含大对象
      zygote_space_(nullptr),
      //大对象数量的阈值
      large_object_threshold_(large_object_threshold),
      //跟踪在JNI critical section中有多少个线程
      disable_thread_flip_count_(0),
      thread_flip_running_(false),
      //正在运行的回收器类型
      collector_type_running_(kCollectorTypeNone),
      //最后一次运行的GC类型
      last_gc_type_(collector::kGcTypeNone),
      //下一次将要运行的GC类型
      next_gc_type_(collector::kGcTypePartial),
      //堆的容量
      capacity_(capacity),
      //堆的增长上限
      growth_limit_(growth_limit),
      //分配对象的上限数,一旦超过着搁置会引起一次GC
      max_allowed_footprint_(initial_size),
      //由registerNativeAllocation请求的一次concurrent GC需要的临界线, size_t
      native_footprint_gc_watermark_(initial_size),
      //bool, 是否需要在下一次的native allocation中运行finalizers
      native_need_to_run_finalization_(false),
      //当num_bytes_allocated_超过该值后,concurrent GC会启动
      concurrent_start_bytes_(std::numeric_limits<size_t>::max()),
      //总共释放的bytes自从heap创建以来
      total_bytes_freed_ever_(0),
      //总共释放的对象自从heap创建以来
      total_objects_freed_ever_(0),
      //当前分配的bytes数量.每次释放和分配以后都会更新
      num_bytes_allocated_(0),
      //native分配的bytes数量
      native_bytes_allocated_(0),
      //Mutex
      native_histogram_lock_("Native allocation lock"),
      //Histogram<uint64_t>,native分配的统计图
      native_allocation_histogram_("Native allocation sizes",
                                   1U,
                                   kNativeAllocationHistogramBuckets),
      //native释放的统计图
      native_free_histogram_("Native free sizes", 1U, kNativeAllocationHistogramBuckets),
      num_bytes_freed_revoke_(0),
      verify_missing_card_marks_(false),
      verify_system_weaks_(false),
     //是否在开始GC前验证堆
      verify_pre_gc_heap_(verify_pre_gc_heap),
      //是否在GC执行清扫前验证堆
      verify_pre_sweeping_heap_(verify_pre_sweeping_heap),
      //是否在GC完成清扫后验证堆
      verify_post_gc_heap_(verify_post_gc_heap),
      //是否验证ModUnionTable
      verify_mod_union_table_(false),
      //是否在开始GC前验证RosAllocSpace
      verify_pre_gc_rosalloc_(verify_pre_gc_rosalloc),
      //是否在GC执行清扫前验证RosAllocSpace
      verify_pre_sweeping_rosalloc_(verify_pre_sweeping_rosalloc),
      //是否在GC完成清扫后验证RosAllocSpace
      verify_post_gc_rosalloc_(verify_post_gc_rosalloc),
      /* For GC a lot mode, we limit the allocations stacks to be kGcAlotInterval allocations. This
       * causes a lot of GC since we do a GC for alloc whenever the stack is full. When heap
       * verification is enabled, we limit the size of allocation stacks to speed up their
       * searching.
       */
      //分配栈最大数量
      max_allocation_stack_size_(kGCALotMode ? kGcAlotAllocationStackSize
          : (kVerifyObjectSupport > kVerifyObjectModeFast) ? kVerifyObjectAllocationStackSize :
          kDefaultAllocationStackSize),
      //当前分配器    
      current_allocator_(kAllocatorTypeDlMalloc),
      //当前不可移动对象分配器
      current_non_moving_allocator_(kAllocatorTypeNonMoving),
      //阶跃型指针space
      bump_pointer_space_(nullptr),
      //临时space,Semispace回收器会将对象拷贝至这里
      temp_space_(nullptr),
      //RegionSpace 有一系列大小相等的区域组成
      region_space_(nullptr),
      //最小空余内存
      min_free_(min_free),
      //最大空余内存
      max_free_(max_free),
      //堆目标利用率
      target_utilization_(target_utilization),
      //前台堆增长因子
      foreground_heap_growth_multiplier_(foreground_heap_growth_multiplier),
      //mutators暂停等待GC的总共时间
      total_wait_time_(0),
      //VerifyObjectMode, 目前heap verification的状态
      verify_object_mode_(kVerifyObjectModeDisabled),
      //Compacting GC disable count
      disable_moving_gc_count_(0),
      is_running_on_memory_tool_(Runtime::Current()->IsRunningOnMemoryTool()),
      use_tlab_(use_tlab),
      //homogeneous space compaction时的新main space
      main_space_backup_(nullptr),
      //两次OOM引起homogeneous space compaction时间间隔
      min_interval_homogeneous_space_compaction_by_oom_(
          min_interval_homogeneous_space_compaction_by_oom),
      //上一次由OOM引起的HomogeneousSpaceCompact的时间
      last_time_homogeneous_space_compaction_by_oom_(NanoTime()),
      //CollectorTransitionTask*
      pending_collector_transition_(nullptr),
      //HeapTrimTask*
      pending_heap_trim_(nullptr),
      //是否使用homogeneous space compaction来避免OOM
      use_homogeneous_space_compaction_for_oom_(use_homogeneous_space_compaction_for_oom),
      //如果当前的回收工作导致一些线程暂停,则该值为true
      running_collection_is_blocking_(false),
      //blocking gc 数量
      blocking_gc_count_(0U),
      //blocking gc总共持续时间
      blocking_gc_time_(0U),
      //GC count rate统计图最后已更新时间
      last_update_time_gc_count_rate_histograms_(  // Round down by the window duration.
          (NanoTime() / kGcCountRateHistogramWindowDuration) * kGcCountRateHistogramWindowDuration),
      //在上一个window运行的GC数量
      gc_count_last_window_(0U),
      //在上一个window运行的blocking GC数量
      blocking_gc_count_last_window_(0U),
      //每一个window的GC调用统计图
      gc_count_rate_histogram_("gc count rate histogram", 1U, kGcCountRateMaxBucketCount),
      //每一个window的blocking GC调用统计图
      blocking_gc_count_rate_histogram_("blocking gc count rate histogram", 1U,
                                        kGcCountRateMaxBucketCount),
      //是否支持allocation tracking
      alloc_tracking_enabled_(false),
      //Mutex*
      backtrace_lock_(nullptr),
      seen_backtrace_count_(0u),
      unique_backtrace_count_(0u),
      gc_disabled_for_shutdown_(false) {

2.2.2 具体创建逻辑

Heap的构造函数的代码较多,不过整体逻辑比较清晰,整体逻辑可以分为以下几块:

  1. 判断当前是否在zygote进程,如果不在zygote,将background_collector_type_设为和foreground_collector_type_一样,并检查传入的desired_collector_type_collector_type_是否一样,如果不一样,则将collector_type_设为desired_collector_type_
  Runtime* const runtime = Runtime::Current();
    //判断当前是否是zygote模式,如果不是判断后台回收器类型是否和前台回收器相等,不想等,则设为相等
    const bool is_zygote = runtime->IsZygote();
    if (!is_zygote) {
        if (background_collector_type_ != foreground_collector_type_) {
            ...
            background_collector_type_ = foreground_collector_type_;
        }
    }
    //检查collector_type_是否和desired_collector_type_相等,不等的话将collector_type_置为desired_collector_type_
    ChangeCollector(desired_collector_type_);
  1. 创建两个HeapBitmap(live_bitmap_:用来记录上次GC之后还存活的对象;mark_bitmap_:用来记录当前GC中还存活的对象)
live_bitmap_.reset(new accounting::HeapBitmap(this));
mark_bitmap_.reset(new accounting::HeapBitmap(this));
  1. 如果foreground_collector_type_是Concurrent-Copying,设置requested_alloc_space_begin即alloc space的起始地址为(如果前台回收器是CC则是300MB-non_moving_space_capacity,否则是nullptr)
if (foreground_collector_type_ == kCollectorTypeCC) {
    ...  
    requested_alloc_space_begin = reinterpret_cast<uint8_t*>(300 * MB) - non_moving_space_capacity;
}
  1. 根据传入的image文件路径(/system/framework/boot.art)创建ImageSpace,在ImageSpace后面紧跟的是/system/framework/boot.oat,如果创建成功,将requested_alloc_space_begin指向boot.oat地址的末尾;如果创建ImageSpace失败,删除已加载的Space,将requested_alloc_space_begin指回原来的(300MB-non_moving_space_capacity)
//创建ImageSpace, image_file_name是/system/framework/boot.art
if (!image_file_name.empty()) {
    std::vector<std::string> image_file_names;
    image_file_names.push_back(image_file_name);
    std::vector<space::Space*> added_image_spaces;
    uint8_t* const original_requested_alloc_space_begin = requested_alloc_space_begin;
    for (size_t index = 0; index < image_file_names.size(); ++index) {
        std::string& image_name = image_file_names[index];///system/framework/boot.art
        std::string error_msg;
        //创建boot_image_space
        space::ImageSpace* boot_image_space = space::ImageSpace::CreateBootImage(
                image_name.c_str(),
                image_instruction_set,
                index > 0,
                &error_msg);
        //创建boot_image_space成功
        if (boot_image_space != nullptr) {
            /* 根据boot_image_space是否时连续空间,将boot_image_space添加到对应的Space列表,并在live_bitmap_和mark_bitmap_中添加对应的位图 */
            AddSpace(boot_image_space);
            added_image_spaces.push_back(boot_image_space);
            //Oat文件即boot.oat紧跟在boot_image_space末尾
            uint8_t* oat_file_end_addr = boot_image_space->GetImageHeader().GetOatFileEnd();
            ...
            //将boot.oat的地址按页大小(pageSize)对齐
            requested_alloc_space_begin = AlignUp(oat_file_end_addr, kPageSize);
            boot_image_spaces_.push_back(boot_image_space);

            if (index == 0) {
              //如果是第一块Space,检查是否还有其他的oat文件需要加载
              const OatFile* boot_oat_file = boot_image_space->GetOatFile();
              if (boot_oat_file == nullptr) {
                continue;
              }
              //如果还有其他的oat文件,根据OatHeader获取boot_classpath,再根据boot_classpath生成
              //oat文件完整路径,将完整路径添加进image文件列表,从而可以在下次循环中加载
              const OatHeader& boot_oat_header = boot_oat_file->GetOatHeader();
              const char* boot_classpath =
                  boot_oat_header.GetStoreValueByKey(OatHeader::kBootClassPathKey);
              if (boot_classpath == nullptr) {
                continue;
              }
              space::ImageSpace::CreateMultiImageLocations(image_file_name,
                                                                 boot_classpath,
                                                                 &image_file_names);
            }
        } else {
            //创建ImageSpace失败, 删除已加载的Space
            for (space::Space* loaded_space : added_image_spaces) {
              RemoveSpace(loaded_space);
              delete loaded_space;
            }
            boot_image_spaces_.clear();
            requested_alloc_space_begin = original_requested_alloc_space_begin;
            break;
        }
    }
}
  1. 判断是否支持Homogeneous-Space-Compact.当background_collector_type_是Homogeneous-Space-Compact或者foreground_collector_type_不是GSS(Generational Semi-Space)CC(Concurrent-Copying)时,支持Homogeneous-Space-Compact
if (foreground_collector_type_ == kCollectorTypeGSS ||
            foreground_collector_type_ == kCollectorTypeCC) {
      use_homogeneous_space_compaction_for_oom_ = false;
}
//如果后台回收器是homogeneous space compact或者前台回收器不是GSS和CC时,支持homogeneous space compact
bool support_homogeneous_space_compaction =
      background_collector_type_ == gc::kCollectorTypeHomogeneousSpaceCompact ||
      use_homogeneous_space_compaction_for_oom_;
  1. 判断是否给Non-Moving Space独立的地址.只要以下满足四个条件中的一项就会给Non-Moving Space独立地址(处于Zygote;支持Homogeneous-Space-Compact(foreground_collector_type_不是GSS或者不是CC);foreground_collector_type_可以移动对象;background_collector_type_可以移动对象), 之后再排除foreground_collector_type_是GSS的情况,即前台回收器是GSS时,不给Non-Moving Space独立地址
//如果当前处于Zygote模式或者支持homogeneous space compact或者前台回收器是可以移动对象的或者后台回收器也可以移动对象时
//给non_moving_space一个独立的地址
bool separate_non_moving_space = is_zygote ||
          support_homogeneous_space_compaction || IsMovingGc(foreground_collector_type_) ||
          IsMovingGc(background_collector_type_);
//再次检查前台进程是否是GSS,如果是,则不给non_moving_space_一个独立的地址
if (foreground_collector_type_ == kCollectorTypeGSS) {
    separate_non_moving_space = false;
}

只要传入的type是SS,GSS,CC,MC,Homogeneous-Space-Compact其中一个时,IsMovingGc返回的都是true

  1. 创建两个内存映射MemMap
std::unique_ptr<MemMap> main_mem_map_1;
std::unique_ptr<MemMap> main_mem_map_2;
  1. 如果之前创建ImageSpace失败同时foreground_collector_type_MarkSweep而且此时的Runtime由dex2oat创建即处于dex2oat进程中时,将requested_alloc_space_begin指向kAllocSpaceBeginForDeterministicAoT
// 如果前台回收器是MS(MarkSweep)且requested_alloc_space_begin
// 是null(即之前ImageSpace创建失败)同时当前是dex2oat程序
// 将requested_alloc_space_begin设为kAllocSpaceBeginForDeterministicAoT
if (foreground_collector_type_ == kCollectorTypeMS &&
            requested_alloc_space_begin == nullptr &&
            Runtime::Current()->IsAotCompiler()) {
    requested_alloc_space_begin = reinterpret_cast<uint8_t*>(kAllocSpaceBeginForDeterministicAoT);
}
  1. 初始化request_begin.如果Non-Moving Space有独立地址,根据当前是否是zygote确定Non-Moving Space的名字,之后创建一块匿名内存映射,由non_moving_space_mem_map指向,non_moving_space_mem_map紧跟在requested_alloc_space_begin后面,如果ImageSpace创建成功,就是紧跟在ImageSpace+boot.oat后面,否则紧跟在kAllocSpaceBeginForDeterministicAoT后面,最后设置request_begin为300MB,即其他Space的起始地址为300MB
uint8_t* request_begin = requested_alloc_space_begin;
if (request_begin != nullptr && separate_non_moving_space) {
    request_begin += non_moving_space_capacity;
}
std::string error_str;
std::unique_ptr<MemMap> non_moving_space_mem_map;
//如果确定给non moving space一块独立的地址
if (separate_non_moving_space) {
    ScopedTrace trace2("Create separate non moving space");
    // 如果当前正在Zygote当中,将non moving space设为zygote space
    const char* space_name = is_zygote ? kZygoteSpaceName: kNonMovingSpaceName;
    //创建匿名内存映射
    //non moving sapce紧跟在requested_alloc_space_begin后面(即如果ImageSpace创建成功,紧跟在ImageSpace + boo.oat后面)
    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));
    ...
    // 如果要给non moving space一个独立的地址, 将其他Space的起始地址设为300MB,由request_begin指向
    request_begin = reinterpret_cast<uint8_t*>(300 * MB);
}
  1. 如果foreground_collector_type_不是CC,初始化之前创造的main_mem_map_1,这块内存的作用是作为MarkSweepMain Space或者Compact GCFrom-Bump-Space.当Non-Moving Space有独立地址且当前不处于Zygote时,紧跟在300MB后面创建匿名内存映射;否则紧跟在ImageSpace+boot.oat后面创建匿名内存映射
//如果前台回收器不是CC,创建第一块匿名共享内存,由main_mem_map_1指向,这块内存的作用是作为Compact GC的From Bump Space或者
//MarkSweep的Main Space
if (foreground_collector_type_ != kCollectorTypeCC) {
      ScopedTrace trace2("Create main mem map");
      if (separate_non_moving_space || !is_zygote) {
          //如果non moving space有独立地址或者当前不是zygote,则main_mem_map_1紧跟在  request_begin后面,即300MB后面
          //名字是main space
          main_mem_map_1.reset(MapAnonymousPreferredAddress(kMemMapSpaceName[0],
                                                            request_begin,
                                                            capacity_,
                                                            &error_str));
      } else {
          //如果non-moving space有独立地址且当前处于zygote或者non-moving space没有独立地址,
          //则main space必须紧跟在ImageSpace后面,这样zygote space就会临近ImageSpace
          main_mem_map_1.reset(MemMap::MapAnonymous(kMemMapSpaceName[0], request_begin, capacity_,
                                                    PROT_READ | PROT_WRITE, true, false,
                                                    &error_str));
      }
      ...
}
  1. 如果支持Homogeneous-Space-Compact或者background_collector_type_foreground_collector_type_其中一个是SS时,创建第二块匿名内存映射main_mem_map_2
//如果支持homogeneous space compact或者后台回收器和前台回收器中有一个为为SS(Semi Space)时,创建第二块匿名共享内存
//由main_mem_map_2指向
if (support_homogeneous_space_compaction ||
        background_collector_type_ == kCollectorTypeSS ||
        foreground_collector_type_ == kCollectorTypeSS) {
      ScopedTrace trace2("Create main mem map 2");
      main_mem_map_2.reset(MapAnonymousPreferredAddress(kMemMapSpaceName[1], main_mem_map_1->End(),
                                                            capacity_, &error_str));
      ...
}
  1. 如果Non-Moving Space有独立地址,则之前已经创建了匿名内存映射non_moving_space_mem_map,现在将这块内存封装成DlMallocSpace,由non-moving_space指向,并将这块Space添加至Space列表中
//如果non moving space有独立的地址时,将non_moving_space_mem_map封装成Non-Moving Space(space::MallocSpace)
if (separate_non_moving_space) {
      ScopedTrace trace2("Add non moving space");
      //Non-Moving Space必须是dlmalloc,因为目前并不支持多个rosalloc spaces
      const size_t size = non_moving_space_mem_map->Size();
      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大小限制
      non_moving_space_->SetFootprintLimit(non_moving_space_->Capacity());
      ...
      //将non_moving_space_添加至space列表中
      AddSpace(non_moving_space_);
}
  1. 根据条件处理之前创建的另外两块匿名内存映射main_mem_map_1main_mem_map_2.因为在之前的逻辑中,当foreground_collector_type_是CC时,并没有创建main_mem_map_1匿名内存映射,所以如果foreground_collector_type_恰好是CC时,紧跟request_begin(如果Non-Moving Space有独立地址,则是300MB,否则是ImageSpace+boot.oat)创建一个RegionSpace,由region_space_指向; 如果foreground_collector_type_不是CC时,也要分两种情况:(1)foreground_collector_type_SS,MC,Homogeneous-Space-Compact中的一个;(2)foreground_collector_type_MarkSweep, Compact MarkSweep或者GSS. 对于第一种情况来说,将main_mem_map_1封装成BumpPointerSpace1并添加至space列表,由bump_pointer_space_指向,将main_mem_map_2封装成另一块BumpPointerSpace2同样添加至space列表,由temp_space_指向;对于第二种情况,首先将main_mem_map_1封装成MainSpace同时添加至space列表,之后如果Non-Moving Space没有独立地址,则将non_moving_space_指向MainSpace,即MainSpace和Non-Moving Space共用同一块内存,接着判断如果foreground_collector_type_是GSS时,调用BumpPointerSpace::Craete直接创建BumpPointerSpace1(bump_pointer_space_)和BumpPointerSpace2(temp_space_)并依次添加至space列表;如果foreground_collector_type_不是GSS时,即MarkSweepCompact MarkSweep,且main_mem_map_2不为空时(如果支持HomogeneousSpaceCompact),将main_mem_map_2封装成Backup Space,并添加至space列表
if (foreground_collector_type_ == kCollectorTypeCC) {
      // 如果前台回收器是CC(Concurrent Copying),创建RegionSpace,并将RegionSpace添加至space列表
      region_space_ = space::RegionSpace::Create("Region space", capacity_ * 2, request_begin);
      AddSpace(region_space_);
} else if (IsMovingGc(foreground_collector_type_) &&
          foreground_collector_type_ != kCollectorTypeGSS) {
      //如果前台回收器是除了GSS(Generational Semi-Space)以外的Compact GC,将main_mem_map_1封装成BumpPointerSpace
      //并将bump_pointer_space_添加至space列表
      // TODO: Place bump-pointer spaces somewhere to minimize size of card table.
      bump_pointer_space_ = space::BumpPointerSpace::CreateFromMemMap("Bump pointer space 1",
                                                                            main_mem_map_1.release());
      ...
      AddSpace(bump_pointer_space_);
      //将main_mem_map_2封装成第二块BumpPointerSpace,由temp_space_指向,同时将temp_space_添加至space列表
      temp_space_ = space::BumpPointerSpace::CreateFromMemMap("Bump pointer space 2",
                                                                    main_mem_map_2.release());
      ...
      AddSpace(temp_space_);
      ...
} else {
      //如果前台回收器不是Compact GC即MarkSweep或者是GSS,则在main_mem_map_1创建Main Space,并将Main Space添加至space列表
      CreateMainMallocSpace(main_mem_map_1.release(), initial_size, growth_limit_, capacity_);
      ...
      AddSpace(main_space_);
      if (!separate_non_moving_space) {
          //如果Non-Moving Space没有独立地址,则将non_moving_space_指向main_space_,即Non-Moving Space和Main Space是同一块Space
          non_moving_space_ = main_space_;
          ...
      }
      if (foreground_collector_type_ == kCollectorTypeGSS) {
          ....
          //如果前台回收器是GSS, 并创建BumpPointerSpace,由bump_pointer_space_指向
          //同时将bump_pointer_space_添加至space列表
          main_mem_map_2.release();
          bump_pointer_space_ = space::BumpPointerSpace::Create("Bump pointer space 1",
                                                              kGSSBumpPointerSpaceCapacity, nullptr);
          ...
          AddSpace(bump_pointer_space_);
          //创建第二块BumpPointerSpace,由temp_space_指向,并将temp_space_添加至space列表
          temp_space_ = space::BumpPointerSpace::Create("Bump pointer space 2",
                                                            kGSSBumpPointerSpaceCapacity, nullptr);
          ...
          AddSpace(temp_space_);
      }  else if (main_mem_map_2.get() != nullptr) {
          //此时前台回收器根据排除法只剩MarkSweep了,将main_mem_map_2封装成Backup Space,由main_space_backup_指向
          //同时将main_space_backup_添加至space列表,如果kUseRosAlloc为true,main_space_backup_为RosAllocSpace,否则为DlMallocSpace
          const char* name = kUseRosAlloc ? kRosAllocSpaceName[1] : kDlMallocSpaceName[1];
          main_space_backup_.reset(CreateMallocSpaceFromMemMap(main_mem_map_2.release(), initial_size,
                                                                   growth_limit_, capacity_, name, true));
          ...
          AddSpace(main_space_backup_.get());
        }
}
  1. 创建大对象存储空间.
// 创建LargeObjectSpace(大对象存储空间)
if (large_object_space_type == space::LargeObjectSpaceType::kFreeList) {
      //如果LargeObjectSpace类型是FreeList,创建FreeList类型的LargeObjectSpace
      large_object_space_ = space::FreeListSpace::Create("free list large object space", nullptr,
                                                               capacity_);
      ...
} else if (large_object_space_type == space::LargeObjectSpaceType::kMap) {
      //创建相互独立的内存快组成的LargeObjectSpace
      large_object_space_ = space::LargeObjectMapSpace::Create("mem map large object space");
      ...
} else {
      large_object_threshold_ = std::numeric_limits<size_t>::max();
      large_object_space_ = nullptr;
}
//如果LargeObjectSpace不为空,则添加至Space列表
if (large_object_space_ != nullptr) {
      AddSpace(large_object_space_);
}
  1. 如果foreground_collector_type_是MarkSweep或Compact MarkSweep且创建了Backup Space时,由于Backup Space占用的额外的空间会降低GC速度,所以移除Backup Space;之后创建CardTable(Card Table是为了记录在垃圾收集过程中对象的引用情况的), ModUnionTable(来记录ImageSpace对ZygoteSpace引用情况的ModUnionTable), RememberSet(用来记录Non-moving Space对其他Space引用情况的RememberedSet, GSS时不会创建,CC, SS, MC, HomogeneousSpaceCompact时根据collector::SemiSpace::kUseRememberedSet == true判断, MS,CMS时根据Non-Moving Space有没有独立地址加collector::SemiSpace::kUseRememberedSet == true判断)
//获取连续空间的起始地址和结束地址
uint8_t* heap_begin = continuous_spaces_.front()->Begin();
uint8_t* heap_end = continuous_spaces_.back()->Limit();
size_t heap_capacity = heap_end - heap_begin;
//移除main_space_backup_,此时foreground_collector_type_是MarkSweep
//因为Backup Space的额外的未使用的空间降低了GC速度
if (main_space_backup_.get() != nullptr) {
       RemoveSpace(main_space_backup_.get());
}
...
// 创建card table,因为不知道在low_4gb模式下,app image会在何处定位,
// 所以card table将会从64KB开始覆盖整个4GB的低地址,64KB以前的地址预留给kernel
static constexpr size_t kMinHeapAddress = 4 * KB;
card_table_.reset(accounting::CardTable::Create(reinterpret_cast<uint8_t*>(kMinHeapAddress), 4 * GB - kMinHeapAddress));
....
//如果前台回收器是CC(Concurrent Copying)同时kUseTableLookupReadBarrier=true,创建ReadBarrierTable
if (foreground_collector_type_ == kCollectorTypeCC && kUseTableLookupReadBarrier) {
      rb_table_.reset(new accounting::ReadBarrierTable());
    ...
}
if (HasBootImageSpace()) {
    // 如果有ImageSpace,则创建用来记录ImageSpace对ZygoteSpace引用情况的ModUnionTable
    for (space::ImageSpace* image_space : GetBootImageSpaces()) {
        accounting::ModUnionTable* mod_union_table = new     accounting::ModUnionTableToZygoteAllocspace(
              "Image mod-union table", this, image_space);
          ...
        AddModUnionTable(mod_union_table);
    }
}
//如果Non-moving Space有独立地址而且kUseRememberedSet=true,
//创建用来记录Non-moving Space对其他Space引用情况的RememberedSet
if (collector::SemiSpace::kUseRememberedSet && non_moving_space_ != main_space_) {
        accounting::RememberedSet* non_moving_space_rem_set =
            new accounting::RememberedSet("Non-moving space remembered set", this, non_moving_space_);
        ...
        AddRememberedSet(non_moving_space_rem_set);
}
  1. 创建Mark-Stack,Allocation-Stack,Live-Stack;创建之后GC需要用到的的锁;创建TaskProcessor,ReferenceProcessor;如果前后台回收器有一个是CMS,则创建一组包含三个支持并发的Collector:MarkSweep, PartialMarkSweep, StickyMarkSweep回收器; 如果前后台回收器有一个是MS,则创建一组包含三个不支持并发的Collector:MarkSweep, PartialMarkSweep, StickyMarkSweep回收器;之后再根据条件创建Semi-Space Collector(SSGSS时创建),Concurrent-Copying Collector(CC时创建),Mark Compact Collector(MS,CMSshichu)
// TODO: Count objects in the image space here?
num_bytes_allocated_.StoreRelaxed(0);
// 创建Mark-Stack, Allocation-Stack, Live-Stack
mark_stack_.reset(accounting::ObjectStack::Create("mark stack", kDefaultMarkStackSize, kDefaultMarkStackSize));
const size_t alloc_stack_capacity = max_allocation_stack_size_ + kAllocationStackReserveSize;
allocation_stack_.reset(accounting::ObjectStack::Create("allocation stack", max_allocation_stack_size_, alloc_stack_capacity));
live_stack_.reset(accounting::ObjectStack::Create("live stack", max_allocation_stack_size_, alloc_stack_capacity));
// 创建gc_complete_lock_,thread_flip_lock_
gc_complete_lock_ = new Mutex("GC complete lock");
gc_complete_cond_.reset(new ConditionVariable("GC complete condition variable",*gc_complete_lock_));
thread_flip_lock_ = new Mutex("GC thread flip lock");
thread_flip_cond_.reset(new ConditionVariable("GC thread flip condition variable",*thread_flip_lock_));
//创建TaskProcessor, ReferenceProcessor, pending_task_lock_
task_processor_.reset(new TaskProcessor());
reference_processor_.reset(new ReferenceProcessor());
pending_task_lock_ = new Mutex("Pending task lock");
if (ignore_max_footprint_) {
      //如果不限制堆的增长,则将堆的最大限制数设为最大
      SetIdealFootprint(std::numeric_limits<size_t>::max());
      //将concurrent gc的启动值也设为最大,即只有堆达到最大时,才开启concurrent gc
      concurrent_start_bytes_ = std::numeric_limits<size_t>::max();
}
...
// 如果前后台回收器有一个是CMS,则创建一组包含三个支持并发的Collector:MarkSweep, PartialMarkSweep, StickyMarkSweep回收器
// 如果前后台回收器有一个是MS,则创建一组包含三个不支持并发的Collector:MarkSweep, PartialMarkSweep, StickyMarkSweep回收器
for (size_t i = 0; i < 2; ++i) {
      const bool concurrent = i != 0;
      if ((MayUseCollector(kCollectorTypeCMS) && concurrent) ||
                (MayUseCollector(kCollectorTypeMS) && !concurrent)) {
          garbage_collectors_.push_back(new collector::MarkSweep(this, concurrent));
          garbage_collectors_.push_back(new collector::PartialMarkSweep(this, concurrent));
          garbage_collectors_.push_back(new collector::StickyMarkSweep(this, concurrent));
      }
}
if (kMovingCollector) {//kMovingCollector=true
      if (MayUseCollector(kCollectorTypeSS) || MayUseCollector(kCollectorTypeGSS) ||
                  MayUseCollector(kCollectorTypeHomogeneousSpaceCompact) ||
                  use_homogeneous_space_compaction_for_oom_) {
        //如果前后台回收器中某一个是SS,GSS,HomogeneousSpaceCompact三者其中一个或者
        //使用homogeneous space compaction来避免OOM时,再创键一个Semi-Space Collector
        const bool generational = foreground_collector_type_ == kCollectorTypeGSS;
        semi_space_collector_ = new collector::SemiSpace(this, generational,
                                                               generational ? "generational" : "");
        garbage_collectors_.push_back(semi_space_collector_);
      }
      if (MayUseCollector(kCollectorTypeCC)) {
        //如果前后台回收器中某一个是CC,再创建一个ConcurrentCopying Collector
        concurrent_copying_collector_ = new collector::ConcurrentCopying(this);
        garbage_collectors_.push_back(concurrent_copying_collector_);
      }
      if (MayUseCollector(kCollectorTypeMC)) {
        //如果前后台回收器中某一个是MarkCompact,再创建一个MarkCompact Collector
        mark_compact_collector_ = new collector::MarkCompact(this);
        garbage_collectors_.push_back(mark_compact_collector_);
      }
}
  1. 如果有ImageSpace同时Non-Moving Space不为空同时满足三个条件(处于zygote,Non-Moving Space有独立地址,前台回收器是GSS)中的一个时,检查ImageSpace和Non-Moving Space之间没有内存空隙
if (!GetBootImageSpaces().empty() && non_moving_space_ != nullptr &&
            (is_zygote || separate_non_moving_space || foreground_collector_type_ == kCollectorTypeGSS)) {
      //如果有ImageSpace同时Non-Moving Space不为空同时满足三个条件
      //(处于zygote,Non-Moving Space有独立地址,前台回收器是GSS)中的一个时,
      //检查ImageSpace和Non-Moving Space只见没有内存空隙
      space::ImageSpace* first_space = nullptr;
      for (space::ImageSpace* space : boot_image_spaces_) {
        if (first_space == nullptr || space->Begin() < first_space->Begin()) {
          first_space = space;
        }
      }
      bool no_gap = MemMap::CheckNoGaps(first_space->GetMemMap(), non_moving_space_->GetMemMap());
      if (!no_gap) {
        PrintFileToLog("/proc/self/maps", LogSeverity::ERROR);
        MemMap::DumpMaps(LOG(ERROR), true);
        ...
      }
  }
instrumentation::Instrumentation* const instrumentation = runtime->GetInstrumentation();
if (gc_stress_mode_) {
      backtrace_lock_ = new Mutex("GC complete lock");
}
if (is_running_on_memory_tool_ || gc_stress_mode_) {
      instrumentation->InstrumentQuickAllocEntryPoints();
}

三. 总结

3.1 前台回收器是ConcurrentCopying

从代码逻辑看,如果foreground_collector_type_=kCollectorTypeCC时Heap的创建流程要跟其他回收器类型的创建流程不太相同:

  1. requested_alloc_space_begin = 300MB - non_moving_space_capacity
  2. 创建ImageSpace(只要image文件不为空,都会创建),如果创建成功,requested_alloc_space_begin=ImageSpace+boo.oat

这一点所有回收器类型都一样,不同的是,如果创建失败,requested_alloc_space_begin = 300MB - non_moving_space_capacity, 其他回收器类型则是requested_alloc_space_begin = nullptr

  1. 如果background_collector_type_ != kCollectorTypeHomogeneousSpaceCompact,则不支持Homogeneous-Space-Compact
  2. 由于是CC回收器,所以必然会给Non-Moving Space独立的地址
  3. 由于是CC回收器,所以即使ImageSpace创建失败,requested_alloc_space_begin也不会为nullptr,又因为Non-Moving Space有独立的地址,所以最后request_begin=requested_alloc_space_begin + non_moving_space_capacity

如果ImageSpace创建成功,request_begin=ImageSpace+boot.oat+non_moving_space_capacity;如果创建失败,request_begin = 300MB-non_moving_space_capacity+non_moving_space_capacity->request_begin=300MB

  1. 紧跟着requested_alloc_space_begin创建用于Non-Moving Space的匿名内存映射non_moving_space_mem_map, 将request_begin固定在300MB的地址(request_begin=reinterpret_cast<uint8_t*>(300*MB));之后将匿名内存映射封装成Non-Moving Space,如果在Zygote中,就叫ZygoteSpace,否则叫Non-Moving Space
  2. 由于是CC回收器,所以不会创建两块匿名内存main_mem_map_1,main_mem_map_2,而是紧跟着在request_begin后(即300MB,因为之前已经将request_begin固定在这个地址)直接创建RegionSpace
  3. 创建LargeObjectSpace
  4. 如果kUseTableLookupReadBarrier=true,创建ReadBarrierTable
  5. 创建CardTable,ModUnionTable(如果ImageSpace创建成功),如果collector::SemiSpace::kUseRememberedSet == true创建RememberedSet;创建allocation_stack_,mark_stack_,live_stack_;创建锁;创建TaskProcessor,ReferenceProcessor
  6. 由于是CC回收器,创建collector::ConcurrentCopying并添加至garbage_collectors_
  7. 如果ImageSpace创建成功,且Non-Moving Space不为空,检查ImageSpace和Non-Moving Space之间有没有内存间隙

因为是CC,所以Non-Moving Space必然有独立地址,所以只需要判断ImageSpace创建成功和Non-Moving Space不为空

3.2 前台回收器是GSS

GSS(Generational Semi-Space)是另一个较为特殊的回收器类型

  1. requested_alloc_space_begin=nullptr
  2. 创建ImageSpace,如果成功,requested_alloc_space_begin=ImageSpace+boot.oat,如果创建失败,requested_alloc_space_begin=nullptr
  3. 如果background_collector_type_ != kCollectorTypeHomogeneousSpaceCompact,则肯定不支持Homogeneous-Space-Compact
  4. 由于是GSS回收器,所以不会给Non-Moving Space独立的地址(这一点很重要,即不会创建Non-Moving Space的匿名内存映射)
  5. 如果ImageSpace创建失败,则request_begin=requested_alloc_space_begin=nullptr;如果创建成功,则request_begin=reuqest_alloc_space_begin=ImageSpace+boo.oat
  6. 由于是GSS回收器,那么Non-Moving Space不会有独立地址,如果此时处于Zygote中,则紧跟ImageSpace+boo.oat创建匿名内存映射main_mem_map_1(因为Non-Moving Space没有独立地址,所以不会将request_begin固定在300MB,又因为如果ImageSpace创建成功此时request_begin=ImageSpace+boot.oat)
  7. 如果background_collector_type_ == kCollectorTypeHomogeneousSpaceCompact,则会紧跟着main_mem_map_1再创建第二块匿名内存映射main_mem_map_2,否则不会创建main_mem_map_2
  8. main_mem_map_1封装成Main Space,由于是GSS回收器,所以将non_moving_space_也指向Main Space
  9. 由于是GSS回收器,调用space::BumpPointerSpace::Create直接创建BumpPointerSpace1BumpPointerSpace2
  10. 创建LargeObjectSpace
  11. 创建CardTable,ModUnionTable(如果ImageSpace创建成功),由于是GSS回收器,所以non_moving_space_ == main_space_,所以不会创建RememberedSet;创建allocation_stack_,mark_stack_,live_stack_;创建锁;创建TaskProcessor,ReferenceProcessor
  12. 由于是GSS,所以创建collector::SemiSpace,其中generational_ = true
  13. 如果ImageSpace创建成功,且MainSpace不为空,检查ImageSpace和Non-Moving Space之间有没有内存间隙

因为是GSS,所以non_moving_space_指向MainSpace,所以只需要判断ImageSpace创建成功和Non-Moving Space不为空

3.3 Moving GC(Semi-Space, MarkCompact, HomogeneousSpaceCompact)

  1. requested_alloc_space_begin=nullptr
  2. 创建ImageSpace,如果成功,requested_alloc_space_begin=ImageSpace+boot.oat,如果创建失败,requested_alloc_space_begin=nullptr
  3. 由于不是GSSCC,所以只要传入的use_homogeneous_space_compaction==true或者background_collector_type_ == kCollectorTypeHomogeneousSpaceCompact时会支持Homogeneous-Space-Compact
  4. Non-Moving必然有独立的地址
  5. 如果ImageSpace创建成功,request_begin = requested_alloc_space_begin + non_moving_space_capacity,否则request_begin=nullptr
  6. 创建Non-Moving Space使用的匿名内存映射non_moving_space_mem_map,将request_begin固定在300MB的地址(request_begin=reinterpret_cast<uint8_t*>(300*MB))
  7. 紧跟request_begin创建匿名内存映射main_mem_map_1
  8. 如果支持Homogeneous-Space-Compact或者前后台回收器有一个是Semi-Space,则紧跟main_mem_map_1创建第二块匿名内存映射main_mem_map_2
  9. non_moving_space_mem_map封装成Non-Moving Space,由non_moving_space_指向
  10. main_mem_map_1封装成BumpPointerSpace1,将main_mem_map_2封装成BumpPointerSpace2
  11. 创建LargeObjectSpace
  12. 创建CardTable,ModUnionTable(如果ImageSpace创建成功),如果collector::SemiSpace::kUseRememberedSet == true创建RememberedSet;创建allocation_stack_,mark_stack_,live_stack_;创建锁;创建TaskProcessor,ReferenceProcessor
  13. 如果前后台回收器中有一个是SSHomogeneous-Space-Compact,创建collector::SemiSpace;如果前后台回收器有一个是MarkCompact,则创建collector::MarkCompact
  14. 如果ImageSpace创建成功,且Non-Moving Space不为空,检查ImageSpace和Non-Moving Space之间有没有内存间隙

因为Non-Moving必然有独立的地址,所以只需要判断ImageSpace创建成功和Non-Moving Space不为空

3.4 前台回收器MarkSweep或Concurrent MarkSweep

  1. requested_alloc_space_begin=nullptr
  2. 创建ImageSpace,如果成功,requested_alloc_space_begin=ImageSpace+boot.oat,如果创建失败,requested_alloc_space_begin=nullptr
  3. 由于不是GSSCC,所以只要传入的use_homogeneous_space_compaction=true或者background_collector_type_ == kCollectorTypeHomogeneousSpaceCompact时会支持Homogeneous-Space-Compact
  4. 只要当前处于Zygote当中,则Non-Moving Space必然有独立地址,否则得看是否支持Homogeneous-Space-Compact,支持的话,就有独立地址,不支持就没有
  5. 如果ImageSpace创建失败且foreground_collector_type_=kCollectorTypeMS同时当前处于dex2oat,requested_alloc_space_begin=kAllocSpaceBeginForDeterministicAoT
  6. 如果ImageSpace创建成功且如果Non-Moving Space有独立地址的话,创建Non-Moving Space要用到的匿名内存映射non_moving_space_mem_map,将request_begin固定在300MB的地址(request_begin=reinterpret_cast<uint8_t*>(300*MB))
  7. 如果Non-Moving Space有独立地址或者当前不在Zygote中,紧跟着request_begin(300MB)创建匿名内存映射main_mem_map_1;如果Non-Moving Space没有独立地址同时处于Zygote中,则紧跟着ImageSpace_boot.oat创建匿名内存映射main_mem_map_1
  8. 如果支持Homogeneous-Space-Compact,紧跟着main_mem_map_1创建第二块匿名内存映射main_mem_map_2,否则不创建main_mem_map_2
  9. 如果Non-Moving Space有独立地址,将non_moving_space_mem_map封装成Non-Moving Space
  10. main_mem_map_1封装成Main Space,如果Non-Moving Space没有独立地址,则将non_moving_space_也指向MainSpace
  11. 如果之前创建了main_mem_map_2,则将main_mem_map_2封装成Main Backup Space
  12. 创建LargeObjectSpace
  13. 移除Main Backup Space
  14. 创建CardTable,ModUnionTable(如果ImageSpace创建成功),如果Non-Moving Space有独立地址,创建RememberedSet,否则不创建;创建allocation_stack_,mark_stack_,live_stack_;创建锁;创建TaskProcessor,ReferenceProcessor
  15. 创建一组回收器,里面有三个回收器分别是MarkSweep, PartialMarkSweep, StickyMarkSweep,如果是Concurrent Mark Compact,则这一组回收器是支持并行GC的;如果是MarkSweep,则这一组不支持并行GC
  16. 如果ImageSpace创建成功且Non-Moving Space不为空同时满足:处于Zygote或者Non-Moving Space有独立地址时,检查ImageSpace和Non-Moving Space之间有没有内存间隙

因为Non-Moving Space有没有独立地址不确定,需要视条件而定

四. 参考资料

  1. ART运行时垃圾收集机制简要介绍和学习计划
  2. Debugging ART Garbage Collection
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容