Android ART虚拟机 关键类

前言

本文介绍ART虚拟机中的关键类,方便之后对下一篇ART的Heap构造函数更好的理解。此处几个类和dalvik一脉相承,也可以更好的理解dalvik里面的GC模块。

HeapBitmap

这块和dalvik类似,是用一块位图来表示内存对象的引用。

  • 如果创建1万个对象的话,那么这一万个对象的指针本身所占据的内存空间就很可观了。指针本身的长度根据CPU架构的不同导致是32位长或者是64位长。

  • 如何减少指针本身所占据的内存空间呢?ART采用的办法很简单,就是将对象的指针转换成一个位图里的索引,位图里的每一位指向一个唯一的指针。
    image.png

  • HeapBitmap:它其实是一个辅助类,它内部包含continuous_space_bitmaps_和large_object_bitmaps_两个成员。这两个成员都是vector数组,所存储的元素类型分别是ContinuousSpaceBitmap和LargeObjectBitmap。

art/runtime/gc/accounting/heap_bitmap.h

class HeapBitmap {
    
    
 public:
  void Clear(const mirror::Object* obj) REQUIRES(Locks::heap_bitmap_lock_);

  template<typename LargeObjectSetVisitor>
  bool Set(const mirror::Object* obj, const LargeObjectSetVisitor& visitor)
      SHARED_REQUIRES(Locks::mutator_lock_)
      REQUIRES(Locks::heap_bitmap_lock_) ALWAYS_INLINE;

  template<typename LargeObjectSetVisitor>
  bool AtomicTestAndSet(const mirror::Object* obj, const LargeObjectSetVisitor& visitor)
      SHARED_REQUIRES(Locks::mutator_lock_)
      REQUIRES(Locks::heap_bitmap_lock_) ALWAYS_INLINE;
  ContinuousSpaceBitmap* GetContinuousSpaceBitmap(const mirror::Object* obj) const;
  LargeObjectBitmap* GetLargeObjectBitmap(const mirror::Object* obj) const;

  void Walk(ObjectCallback* callback, void* arg)
      SHARED_REQUIRES(Locks::heap_bitmap_lock_);

  template <typename Visitor>
  void Visit(const Visitor& visitor)
      REQUIRES(Locks::heap_bitmap_lock_)
      SHARED_REQUIRES(Locks::mutator_lock_);

  // Find and replace a bitmap pointer, this is used by for the bitmap swapping in the GC.
  void ReplaceBitmap(ContinuousSpaceBitmap* old_bitmap, ContinuousSpaceBitmap* new_bitmap)
      REQUIRES(Locks::heap_bitmap_lock_);

  // Find and replace a object set pointer, this is used by for the bitmap swapping in the GC.
  void ReplaceLargeObjectBitmap(LargeObjectBitmap* old_bitmap, LargeObjectBitmap* new_bitmap)
      REQUIRES(Locks::heap_bitmap_lock_);

  explicit HeapBitmap(Heap* heap) : heap_(heap) {
    
    }

 private:
  const Heap* const heap_;

  void AddContinuousSpaceBitmap(ContinuousSpaceBitmap* bitmap);
  void RemoveContinuousSpaceBitmap(ContinuousSpaceBitmap* bitmap);
  void AddLargeObjectBitmap(LargeObjectBitmap* bitmap);
  void RemoveLargeObjectBitmap(LargeObjectBitmap* bitmap);

  // Bitmaps covering continuous spaces.
  std::vector<ContinuousSpaceBitmap*,
              TrackingAllocator<ContinuousSpaceBitmap*, kAllocatorTagHeapBitmap>>
      continuous_space_bitmaps_;

  // Sets covering discontinuous spaces.
  std::vector<LargeObjectBitmap*,
              TrackingAllocator<LargeObjectBitmap*, kAllocatorTagHeapBitmapLOS>>
      large_object_bitmaps_;

  friend class art::gc::Heap;
  friend class art::gc::collector::ConcurrentCopying;
};

SpaceBitmap

  • SpaceBitmap是一个模板类,模板参数表示内存地址对齐长度。
    取值为kObjectAlignment(值为8)表示按对象对齐,其对应的类型别名就是ContinuousSpaceBitmap。
    取值为kLargeObjectAlignment(值为4KB,一个内存页的大小)表示按页对齐,对应的类型别名为LargeObjectBitmap。
  • SpaceBitmap类才是真正承载位图的地方。 比如,它的heap_begin_成员代表所针对内存的基地址,位图本身的内存基地址由heap_begin_表示,位图的长度(包含多少位)则由bitmap_size_表示。

art/runtime/gc/accounting/space_bitmap.h

typedef SpaceBitmap<kObjectAlignment> ContinuousSpaceBitmap;
typedef SpaceBitmap<kLargeObjectAlignment> LargeObjectBitmap;

template<size_t kAlignment>
class SpaceBitmap {
    
    
 public:
  typedef void ScanCallback(mirror::Object* obj, void* finger, void* arg);
  typedef void SweepCallback(size_t ptr_count, mirror::Object** ptrs, void* arg);

  // Initialize a space bitmap so that it points to a bitmap large enough to cover a heap at
  // heap_begin of heap_capacity bytes, where objects are guaranteed to be kAlignment-aligned.
  static SpaceBitmap* Create(const std::string& name, uint8_t* heap_begin, size_t heap_capacity);

  // Initialize a space bitmap using the provided mem_map as the live bits. Takes ownership of the
  // mem map. The address range covered starts at heap_begin and is of size equal to heap_capacity.
  // Objects are kAlignement-aligned.
  static SpaceBitmap* CreateFromMemMap(const std::string& name, MemMap* mem_map,
                                       uint8_t* heap_begin, size_t heap_capacity);

  ~SpaceBitmap();

 private:
  SpaceBitmap(const std::string& name, MemMap* mem_map, uintptr_t* bitmap_begin, size_t bitmap_size, const void* heap_begin);

  // Backing storage for bitmap.
  std::unique_ptr<MemMap> mem_map_;

  // This bitmap itself, word sized for efficiency in scanning.
  uintptr_t* const bitmap_begin_;

  // Size of this bitmap.
  size_t bitmap_size_;

  // The base address of the heap, which corresponds to the word containing the first bit in the bitmap.
  const uintptr_t heap_begin_;

  // Name of this bitmap.
  std::string name_;
}

SpaceBitmap构造函数

art/runtime/gc/accounting/space_bitmap.cc

template<size_t kAlignment>
SpaceBitmap<kAlignment>::SpaceBitmap(const std::string& name, MemMap* mem_map, uintptr_t* bitmap_begin,
                                     size_t bitmap_size, const void* heap_begin)
    : mem_map_(mem_map), bitmap_begin_(bitmap_begin), bitmap_size_(bitmap_size),
      heap_begin_(reinterpret_cast<uintptr_t>(heap_begin)),
      name_(name) {
    
    
  CHECK(bitmap_begin_ != nullptr);
  CHECK_NE(bitmap_size, 0U);
}

template<size_t kAlignment>
SpaceBitmap<kAlignment>::~SpaceBitmap() {
    
    }

template<size_t kAlignment>
SpaceBitmap<kAlignment>* SpaceBitmap<kAlignment>::Create(
    const std::string& name, uint8_t* heap_begin, size_t heap_capacity) {
    
    
  // Round up since heap_capacity is not necessarily a multiple of kAlignment * kBitsPerWord.
  const size_t bitmap_size = ComputeBitmapSize(heap_capacity);
  std::string error_msg;
  std::unique_ptr<MemMap> mem_map(MemMap::MapAnonymous(name.c_str(), nullptr, bitmap_size, PROT_READ | PROT_WRITE, false, false, &error_msg));

  return CreateFromMemMap(name, mem_map.release(), heap_begin, heap_capacity);
}

template<size_t kAlignment>
SpaceBitmap<kAlignment>* SpaceBitmap<kAlignment>::CreateFromMemMap(
    const std::string& name, MemMap* mem_map, uint8_t* heap_begin, size_t heap_capacity) {
    
    
  CHECK(mem_map != nullptr);
  uintptr_t* bitmap_begin = reinterpret_cast<uintptr_t*>(mem_map->Begin());
  const size_t bitmap_size = ComputeBitmapSize(heap_capacity);
  return new SpaceBitmap(name, mem_map, bitmap_begin, bitmap_size, heap_begin);
}

CardTable、RememberedSet、ModUnionTable

分代GC下,避免在回收新时代对象时将老年代对象也一并回收了,虚拟机需要主动记录哪些老年代对象引用了新生代的对象。所以,分代GC不仅要扫描新生代对应的root,还需要扫描这些纳入记录了的老年代对象。所以需要辅助的数据结构:

概念

  • RememberedSet:简单点说它就是一个容器类的数据结构。每一个引用了新生代对象的老年代对象都保存在RememberedSet中。其优点是精确,缺点是需要额外的内存空间来保存这些老年代对象。

  • CardTable:ART虚拟机中,CardTable可看作是一个元素大小为1字节的数组,该数组的每一个元素叫作一个Card(大小为1字节,不同虚拟机有不同的取值)。
    然后对AllocatedSpace按128字节(不同虚拟机有不同的取值)大小进行划分。每一个Card对应为Space中的一个128字节区域。
    所以,凡是内存地址位于某一个128字节区域的Object对象都对应同一个Card。
    在这个128字节区域内的Object对象中,只要有一个引用了新生代的对象,则该区域对应的Card元素将被标记为脏Card(Dirty Card)。

  • 简单来说,RememberedSet是以单个Object为管理对象,而CardTable是以128字节空间为管理对象。这128字节的空间中可能存在多个Object。

  • The mod-union table is the union of modified cards. It is used to allow the card table to be cleared between GC phases, reducing the number of dirty cards that need to be scanned.

  • ModUnionTable是Union of Modified Cards的意思,用于减少GC的工作量。

  • ModUnionTable只和ImageSpace、ZygoteSpace相关联。而RememberedSet只和MallocSpace(DlMallocSpace或RosAllocSpace)关联。

  • 在ART虚拟机中,RememberedSet和ModUnionTable都和GC密切相关。本质上来说,它们内部操作的都是CardTable。

关系

下图展示了ART虚拟机中CardTable、Space、RememberedSet和ModUnionTable之间的关系。
image.png

  • CardTable,它是一个数组,元素大小为1字节。该数组构造在一个内存映射对象上,起始位置为4KB,结尾为4GB。注意,CardTable前面一段灰色区域用于对齐。Heap利用这一个CardTable对象维护了Heap中其他空间所需的card信息。
  • 上方为一个ContinuousSpace对象(严格来说是一个MallocSpace对象)。它们按kCardSize(128字节)进行划分。每一个kCardSize单元可映射到CardTable中的一个Card。
  • 一个RememberedSet会关联一个ContinuousSpace,它用于记录该ContinuousSpace空间中的Object是否引用了其他Space空间中的Object等信息。
    也就是说,我们要想了解或操作某个ContinuousSpace和其他Space空间中Object引用关系的话,只要通过这个ContinuousSpace所关联的RememberedSet即可,而无须操作整个CardTable。
    另外,代码中只有DlMallocSpace或RosAllocSpace会关联RememberedSet。Bump-PointerSpace和RegionSpace均没有使用它。
  • 下方为一个ImageSpace或ZygoteSpace对象,它会关联一个ModUnionTable对象。在代码中,只有ImageSpace或ZygoteSpace这两种类型的Space对象会使用ModUnion-Table。

猜你喜欢

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