Android ART虚拟机 GC的各种类型

前言

本文介绍ART虚拟机的GC类型,为下篇介绍ART的GC做准备。

GcRetentionPolicy

每个Space都有自己的gc回收策略,如下图所示:

  • kGcRetentionPolicyNeverCollect:不需要回收某个Space所包含的垃圾对象(因为该Space可能不存在垃圾对象)。
  • kGcRetentionPolicyAlwaysCollect:每次垃圾回收都需要处理某个Space空间。
  • kGcRetentionPolicyFullCollect:直到最后时刻才回收某个Space空间中的垃圾对象。这个最后时刻就是所谓的full GC。

image.png

垃圾收集器类型 和 内存分配器类型

各种头文件

art/runtime/gc/collector_type.h
art/runtime/gc/allocator_type.h
art/runtime/gc/gc_cause.h
art/runtime/gc/collector/garbage_collector.h

// Which types of collections are able to be performed.
enum CollectorType {
    
    
  // No collector selected.
  kCollectorTypeNone,
  // Non concurrent mark-sweep.
  kCollectorTypeMS,
  // Concurrent mark-sweep.
  kCollectorTypeCMS,
  // Semi-space / mark-sweep hybrid, enables compaction.
  kCollectorTypeSS,
  // A generational variant of kCollectorTypeSS.
  kCollectorTypeGSS,
  // Mark compact collector.
  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,
};

// Different types of allocators.
enum AllocatorType {
    
    
  kAllocatorTypeBumpPointer,  // Use BumpPointer allocator, has entrypoints.
  kAllocatorTypeTLAB,  // Use TLAB allocator, has entrypoints.
  kAllocatorTypeRosAlloc,  // Use RosAlloc allocator, has entrypoints.
  kAllocatorTypeDlMalloc,  // Use dlmalloc allocator, has entrypoints.
  kAllocatorTypeNonMoving,  // Special allocator for non moving objects, doesn't have entrypoints.
  kAllocatorTypeLOS,  // Large object space, also doesn't have entrypoints.
  kAllocatorTypeRegion,
  kAllocatorTypeRegionTLAB,
};

// What caused the GC?
enum GcCause {
    
    
  // GC triggered by a failed allocation. Thread doing allocation is blocked waiting for GC before
  // retrying allocation.
  kGcCauseForAlloc,
  // A background GC trying to ensure there is free memory ahead of allocations.
  kGcCauseBackground,
  // An explicit System.gc() call.
  kGcCauseExplicit,
  // GC triggered for a native allocation.
  kGcCauseForNativeAlloc,
  // GC triggered for a collector transition.
  kGcCauseCollectorTransition,
  // Not a real GC cause, used when we disable moving GC (currently for GetPrimitiveArrayCritical).
  kGcCauseDisableMovingGc,
  // Not a real GC cause, used when we trim the heap.
  kGcCauseTrim,
  // Not a real GC cause, used to implement exclusion between GC and instrumentation.
  kGcCauseInstrumentation,
  // Not a real GC cause, used to add or remove app image spaces.
  kGcCauseAddRemoveAppImageSpace,
  // GC triggered for background transition when both foreground and background collector are CMS.
  kGcCauseHomogeneousSpaceCompact,
  // Class linker cause, used to guard filling art methods with special values.
  kGcCauseClassLinker,
};

虚拟机启动时gc参数解析设置前后台回收器类型

oreground_collector_type_和background_collector_type_表示进程处于前台(即用户能感知)以及进程处于后台时的回收器类型。

  • 前台回收器为CMS时,后台回收器为HSC。
  • 前台回收器为SS时,后台回收器类型为HSC。
  • 前台回收器类型为GSS时,后台回收器类型也必须为GSS。

art/runtime/parsed_options.cc

bool ParsedOptions::DoParse(const RuntimeOptions& options,
                            bool ignore_unrecognized,
                            RuntimeArgumentMap* runtime_options) {
    
    

  {
    
    
    // If not set, background collector type defaults to homogeneous compaction.
    // If foreground is GSS, use GSS as background collector.
    // If not low memory mode, semispace otherwise.

    gc::CollectorType background_collector_type_;
    gc::CollectorType collector_type_ = (XGcOption{
    
    }).collector_type_;  // NOLINT [whitespace/braces] [5]
    bool low_memory_mode_ = args.Exists(M::LowMemoryMode);

    background_collector_type_ = args.GetOrDefault(M::BackgroundGc);
    {
    
    
      XGcOption* xgc = args.Get(M::GcOption);
      if (xgc != nullptr && xgc->collector_type_ != gc::kCollectorTypeNone) {
    
    
        collector_type_ = xgc->collector_type_;
      }
    }

    if (background_collector_type_ == gc::kCollectorTypeNone) {
    
    
      if (collector_type_ != gc::kCollectorTypeGSS) {
    
    
        background_collector_type_ = low_memory_mode_ ?
            gc::kCollectorTypeSS : gc::kCollectorTypeHomogeneousSpaceCompact;
      } else {
    
    
        background_collector_type_ = collector_type_;
      }
    }

    args.Set(M::BackgroundGc, BackgroundGcOption {
    
     background_collector_type_ });
  }
}

Heap构造函数根据回收器类型设置垃圾收集器

  • 回收器类型为CMS时,前台回收器类型为CMS,后台回收器类型为HSC。garbage_collectors_包含四个回收器对象,分别是MarkSweep、PartialMarkSweep、StickyMarkSweep和SemiSpace。其中,前三个回收器启用concurrent gc功能,而SemiSpace关闭分代gc的功能。
  • 回收器类型为SS时,前台回收器类型为SS,后台回收器类型为HSC,garbage_collectors_包含一个SemiSpace回收器对象(关闭分代gc功能,generational为false)。
  • 回收器类型为GSS时,前后台都使用GSS回收器,garbage_collectors_包含一个SemiSpace回收器对象,启用分代gc的功能(generational为true)。
  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_));
  task_processor_.reset(new TaskProcessor());
  reference_processor_.reset(new ReferenceProcessor());
  pending_task_lock_ = new Mutex("Pending task lock");

  // Create our garbage collectors.
  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) {
    
    
    if (MayUseCollector(kCollectorTypeSS) || MayUseCollector(kCollectorTypeGSS) ||
        MayUseCollector(kCollectorTypeHomogeneousSpaceCompact) ||
        use_homogeneous_space_compaction_for_oom_) {
    
    
      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)) {
    
    
      concurrent_copying_collector_ = new collector::ConcurrentCopying(this);
      garbage_collectors_.push_back(concurrent_copying_collector_);
    }
    if (MayUseCollector(kCollectorTypeMC)) {
    
    
      mark_compact_collector_ = new collector::MarkCompact(this);
      garbage_collectors_.push_back(mark_compact_collector_);
    }
  }

}

bool Heap::MayUseCollector(CollectorType type) const {
    
    
  return foreground_collector_type_ == type || background_collector_type_ == type;
}

ChangeCollector设置gc_plan_

  • 如果回收器类型为CMS,则gc_plan_依次为kGcTypeSticky、kGcTypePartial和kGc-TypeFull。
  • 如果回收器类型为SS或GSS,则gc_plan_只有kGcTypeFull一种策略。
// Change the collector to be one of the possible options (MS, CMS, SS).
void Heap::ChangeCollector(CollectorType collector_type) {
    
    
  if (collector_type != collector_type_) {
    
    
    collector_type_ = collector_type;
    gc_plan_.clear();
    switch (collector_type_) {
    
    
      case kCollectorTypeCC: {
    
    
        gc_plan_.push_back(collector::kGcTypeFull);
        if (use_tlab_) {
    
    
          ChangeAllocator(kAllocatorTypeRegionTLAB);
        } else {
    
    
          ChangeAllocator(kAllocatorTypeRegion);
        }
        break;
      }
      case kCollectorTypeMC:  // Fall-through.
      case kCollectorTypeSS:  // Fall-through.
      case kCollectorTypeGSS: {
    
    
        gc_plan_.push_back(collector::kGcTypeFull);
        if (use_tlab_) {
    
    
          ChangeAllocator(kAllocatorTypeTLAB);
        } else {
    
    
          ChangeAllocator(kAllocatorTypeBumpPointer);
        }
        break;
      }
      case kCollectorTypeMS: {
    
    
        gc_plan_.push_back(collector::kGcTypeSticky);
        gc_plan_.push_back(collector::kGcTypePartial);
        gc_plan_.push_back(collector::kGcTypeFull);
        ChangeAllocator(kUseRosAlloc ? kAllocatorTypeRosAlloc : kAllocatorTypeDlMalloc);
        break;
      }
      case kCollectorTypeCMS: {
    
    
        gc_plan_.push_back(collector::kGcTypeSticky);
        gc_plan_.push_back(collector::kGcTypePartial);
        gc_plan_.push_back(collector::kGcTypeFull);
        ChangeAllocator(kUseRosAlloc ? kAllocatorTypeRosAlloc : kAllocatorTypeDlMalloc);
        break;
      }
      default: {
    
    
        UNIMPLEMENTED(FATAL);
        UNREACHABLE();
      }
    }
    if (IsGcConcurrent()) {
    
    
      concurrent_start_bytes_ =
          std::max(max_allowed_footprint_, kMinConcurrentRemainingBytes) - kMinConcurrentRemainingBytes;
    } else {
    
    
      concurrent_start_bytes_ = std::numeric_limits<size_t>::max();
    }
  }
}

// Change the allocator, updates entrypoints.
void Heap::ChangeAllocator(AllocatorType allocator) {
    
    
  if (current_allocator_ != allocator) {
    
    
    current_allocator_ = allocator;
    MutexLock mu(nullptr, *Locks::runtime_shutdown_lock_);
    SetQuickAllocEntryPointsAllocator(current_allocator_);
    Runtime::Current()->GetInstrumentation()->ResetQuickAllocEntryPoints();
  }
}

猜你喜欢

转载自blog.csdn.net/u014099894/article/details/129964106