写点什么

JVM 源码分析之堆内存的初始化

用户头像
猿灯塔
关注
发布于: 2020 年 05 月 22 日
JVM源码分析之堆内存的初始化

原创申明:本文由公众号【猿灯塔】原创,转载请说明出处标注


今天呢!灯塔君跟大家讲:

JVM 源码分析之堆内存的初始化


Java 堆的初始化入口位于Universe::initialize_heap方法中,实现如下:



其中 UseParallelGC、UseG1GC、UseConcMarkSweepGC 都可以通过启动参数进行设置,整个初始化过程分成三步:

1、初始化 GC 策略;

2、初始化分代生成器;

3、初始化 Java 堆管理器;


GC 策略初始化

HotSpot 的 GC 策略实现如下:



其中MarkSweepPolicy是基于标记-清除思想的 GC 策略,如果虚拟机启动参数没有指定 GC 算法,则使用默认使用UseSerialGC,以ASConcurrentMarkSweepPolicy策略为例,对 GC 策略的初始化过程进行分析:



调用父类 ConcurrentMarkSweepPolicy 构造方法,其中 initialize_all 定义在 GenCollectorPolicy 中,实现如下:



initialize_flags

负责对新生代、老年代以及永久代设置的内存大小进行对齐调整。

1、调整永久代



CollectorPolicy::initialize_flags实现,永久代的初始值默认为 4M,最大值为 64M,可以通过参数-XX:PermSize-XX:MaxPermSize进行重新设置。


2、调整新生代

GenCollectorPolicy::initialize_flags实现:

1、新生代的初始值NewSize默认为 1M,最大值需要设置,可以通过参数-XX:NewSize-XX:MaxNewSize-Xmn进行设置;

2、NewRatio为老年代与新生代的大小比值,默认为 2;

3、SurvivorRatio为新生代中 Eden 和 Survivor 的大小比值,默认为 8;


initialize_size_info

设置新生代、老年代以及永久代的容量,包括初始值、最小值和最大值

设置堆容量



其中InitialHeapSizeArguments::min_heap_size()可以通过参数-Xms进行设置。

1、设置初始堆容量_initial_heap_byte_size

2、设置最小堆容量_min_heap_byte_size

3、设置最大堆容量_max_heap_byte_size


设置新生代



1、如果MaxNewSize重新设置过,即设置-Xmn参数,则根据不同情况设置max_new_size

2、否则通过scale_by_NewRatio_aligned方法根据NewRatio_max_heap_byte_size重新计算max_new_size值,其中NewRatio默认为 2,表示新生代的大小占整个堆的 1/3;



3、如果最大堆_max_heap_byte_size等于最小堆_min_heap_byte_size,则设置新生代的初始值、最小值和最大值为max_new_size,否则执行步骤 4;



4、如果NewSize重新设置过,即设置了-Xmn参数,则使用NewSize设置_min_gen0_size,否则使用scale_by_NewRatio_aligned方法重新计算新生代最小值和初始值,实现如下:



设置老年代

1、如果参数没有设置OldSize,则使用min_heap_byte_size() - min_gen0_size(),即最小堆大小和新生代最小值之差设置老年代最小值,初始值类似;

2、否则根据设置的OldSize,通过adjust_gen0_sizes方法重新设置新生代的最小值和初始值;


初始化分代生成器

分代生成器保存了各个内存代的初始值和最大值,新生代和老年代通过GenerationSpec实现,永久代通过PermanentGenerationSpec实现。


GenerationSpec 实现



每个生成器 GenerationSpec 实例保存当前分代的 GC 算法、内存的初始值和最大值。


PermanentGenerationSpec 实现



除了GenerationSpec实例中的数据,如果设置UseSharedSpacesDumpSharedSpaces,还需要保存额外的数据。

ConcurrentMarkSweepPolicy::initialize_generations

方法实现了分代生成器的初始化,实现如下:



创建新生代、老年代和永久代对应的生成器实例。


初始化 Java 堆管理器

GenCollectedHeap 是整个 Java 堆的管理器,负责 Java 对象的内存分配和垃圾对象的回收,通过 initialize 方法进行初始化,实现如下:



1、通过 GC 策略的number_of_generations方法获取分代数量,如果使用 ASConcurrentMarkSweepPolicy,默认分代数为 2;

2、通过align方法对齐生成器的初始值和最大值(为什么需要一直对齐,我觉得前面初始化 GC 策略的时候已经对齐很多次了)



3、通过 allocate 为堆申请空间;



4、通过分代生成器的init方法为对应的分代分配内存空间;



5、如果当前的 GC 策略为 ConcurrentMarkSweepPolicy,则通过create_cms_collector创建 GC 线程。

365 天干货不断微信搜索「猿灯塔」第一时间阅读,回复【资料】【面试】【简历】有我准备的一线大厂面试资料和简历模板


发布于: 2020 年 05 月 22 日阅读数: 65
用户头像

猿灯塔

关注

猿灯塔-做程序员的引导者! 2020.04.02 加入

我们立志作为IT行业知识大海的一座座灯塔,为想在这个行业中奋斗的你们指明正确的方向,引领大家一起前进。

评论

发布
暂无评论
JVM源码分析之堆内存的初始化