<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                [原文出處--------------ART運行時垃圾收集機制簡要介紹和學習計劃](http://blog.csdn.net/luoshengyang/article/details/42072975) 為了學習ART運行時的垃圾收集機制,我們先把Dalvik虛擬機的垃圾收集機制研究了一遍。這是因為兩者都使用到了Mark-Sweep算法,因此它們在概念上有很多一致的地方。然而在實現上,Dalvik虛擬機的垃圾收集機制要簡單一些。這樣我們就可以先從簡單的Dalvik虛擬機垃圾收集機制入手,然后再逐步深入地學習復雜的ART運行時垃圾收集機制。本文就對ART運行時垃圾收集機制進行簡要介紹和制定學習計劃。 與Dalvik虛擬機垃圾收集機制簡要介紹和學習計劃一文介紹的Dalvik虛擬機垃圾收集機制一樣,ART運行時垃圾收集機制也涉及到類似于Zygote堆、Active堆、Card Table、Heap Bitmap和Mark Stack等概念,如圖1所示: ![](https://box.kancloud.cn/004d9af976272de89c6c8af969094129_833x719.png) 圖1 ART運行時垃圾收集機制的基本概念 從圖1可以看到,ART運行時堆劃分為四個空間,分別是Image Space、Zygote Space、Allocation Space和Large Object Space。其中,Image Space、Zygote Space、Allocation Space是在地址上連續的空間,稱為Continuous Space,而Large Object Space是一些離散地址的集合,用來分配一些大對象,稱為Discontinuous Space。 在Image Space和Zygote Space之間,隔著一段用來映射system@framework@boot.art@classes.oat文件的內存。從前面[Android運行時ART加載OAT文件的過程分析](http://blog.csdn.net/luoshengyang/article/details/39307813)一文可以知道,system@framework@boot.art@classes.oat是一個OAT文件,它是由在系統啟動類路徑中的所有DEX文件翻譯得到的,而Image Space空間就包含了那些需要預加載的系統類對象。這意味著需要預加載的類對象是在生成system@framework@boot.art@classes.oat這個OAT文件的時候創建并且保存在文件system@framework@boot.art@classes.dex中,以后只要系統啟動類路徑中的DEX文件不發生變化(即不發生更新升級),那么以后每次系統啟動只需要將文件system@framework@boot.art@classes.dex直接映射到內存即可,省去了創建各個類對象的時間。之前使用Dalvik虛擬機作為應用程序運行時時,每次系統啟動時,都需要為那些預加載的類創建類對象。因此,雖然ART運行時第一次啟動時會比較慢,但是以后啟動實際上會更快。 由于system@framework@boot.art@classes.dex文件保存的是一些預先創建的對象,并且這些對象之間可能會互相引用,因此我們必須保證system@framework@boot.art@classes.dex文件每次加載到內存的地址都是固定的。這個固定的地址保存在system@framework@boot.art@classes.dex文件開頭的一個Image Header中。此外,system@framework@boot.art@classes.dex文件也依賴于system@framework@boot.art@classes.oat文件,因此也會將后者固定加載到Image Space的末尾。 Zygote Space和Allocation Space與Dalvik虛擬機垃圾收集機制中的Zygote堆和Active堆的作用是一樣的。Zygote Space在Zygote進程和應用程序進程之間共享的,而Allocation Space則是每個進程獨占的。同樣的,Zygote進程一開始只有一個Image Space和一個Zygote Space。在Zygote進程fork第一個子進程之前,就會把Zygote Space一分為二,原來的已經被使用的那部分堆還叫Zygote Space,而未使用的那部分堆就叫Allocation Space。以后的對象都在Allocation Space上分配。 通過上述這種方式,就可以使得Image Space和Zygote Space在Zygote進程和應用程序進程之間進行共享,而Allocation Space就每個進程都獨立地擁有一份。注意,雖然Image Space和Zygote Space都是在Zygote進程和應用程序進程之間進行共享,但是前者的對象只創建一次,而后者的對象需要在系統每次啟動時根據運行情況都重新創建一遍。 為了驗證上面的分析,我們在某一次系統啟動時,查看Settings.apk進程的地址空間,如圖2所示: ![](https://box.kancloud.cn/86a433990d5960d8befa55dd3729668b_1090x286.png) 圖2 Settings.apk的地址空間 其中,地址空間0x60000000-0x60a94000對應的就是Image Space,它映射的是system@framework@boot.art@classes.dex文件,固定映射在地址0x60000000上。緊跟著的地址空間0x60a94000-0x64591000映射的是system@framework@boot.art@classes.oat文件。再接下來就是Zygote Space和Allocation Space,分別映射在地址空間0x64591000-0x646e7000和0x646e7000-0x6754e000上。并且都是匿名共享內存塊。另外,通過翻譯Settings.apk里面的classes.dex文件得到的OAT文件system@priv-app@Settings.apk@classes.dex映射在地址空間0xaf29b000-0xaf654000上。 與Dalivk虛擬機類似,ART運行時也使用一個Heap對象來描述堆,它的實現如圖3所示: ![](ART運行時堆描述類Heap的實現) 圖3 ART運行時堆描述類Heap的實現 Heap類包含了以下重要成員變量描述ART運行時的堆,它們的作用如下所述: 1. mark_sweep_collectors_: 一個std::vector<collector::MarkSweep*>向量,保存了六種Mark-Sweep垃圾收集器。 2. continuous_spaces_: 一個std::vector<space::ContinuousSpace*>向量,保存了圖1所示的三個在地址空間上連續的Image Space、Zygote Space和Allocation Space。 3. concurrent_gc_: 一個bool變量,描述是否支持并行GC,可以通過ART運行時啟動選項-Xgc來指定。 4. parallel_gc_threads_: 一個size_t變量,指定在GC暫停階段用來同時執行GC任務的線程數,可以通過ART運行時啟動選項-XX:ParallelGCThreads指定。如果沒有指定,它的值就等于CPU核心數減1。這里之所以要減1是因為parallel_gc_threads_描述的實際上是除了當前GC線程之外的其它也用于GC任務的線程的個數。 5. conc_gc_threads_: 一個size_t變量,指定非GC暫停階段用來同時執行GC任務的線程數,可以通過ART運行時啟動選項-XX:ConcGCThreads來指定。 6. discontinuous_spaces_: 一個std::vector<space::DiscontinuousSpace*>向量,保存了圖1所示的在地址空間上不連續的Large Object Space。 7. alloc_space_: 一個space::DlMallocSpace指針,指向一個space::DlMallocSpace對象,該對象描述的是圖1所示的Allocation Space。 8. large_object_space_: 一個space::LargeObjectSpace指針,指向一個space::LargeObjectSpace對象,該對象描述的是圖1所示的Large Object Space。 9. card_table_: 一個UniquePtr<accounting::CardTable>指針,指向一個accounting::CardTable對象,該對象描述的是圖1所示的Card Table。 10. image_mod_union_table_: 一個UniquePtr<accounting::ModUnionTable>指針,指向一個accounting::ModUnionTable對象,該對象描述的是圖1所示的位于上方的Mod Union Table對象,用來記錄在GC并行階段在Image Space上分配的對象對在Zygote Space和Allocation Space上分配的對象的引用。 11. zygote_mod_union_table_: 一個UniquePtr<accounting::ModUnionTable>指針,指向一個accounting::ModUnionTable對象,該對象描述的是圖1所示的位于下方的Mod Union Table,用來記錄在GC并行階段在Zygote Space上分配的對象對在Allocation Space上分配的對象的引用。 12. mark_stack_: 一個UniquePtr<accounting::ObjectStack>指針,指向一個accounting::ObjectStack對象,該對象描述的是圖1所示的Mark Stack,用來在GC過程中實現遞歸對象標記。 13. allocation_stack_: 一個UniquePtr<accounting::ObjectStack>指針,指向一個accounting::ObjectStack對象,該對象描述的是圖1所示的Allocation Stack,用來記錄上一次GC后分配的對象,用來實現類型為Sticky的Mark Sweep Collector。 14. live_stack_: 一個UniquePtr<accounting::ObjectStack>指針,指向一個accounting::ObjectStack對象,該對象描述的是圖1所示的Live Stack,配合allocation_stack_一起使用,用來實現類型為Sticky的Mark Sweep Collector。 15. mark_bitmap_: 一個UniquePtr<accounting::HeapBitmap>指針,指向一個accounting::HeapBitmap對象,該對象描述的是圖1所示的Mark Bitmap,與Dalvik虛擬機的Mark Bitmap作用是一樣的,用來標記當前GC之后還存活的對象。 16. live_bitmap_: 一個UniquePtr<accounting::HeapBitmap>指針,指向一個accounting::HeapBitmap對象,該對象描述的是圖1所示的Live Bitmap,與Dalvik虛擬機的Live Bitmap作用是一樣的,用來標記上一次GC之后還存活的對象。 除了上述的16個成員變量,Heap類還定義了以下三個垃圾收集接口: 1. CollectGarbage: 用來執行顯式GC,例如用實現System.gc接口。 2. ConcurrentGC: 用來執行并行GC,只能被ART運行時內部的GC守護線程調用。 3. CollectGarbageInternal: ART運行時內部調用的GC接口,可以執行各種類型的GC。 上面我們提到,Heap類的成員變量mark_sweep_collectors_保存了ART運行時內部使用的六種垃圾收集器,這六種垃圾收集器分為兩組。其中一組是支持并行GC的,另一組是不支持并行GC的。每一組都由MarkSweep、PartialMarkSweep和StickyMarkSweep三種類型的垃圾收集器組成。它們的類關系如圖4所示: ![](https://box.kancloud.cn/e318278031fb69375e1dd6d486442f5b_729x680.jpg) 圖4 ART運行時的垃圾收集器 StickyMarkSweep繼承于PartialMarkSweep,PartialMarkSweep又繼承于MarkSweep、而MarkSweep又繼承于GarbageCollector。因此,我們可以推斷出,GarbageCollector定義了垃圾收集器接口,而MarkSweep、PartialMarkSweep和StickyMarkSweep通過重定某些接口來實現不同類型的垃圾收集器。 在GarbageCollector中,有一個成員變量heap_,指向的是ART運行時堆,同時定義了兩個public成員函數IsConcurrent和GetGcType。前者用來獲得一個垃圾收集器是否支持并行GC,后者用來獲得垃圾收集器類型 。 垃圾收集器類型通過枚舉類型GcType來描述,它的定義如下所示: ~~~ // The type of collection to be performed. The ordering of the enum matters, it is used to // determine which GCs are run first. enum GcType { // Placeholder for when no GC has been performed. kGcTypeNone, // Sticky mark bits GC that attempts to only free objects allocated since the last GC. kGcTypeSticky, // Partial GC that marks the application heap but not the Zygote. kGcTypePartial, // Full GC that marks and frees in both the application and Zygote heap. kGcTypeFull, // Number of different GC types. kGcTypeMax, }; ~~~ 這個枚舉類型定義在文件t/runtime/gc/collector/gc_type.h中。 其中,kGcTypeNone是一個占位符,kGcTypeMax描述的是垃圾收集器類型個數。kGcTypeSticky指的就是StickyMarkSweep類型的垃圾收集器,用來收集上次GC以來分配的對象。kGcTypePartial指的就是PartialMarkSweep類型的垃圾收集器,用來收集在Allocation Space上分配的對象。kGcTypeFull指的就是MarkSweep類型的垃圾收集器,用來收集在Zygote Space和Allocation Space上分配的對象。 此外,GarbageCollector通過定義以下五個虛函數描述GC的各個階段: 1. InitializePhase: 用來實現GC的初始化階段,用來初始化垃圾收集器內部的狀態。 2. MarkingPhase: 用來實現GC的標記階段,該階段有可能是并行的,也有可能不是并行。 3. HandleDirtyObjectsPhase: 用來實現并行GC的Dirty Object標記,也就是遞歸標記那些在并行標記對象階段中被修改的對象。 4. ReclaimPhase: 用來實現GC的回收階段。 5. FinishPhase: 用來實現GC的結束階段。 MarkSweep類通過重寫上述五個虛函數實現自己的垃圾收集過程,同時,它又通過定義以下三個虛函數來讓子類PartialMarkSweep和StickyMarkSweep實現特定的垃圾收集器: 1. MarkReachableObjects: 用來遞歸標記從根集對象引用的其它對象。 2. BindBitmap: 用來指定垃圾收集范圍。 3. Sweep: 用來回收垃圾對象。 其中,MarkSweep類通過自己實現的成員函數BindBitmap將垃圾收集范圍指定為Zygote和Allocation空間,而PartialMarkSweep和StickyMarkSweep類通過重寫成員函數BindBitmap將垃圾收集范圍指定為Allocation空間和上次GC后所分配的對象。此外,StickyMarkSweep類還通過重定成員函數MarkReachableObjects和Sweep將對象標記和回收限制為上次GC后所分配的對象。 上面我們也提到了ART運行時將堆劃分為連續空間和不連續空間兩種類型,每一種類型又分別有不同的實現。這些實現的類關系如圖5所示: ![](https://box.kancloud.cn/528eabce7f3d9c48ffa3ae7010fd560a_1324x1114.jpg) 圖5. ART運行時各種堆空間的關系圖 首先看最下面的三個類ImageSpace、DlMallocSpace和LargeObjectMapSpace。其中,ImageSpace描述的是Image Space,DlMallocSpace描述的是Zygote Space和Allocation Space,LargeObjectMapSpace描述的是Large Object Space。它們都有一個共同的基類Space。 Space類有一個類型為GcRetentionPolicy的成員變量gc_retention_policy_,用來描述一個Space的回收策略。GcRetentionPolicy是一個枚舉類型,它的定義如下所示: ~~~ // See Space::GetGcRetentionPolicy. enum GcRetentionPolicy { // Objects are retained forever with this policy for a space. kGcRetentionPolicyNeverCollect, // Every GC cycle will attempt to collect objects in this space. kGcRetentionPolicyAlwaysCollect, // Objects will be considered for collection only in "full" GC cycles, ie faster partial // collections won't scan these areas such as the Zygote. kGcRetentionPolicyFullCollect, }; ~~~ 這個枚舉類型定義在文件art/runtime/gc/space/space.h中。 kGcRetentionPolicyNeverCollect表示永遠不會進行垃圾回收的Space,例如Image Space。kGcRetentionPolicyAlwaysCollect表示每一次GC都會嘗試回收垃圾的Space,例如Allocation Space。kGcRetentionPolicyFullCollect表示只有執行類型為kGcTypeFull的GC才會進行垃圾回收的Space,例如Zygote Space。通過Space類的成員函數GetGcRetentionPolicy可以獲得一個Space的回收策略。 一個Space除了具有回收策略之外,還具有Space Type,通過枚舉類型SpaceType來描述。枚舉類型SpaceType的定義如下所示: ~~~ enum SpaceType { kSpaceTypeImageSpace, kSpaceTypeAllocSpace, kSpaceTypeZygoteSpace, kSpaceTypeLargeObjectSpace, }; ~~~ 這個枚舉類型定義在文件art/runtime/gc/space/space.h中。 kSpaceTypeImageSpace、kSpaceTypeAllocSpace、kSpaceTypeZygoteSpace和kSpaceTypeLargeObjectSpace描述的就分別是Image Space、Allocation Space、Zygote Space和Large Object Space。通過Space類的成員函數GetType可以獲得一個Space的Type。此外,Space類還提供了IsImageSpace、IsDlMallocSpace、IsZygoteSpace和IsLargeObjectSpace四個輔助成員函數來方便判斷一個Space的類型。 前面我們提到,Space劃分Continuous和Discontinuous兩種,其實還可以劃分為Allocable和Non-Allocable兩種。例如,Image Space是不能分配新對象的,而Zygote Space、Allocation Space和Large Object Space是可以分配對象。對于可分配新對象的Space,ART運行時定義了一個基類AllocSpace,它的定義以下幾個重要的接口來描述一個可分配新對象的Space,如下所示: 1. GetBytesAllocated: 獲得當前已經分配的字節數。 2. GetObjectsAllocated: 獲得當前已經分配的對象數。 3. GetTotalBytesAllocated: 獲得Space自創建以來所分配的字節數。 4. GetTotalObjectsAllocated: 獲得Space自創建以來所分配的對象數。 5. Alloc: 在Space上分配一個指定大小的對象。 6. AllocationSize: 獲得一個對象占據的內存塊大小。 7. Free: 釋放一個對象占據的內存塊。 8. FreeList: 批量釋放一系列對象占據的內存塊。 Continuous Space和Discontinuous Space分別使用類ContinuousSpace和DiscontinuousSpace來描述,它們都是從類Space繼承下來的。 ContinuousSpace類有兩個成員變量begin_和end_,用來描述一個Continuous Space內部所使用的內存塊的開始和結束地址。此外,ContinuousSpace類還定義了以下幾個重要接口來獲得一個Continuous Space的相關信息,如下所示: 1. Begin: 獲得Space的起始地址。 2. End: 獲得Space的結束地址。 3. Size: 獲得Space的大小。 4. GetLiveBitmap: 獲得Space的Live Bitmap。 5. GetMarkBitmap: 獲得Space的Mark Bitmap。 由于Discontinuous Space在地址空間上是不連續的,因此它不像Continuous Space一樣,可以使用類似begin_和end_的成員變量來確定Space內部使用的內存塊。DiscontinuousSpace類在內部使用兩個SpaceSetMap容器live_objects_和mark_objects_來描述已經分配對象集合和在GC過程中被標記的對象集合。此外,DiscontinuousSpace類還定義了以下兩個接口來獲得這兩個對象集合,如下所示: 1. GetLiveObjects: 獲得當前分配的對象集合。 2. GetMarkObjects: 獲得在當前GC過程被標記的對象集合。 Continuous Space內部使用的內存塊都是通過內存映射得到的,不過這塊內存有可能是通過不同方式映射得到的。例如,Image Space內部使用的內存塊是通過內存映射Image文件得到的,而Zygote Space和Allocation Space內部使用的內存塊是通過內存映射匿名共享內存得到。通過內存映射得到的Space使用類MemMapSpace來描述,它繼承于ContinousSpace。MemMapSpace類有一個成員變量mem_map_,類型是UniquePtr<MemMap>,指向一塊由一個MemMap對象描述的內存塊,可以通過成員函數Capacity來獲得該內存塊的大小。 從圖5可以看到,Image Space是通過ImageSpace類來描述,它繼承于MemMapSpace類。前面我們提到,Image Space是從一個Image文件獲得的,就是圖1所示的boot.art@classes.dex文件,從[Android運行時ART加載OAT文件的過程分析](http://blog.csdn.net/luoshengyang/article/details/39307813)一文又可以知道,Image文件關聯有一個OAT文件,就是圖1所示的boot.art@classes.oat文件。因此,在ImageSpace類內部,有一個成員變量oat_file_,用來描述與Image Space關聯的OAT文件。此外。在ImageSpace類內部,還有一個類型為UniquePtr<accounting::SpaceBitmap>的成員變量live_bitmap_,用來標記Imape Space的存活對象。由于Image Space是不會進行新對象分配和垃圾回收的,因此它不像其它Space一樣,還有另外一個Mark Bitmap。不過Space要求其子類要有一個Live Bitmap和一個Mark Bitmap,于是,ImageSpace就將內部的live_bitmap_同時作為Live Bitmap和Mark Bitmap來使用。 ImageSpace還通過定義以下幾個接口來獲得Image Space的相關信息,如下所示: 1. GetType: 重寫了父類Space的成員函數GetType,返回固定為kSpaceTypeImageSpace,表示這是一個Image Space。 2. GetLiveBitmap: 獲得Image Space的Live Bitmap。 3. GetMarkBitmap: 獲得Image Space的Mark Bitmap。 4. Create: 一個靜態成員函數,根據指定的Image文件創建一個Image Space。 Zygote Space和Allocation Space都是通過類DlMallocSpace來描述。雖然Zygote Space和Allocation Space內部使用的內存塊都是通過內存映射得到的,不過在使用它們的時候,是通過C庫提供的內存管理接口來使用的,因此這里就將它們的名字命名為DlMalloc,這也是DlMallocSpace的由來。由于DlMallocSpace還是可以分配新對象的,因此在圖5中,我們看到它除了繼承于MemMapSpace類之外,還繼承于AllocSpace。 DlMallocSpace定義了以下幾個重要成員變量來描述內部狀態,如下所示: 1. mspace_: 和Dalvik虛擬機一樣,ART運行時也是將Zygote Space和Allocation Space使用的匿名共享內存塊封裝成一個mspace對象,以便可以使用C庫提供的內存管理接口來在上面分配和釋放內存。 2. live_bitmap_: 指向一個SpaceBitmap,用來記錄上次GC后存活對象。 3. mark_bitmap_: 指向一個SpaceBitmap,用來記錄當前GC被標記的對象。 4. num_bytes_allocated_: 記錄當前已經分配的內存字節數。 5. num_objects_allocated_: 記錄當前已經分配的對象數。 6. total_bytes_allocated_: 記錄從Space創建以來所分配的內存字節數。 7. total_objects_allocated_: 記錄從Space創建以來所分配的對象數。 DlMallocSpace還新定義或者重寫了父類的成員函數,如下所示: 1. GetType: 重寫了父類Space的成員函數GetType,返回固定為SpaceTypeZygoteSpace或者kSpaceTypeAllocSpace,表示這是一個Zygote Space或者Allocation Space。 2. Create: 一個靜態成員函數,用來創建一個Zygote Space或者Allocation Space。 3. GetBytesAllocated: 重寫了父類AllocSpace的成員函數GetBytesAllocated。 4. GetObjectsAllocated: 重寫了父類AllocSpace的成員函數GetObjectsAllocated。 5. GetTotalBytesAllocated: 重寫了父類AllocSpace的成員函數GetTotalBytesAllocated。 6. GetTotalObjectsAllocated: 重寫了父類AllocSpace的成員函數GetTotalObjectsAllocated。 7. Alloc: 重寫了父類AllocSpace的成員函數Alloc。 8. AllocationSize: 重寫了父類AllocSpace的成員函數AllocationSize。 9. Free: 重寫了父類AllocSpace的成員函數Free。 10. FreeList: 重寫了父類AllocSpace的成員函數FreeList。 11. Capacity: 重寫了父類MemMapSpace的成員函數Capacity。 現在再來看最后一種Space -- Large Object Space。ART運行時提供了兩種Large Object Space實現。其中一種實現和Continuous Space的實現類似,預先分配好一塊大的內存空間,然后再在上面為對象分配內存塊。不過這種方式實現的Large Object Space不像Continuous Space通過C庫的內塊管理接口來分配和釋放內存,而是自己維護一個Free List。每次為對象分配內存時,都是從這個Free List找到合適的空閑的內存塊來分配。釋放內存的時候,也是將要釋放的內存添加到該Free List去。 另外一種Large Object Space實現是每次為對象分配內存時,都單獨為其映射一新的內存。也就是說,為每一個對象分配的內存塊都是相互獨立的。這種實現方式相比上面介紹的Free List實現方式,也更簡單一些。在Android 4.4中,ART運行時使用的是后一種實現方式,因此我們這里也主要是介紹這種實現。 為每一對象映射一塊獨立的內存塊的Large Object Space實現稱為LargeObjectMapSpace,它與Free List方式的實現都是繼承于類LargeObjectSpace。LargeObjectSpace又分別繼承了DiscontinuousSpace和AllocSpace。因此,我們就可以知道,LargeObjectMapSpace描述的是一個在地址空間上不連續的Large Object Space。 LargeObjectSpace定義了以下重要成員變量描述內部狀態,如下所示: 1. num_bytes_allocated_: 記錄當前已經分配的內存字節數。 2. num_objects_allocated_: 記錄當前已經分配的對象數。 3. total_bytes_allocated_: 記錄從Space創建以來所分配的內存字節數。 4. total_objects_allocated_: 記錄從Space創建以來所分配的對象數。 LargeObjectSpace還重寫了父類AllocSpace的以下成員函數: 1. GetType: 重寫了父類Space的成員函數GetType,返回固定為kSpaceTypeLargeObjectSpace,表示這是一個Large Object Space。 2. GetBytesAllocated: 重寫了父類AllocSpace的成員函數GetBytesAllocated。 3. GetObjectsAllocated: 重寫了父類AllocSpace的成員函數GetObjectsAllocated。 4. GetTotalBytesAllocated: 重寫了父類AllocSpace的成員函數GetTotalBytesAllocated。 5. GetTotalObjectsAllocated: 重寫了父類AllocSpace的成員函數GetTotalObjectsAllocated。 6. FreeList: 重寫了父類AllocSpace的成員函數FreeList。 LargeObjectMapSpace繼承于LargeObjectSpace,它內部有一個成員變量large_objects_,指向一個std::vector<mirror::Object*, accounting::GCAllocator<mirror::Object*> >向量,里面保存的就是為每一個對象獨立映射的內存塊。 此外,LargeObjectMapSpace還新定義或者重寫了父類AllocSpace的以下成員變量: 1. Create: 一個靜態成員函數,用來創建一個LargeObjectMapSpace。 2. Alloc: 重寫了父類AllocSpace的成員函數Alloc。 3. AllocationSize: 重寫了父類AllocSpace的成員函數AllocationSize。 4. Free: 重寫了父類AllocSpace的成員函數Free。 除了Garbage Collector和Space,ART運行時垃圾收集機制比Dalvik垃圾收集機制還多了一個稱Mod Union Table的概念。Mod Union Table是與Card Table配合使用的,用來記錄在一次GC過程中,記錄不會被回收的Space的對象對會被回收的Space的引用。例如,Image Space的對象對Zygote Space和Allocation Space的對象的引用,以及Zygote Space的對象對Allocation Space的對象的引用。 ART運行時定義了一個ModUnionTable基類以及一系列的子類,用來記錄不同Space的對象對特定Space的對象的引用,它們的關系如圖6所示: ![](https://box.kancloud.cn/7ec40250c0c49b44b76da56e1d685253_785x498.jpg) 圖6 ART運行時的Mod Union Table實現 ModUnionTable類有一個成員變量heap_,指向ART運行時堆,可以通過成員函數GetHeap來獲得。 在GC標記階段,Card Table和Mod Union Table分三步處理。第一步是調用ModUnionTable類的成員函數ClearCards清理Card Table里面的Dirty Card,并且將這些Dirty Card記錄在Mod Union Table中。第二步是調用ModUnionTable類的成員函數Update將遍歷記錄在Mod Union Table里面的Drity Card,并且找到對應的被修改對象,然后將被修改對象引用的其它對象記錄起來。第三步是調用ModUnionTable類的成員函數MarkReferences標記前面第二步那些被被修改對象引用的其它對象。通過這種方式,就可以使用Card Table可以在標記階段重復使用,即在執行第二步之前,重復執行第一步,最后通過Mod Union Table將所有被被修改對象引用的其它對象收集起來統一進行標記,避免對相同對象進行重復標記。 上面說到,Mod Union Table的作用就使得Card Table可以重復使用,前提是Mod Union Table將每一次清理Card Table之前,將之前已經是Dirty的Card緩存起來。因此,ModUnionTableCardCache類繼承ModUnionTable類的時候,定義了一個類型為CardSet的成員變量cleared_cards_,就是用來緩存Dirty Card的,并且它重寫了父類ModUnionTable的成員函數ClearCards、Update和MarkReferences來實現自己的DIrty Card緩存策略。 另外一個繼承于ModUnionTable的子類ModUnionTableReferenceCache,不單會將Dirty Card緩存起來保存在類型同樣為CardSet的成員變量cleared_cards_中,而且還將與這些Dirty Card對應的被引用對象也緩存起來保存在成員變量references_指向的一個SafeMap中。同樣的,ModUnionTableReferenceCache重寫了父類ModUnionTable的成員函數ClearCards、Update和MarkReferences來實現自己的Dirty Card緩存策略。此外,ModUnionTableReferenceCache還提供了一個AddReference接口,用來決定哪些被引用對象需要緩存。 ModUnionTableReferenceCache類并不是直接使用的,它也是作為基類使用。ART運行時提供了兩個子類ModUnionTableToZygoteAllocspace和ModUnionTableToAllocspce,它們都繼承于ModUnionTableReferenceCache類。從名字我們可以大致推斷出,ModUnionTableToZygoteAllocspace類是用來記錄位于Zygote Space和Allocation Space的被引用對象的,而ModUnionTableToAllocspace是用來記錄位于Allocation Space的被引用對象的,也就是對應于前面圖1所示的兩個Mod Union Table。不過ART運行時實際上是使用ModUnionTableCardCache來記錄位于Allocation Space的被引用對象的。在后面的文章中,我們就可以看到這一點。 至此,ART運行時垃圾收集機制涉及到的基礎概念我們就介紹完畢。要做到完全理解這些概念,除了要熟悉[Dalvik虛擬機垃圾收集機制簡要介紹和學習計劃](http://blog.csdn.net/luoshengyang/article/details/41338251)這一系列文章分析Dalvik虛擬機垃圾收集機制之外,還需要繼續從以下情景來進一步分析ART運行時垃圾機制: 1. [ART運行時堆的創建過程](http://blog.csdn.net/luoshengyang/article/details/42379729)。 2. [ART運行時的對象分配過程](http://blog.csdn.net/luoshengyang/article/details/42492621)。 3. [ART運行時的垃圾收集過程](http://blog.csdn.net/luoshengyang/article/details/42555483)。 按照這三個情景學習ART運行時的垃圾收集機制之后,我們就會對上面涉及的概念有一個清晰的認識了。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看