从前面ART运行时Java堆创建过程分析一文可以知道,在没有Compacting GC之前,Mark-Sweep GC的堆由Image Space、Zygote Space、Allocation Space和Large Object Space四种Space组成。其中,Allocation Space是从Zygote Space中分离出来的,它们都是一种DlMallocSpace。引入Compacting GC之后,Image Space和Large Object Space没有发生根本性的变化,但是Zygote Space和Allocation Space就发生了很大的变化。因此,接下来我们就结合Compacting GC以及其它的一些新特性来分析Zygote Space和Allocation Space都发生了哪些变化。
从前面ART运行时Compacting GC简要介绍和学习计划一文可以知道,用来分配对象的空间可以是一种DlMallocSpace,也可以是一种RosAllocSpace,因此,堆空间发生的第一个变化是用来分配对象的空间有可能是一个DlMallocSpace,也有可能是一个RosAllocSpace。
从前面ART运行时Compacting GC简要介绍和学习计划一文还可以知道,Semi-Space GC需要两个Bump Pointer Space,Generational Semi-Space GC需要两个Bump Pointer Space和一个Promote Space,Mark-Compact GC需要一个Bump Pointer Space。因此,我们需要增加一种类型为Bump Pointer的Space,以及一个Promote Space。
此外,我们还需要一个Non-Moving Space。由于在Compacting GC中,涉及到对象的移动,但是有些对象,例如类对象(Class)、类方法对象(ArtMethod)和类成员变量对象(ArtField),它们一经加载后,基本上就会一直存在。因此,频繁对此类对象进行移动是无益的,我们需要将它们分配在一个不能移动的Space中,以减少在Compacting GC需要处理的对象的数量。
所谓的同构空间压缩特性(Homogeneous Space Compact),是针对Mark-Sweep GC而言的。一个Space需要有Main和Backup之分。执行同构空间压缩时,将Main Space的对象移动至Backup Space中去,再将Main Space和Backup Space进行交换,这样就达到压缩空间,即减少内存碎片的作用。
综合前面的分析,我们就列出ART运行时支持的各种GC的堆空间结构,如下三个图所示:
图1 Mark-Sweep GC的堆空间结构
图2 Semi-Space GC和Mark-Compact GC的堆空间结构
图3 Generational Semi-Space GC的堆空间结构
接下来,我们将结构源代码来详细分析上述三个图各个Space的创建过程,这样就可以更好理解这三个图所表达的意思。
从前面ART运行时Java堆创建过程分析一文可以知道,堆的创建是从在ART运行时内部创建一个Heap对象开始的,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) { ...... heap_ = new gc::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中。
创建堆所需要的一般性参数的含义可以参考前面ART运行时Java堆创建过程分析一文,这里我们只解释几个与Compacting GC相关的参数:
options->heap_non_moving_space_capacity_:Non-Moving Space的大小,可以通过ART运行时启动选项-XX:NonMovingSpaceCapacity来指定,默认大小为kDefaultNonMovingSpaceCapacity(64MB)。
options->collector_type_:Foreground GC的类型,可以通过ART运行时启动选项-Xgc指定。如果没有指定,在编译ART运行时时,可以通过ART_DEFAULT_GC_TYPE_IS_CMS、ART_DEFAULT_GC_TYPE_IS_SS和ART_DEFAULT_GC_TYPE_IS_GSS这三个宏分别默认为Concurrent Mark-Sweep GC、Semi-Space GC或者Generational Semi-Space GC。
options->background_collector_type_:Background GC的类型,可以通过ART运行时启动选项-XX:BackgroundGC指定。如果没有指定,在编译ART运行时时,可以通过ART_USE_HSPACE_COMPACT宏指定为Homogeneous-Space-Compact。如果没有指定ART_USE_HSPACE_COMPACT宏,默认就与Foreground GC一样。
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对象的创建和初始化过程如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 ata-line="crayon-5812c2433df75629467703-24">24 25 26 27 28 ܌它们都是一种DlMallocSpace。引入Compacting GC之后,Image Space和Large Object Space没有发生根本性的变化,但是Zygote Space和Allocation Space就发生了很大的变化。因此,接下来我们就结合Compacting GC以及其它的一些新特性来分析Zygote Space和Allocation Space都发生了哪些变化。
从前面ART运行时Compacting GC简要介绍和学习计划一文可以知道,用来分配对象的空间可以是一种DlMallocSpace,也可以是一种RosAllocSpace,因此,堆空间发生的第一个变化是用来分配对象的空间有可能是一个DlMallocSpace,也有可能是一个RosAllocSpace。 从前面ART运行时Compacting GC简要介绍和学习计划一文还可以知道,Semi-Space GC需要两个Bump Pointer Space,Generational Semi-Space GC需要两个Bump Pointer Space和一个Promote Space,Mark-Compact GC需要一个Bump Pointer Space。因此,我们需要增加一种类型为Bump Pointer的Space,以及一个Promote Space。 此外,我们还需要一个Non-Moving Space。由于在Compacting GC中,涉及到对象的移动,但是有些对象,例如类对象(Class)、类方法对象(ArtMethod)和类成员变量对象(ArtField),它们一经加载后,基本上就会一直存在。因此,频繁对此类对象进行移动是无益的,我们需要将它们分配在一个不能移动的Space中,以减少在Compacting GC需要处理的对象的数量。 所谓的同构空间压缩特性(Homogeneous Space Compact),是针对Mark-Sweep GC而言的。一个Space需要有Main和Backup之分。执行同构空间压缩时,将Main Space的对象移动至Backup Space中去,再将Main Space和Backup Space进行交换,这样就达到压缩空间,即减少内存碎片的作用。 综合前面的分析,我们就列出ART运行时支持的各种GC的堆空间结构,如下三个图所示: 图1 Mark-Sweep GC的堆空间结构 图2 Semi-Space GC和Mark-Compact GC的堆空间结构 图3 Generational Semi-Space GC的堆空间结构 接下来,我们将结构源代码来详细分析上述三个图各个Space的创建过程,这样就可以更好理解这三个图所表达的意思。 从前面ART运行时Java堆创建过程分析一文可以知道,堆的创建是从在ART运行时内部创建一个Heap对象开始的,如下所示:
这个函数定义在文件art/runtime/runtime.cc中。 创建堆所需要的一般性参数的含义可以参考前面ART运行时Java堆创建过程分析一文,这里我们只解释几个与Compacting GC相关的参数: options->heap_non_moving_space_capacity_:Non-Moving Space的大小,可以通过ART运行时启动选项-XX:NonMovingSpaceCapacity来指定,默认大小为kDefaultNonMovingSpaceCapacity(64MB)。 options->collector_type_:Foreground GC的类型,可以通过ART运行时启动选项-Xgc指定。如果没有指定,在编译ART运行时时,可以通过ART_DEFAULT_GC_TYPE_IS_CMS、ART_DEFAULT_GC_TYPE_IS_SS和ART_DEFAULT_GC_TYPE_IS_GSS这三个宏分别默认为Concurrent Mark-Sweep GC、Semi-Space GC或者Generational Semi-Space GC。 options->background_collector_type_:Background GC的类型,可以通过ART运行时启动选项-XX:BackgroundGC指定。如果没有指定,在编译ART运行时时,可以通过ART_USE_HSPACE_COMPACT宏指定为Homogeneous-Space-Compact。如果没有指定ART_USE_HSPACE_COMPACT宏,默认就与Foreground GC一样。 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对象的创建和初始化过程如下所示:
|