Java Heap
包含三个部分
YoungGen,OldGen,PermGen
三个部分,亦叫作年轻代,年老代,永久代。
DefNewGeneration
是
YoungGen
的一个实现,包含
_eden_space,
_from_space, _to_space
三个部分。在
YoungGen
中分配对象的时候会在
eden
中进行分配,
from
和
to
是在
ygc
的过程中用到的,将
eden
和
from
中存活的对象拷贝到
to
中,每一次ygc,from和to的角色会对调一下
ConcurrentMarkSweepGeneration
是
OldGen
的一个实现,这里存储的是经过
ygc
后,
age
较大的对象,或者是很大的对象
(
在
Young Gen
中分配不了的
)
,或者是
ygc
的时候
to
的区域受限存不了的对象也会晋升到
OldGen
中
PermGen
是存储
class
信息,常量池等等一些信息。
-
2.Java
Heap
在
Hotspot
中是如何创建、分配的
Java Heap
的创建经过下面几层路径,层层下去,最终完成创建,分配。
Thread.cpp,Create_VM
-> Arguments::parse -> init_globals() -> universe_init() -> Universe::initialize_heap()
在上面的路径中,在
JVM
初始化阶段,会先分析传进来的
java
参数,将一些变量进行修改或者初始化。
从
Universe::initialize_heap()
开始创建、分配
java
heap
。
2.1
创建
CollectorPolicy
这里根据传进来的参数,创建合适的
CollectorPolicy
,即给相应的
Generation
,包括
YoungGen,OldGen,PermGen
设置好相应的描述参数,最终会创建
GenerationSpec
来描述每一个
Generation
,根据
GenerationSpec
去创建
Generatiion
。
在
Universe::initialize_heap()
函数中有下面的代码
if (UseParallelGC) {
#ifndef SERIALGC
Universe::_collectedHeap = new ParallelScavengeHeap();
#else // SERIALGC
fatal("UseParallelGC not supported in java kernel vm.");
#endif // SERIALGC
} else if (UseG1GC) {
#ifndef SERIALGC
G1CollectorPolicy* g1p = new G1CollectorPolicy_BestRegionsFirst();
G1CollectedHeap* g1h = new G1CollectedHeap(g1p);
Universe::_collectedHeap = g1h;
#else // SERIALGC
fatal("UseG1GC not supported in java kernel vm.");
#endif // SERIALGC
} else {
GenCollectorPolicy *gc_policy;
if (UseSerialGC) {
gc_policy = new MarkSweepPolicy();
} else if (UseConcMarkSweepGC) {
#ifndef SERIALGC
if (UseAdaptiveSizePolicy) {
gc_policy = new ASConcurrentMarkSweepPolicy();
} else {
gc_policy = new ConcurrentMarkSweepPolicy();
}
#else // SERIALGC
fatal("UseConcMarkSweepGC not supported in java kernel vm.");
#endif // SERIALGC
} else { // default old generation
gc_policy = new MarkSweepPolicy();
}
Universe::_collectedHeap = new GenCollectedHeap(gc_policy);
}
从这段代码中可以看出,根据一些参数的值,例如
UseConcMarkSweepGC
、
UseSerialGC
、
UseParallelGC
等等,选择何种
gc
策略,进而选择使用什么样的
heap
。
以
ParNew
和
Cms
为例来说,会执行到
gc_policy = new ConcurrentMarkSweepPolicy();
这一句,
ConcurrentMarkSweepPolicy
的继承关系结构如下
class ConcurrentMarkSweepPolicy : public TwoGenerationCollectorPolicy {
class TwoGenerationCollectorPolicy : public GenCollectorPolicy {
class GenCollectorPolicy : public CollectorPolicy {
class CollectorPolicy : public CHeapObj {
protected:
size_t _initial_heap_byte_size;
size_t _max_heap_byte_size;
size_t _min_heap_byte_size;
size_t _min_alignment;
size_t _max_alignment;
}
在
ConcurrentMarkSweepPolicy
的构造函数中,会执行下面一些操作。构造函数执行的次序如下。
1.CollectorPolicy
,简单初始化一些参数
_min_alignment(1),
_max_alignment(1),
_initial_heap_byte_size(0),
_max_heap_byte_size(0),
_min_heap_byte_size(0),
2.GenCollectorPolicy
,默认构造
3.TwoGenerationCollectorPolicy
,默认构造
4.ConcurrentMarkSweepPolicy
调用了
initialize_all()
initialize_all();GenCollectorPolicy
的虚函数
virtual void initialize_all() {
initialize_flags();
initialize_size_info();
initialize_generations();
}
接下来分析上面提到的三个初始化函数。
1.initialize_flags()
// 设置调整jvm 参数的值,实际上也就是PermGen的一些参数,CollectorPolicy methods,包括MaxPermSize,PermSize,SharedReadOnlySize,SharedReadWriteSize,SharedMiscDataSize
void CollectorPolicy::initialize_flags() {
// 设置调整jvm 参数的值,包括NewSize,MaxNewSize,SurvivorRatio
void GenCollectorPolicy::initialize_flags() {
// 设置最小对齐65536=64k
set_min_alignment((uintx) Generation::GenGrain);
// 设置最大对齐card_size * os::vm_page
set_max_alignment(compute_max_alignment());
}
/// 设置调整jvm 参数的值,包括OldSize,MaxHeapSize
TwoGenerationCollectorPolicy::initialize_flags
2.initialize_size_info();
//设置_initial_heap_byte_size,_max_heap_byte_size,_min_heap_byte_size
CollectorPolicy::initialize_size_info(){
}
//设置gen[0]
GenCollectorPolicy::initialize_size_info(){
set_min_gen0_size(max_new_size);
set_initial_gen0_size(max_new_size);
set_max_gen0_size(max_new_size);
}
//设置gen[1], _min_gen1_size, _max_gen1_size, _initial_gen1_size
TwoGenerationCollectorPolicy::initialize_size_info(){
}
3.initialize_generations();
ConcurrentMarkSweepPolicy::initialize_generations(){
CollectorPolicy::initialize_perm_generation(),初始化PermGenSpec
_generations = new GenerationSpecPtr[number_of_generations()];//分代,为2
//ParNewGen::in_user()
_generations[0] = new GenerationSpec(Generation::ParNew,
_initial_gen0_size, _max_gen0_size);
_generations[1] = new GenerationSpec(Generation::ConcurrentMarkSweep,
_initial_gen1_size, _max_gen1_size);
//NewGen ,OldGen, PermGen
//NewGen+OldGen = MaxHeapSize
New GenCollectedHeap();初始化gc的workgroup WorkGang
}
2.2
创建
GenCollectedHeap
在创建完
CollectorPolicy
之后,会创建
GenCollectedHeap
。在创建
GenCollectedHeap
中,没有进行真正分配空间,只是初始化了一些参数而已,真正的分配空间是在
Universe::heap()->initialize()
中进行的。
3.2Java Heap
分配
创建
GenCollectedHeap
后,会有初始化的代码,
Universe::heap()->initialize();
这里调用了
GenCollectedHeap::initialize()
,主要代码及注释如下所示。
{
//分配区域,由heap_rs保存,三个区域:YoungGen,OldGen,PermGen
heap_address = allocate(alignment, perm_gen_spec, &n_covered_regions,
&n_covered_regions, &heap_rs);
//_reserved区域包括Y,O,P三个区域
_reserved = MemRegion((HeapWord*)heap_rs.base(),
(HeapWord*)(heap_rs.base() + heap_rs.size()));
_reserved.set_word_size(0);
_reserved.set_start((HeapWord*)heap_rs.base());
size_t actual_heap_size = heap_rs.size() - perm_gen_spec->misc_data_size()
- perm_gen_spec->misc_code_size();
_reserved.set_end((HeapWord*)(heap_rs.base() + actual_heap_size));
//_rem_set管理的_reserved区域为分配的整体内存,包括三个部分Y,O,P
_rem_set = collector_policy()->create_rem_set(_reserved, n_covered_regions);
set_barrier_set(rem_set()->bs());
//将_reserved区域划分到对应的二个Y,O区域,并init
for (i = 0; i < _n_gens; i++) {
ReservedSpace this_rs = heap_rs.first_part(_gen_specs[i]->max_size(),
UseSharedSpaces, UseSharedSpaces);
_gens[i] = _gen_specs[i]->init(this_rs, i, rem_set());
heap_rs = heap_rs.last_part(_gen_specs[i]->max_size());
}
//划分剩余的区域到perm gen,并init
_perm_gen = perm_gen_spec->init(heap_rs, PermSize, rem_set());
}
从代码中看出,这里是根据之前的
generationspec
,通过
allocate
函数分配出空间,包括
YoungGen,OldGen,PermGen
,然后保存在
_reserved
中,
_reserved
会设置实际的
heap
空间为去掉
PermGen
中的
msic_data
和
msic_code
的空间;接下来会创建一个
BarrierSet
,这是一个覆盖整个
_reserved
实际空间的数组,数组中每个
byte
对应
heap
中的
512B(
根据
BarrierSet
中常量设置有关
)
;最后会依次初始化
YoungGen,OldGen,PermGen
。
JVM
会根据传进来的参数选择
gc
算法,
gc
算法确定后,
CollectorPolicy
就会确定了,确定完
collectorpolicy
就能知道
GenerationSpec
,然后创建
GenCollectedHeap
,根据
GenerationSpec
初始化
JavaHeap
中的
YoungGen,OldGen,PermGen
。
分享到:
相关推荐
jdk1.8。hotspot java jdk java开发工具。
[inside hotspot] java方法调用的StubCode1
这是官方的原版表中文档。Java11平台中,官方hotspot虚拟机的具体实现的标书。
学习JDK 源码必备,提起HotSpot VM,相信所有Java程序员都知道,它是Sun JDK和OpenJDK中所带的虚拟机,也是目前使用范围最广的Java虚拟机。 但不一定所有人都知道的是,这个目前看起来“血统纯正”的虚拟机在最初...
The_Java_HotSpot_Performance_Engine_Architecture,java虚拟机进阶
Memory Management in the Java HotSpot Virtual Machine.pdf
Troubleshooting Guide for Java SE 6 with HotSpot VM
Create WiFi Hotspot.bat(创建WiFi热点)
jvm参数介绍,oracle HotSpot官方参数文档。
java openJDK 源码, Hotspot, 未编译, 原始代码, 直接zip压缩包, java openJDK 源码, Hotspot, 未编译, 原始代码, 直接zip压缩包, java openJDK 源码, Hotspot, 未编译, 原始代码, 直接zip压缩包
The Java HotSpot VM.pdf
Java_HotSpot虚拟机的内存管理.pdf
Kupiki-Hotspot-Script, 自动创建一个带有 树莓派的全Wifi热点 什么是Kupiki热点这个项目是最新版本的教程 tutorial在我的博客 Pi Home创建 first Home Home Home,一些功能和工具无法用于 树莓派 3 。 另外,由于...
The Java Platform, Standard Edition HotSpot Virtual Machine Garbage Collection Tuning Guide describes the garbage collection methods included in the Java HotSpot Virtual Machine (Java HotSpot VM) and ...
本书深入浅出地讲解了 HotSpot 虚拟机的工作原理,将隐藏在它内部的本质内容逐一呈现在读者面前,包 括 OpenJDK 与 HotSpot 项目、编译和调试 HotSpot 的方法、HotSpot 内核结构、Launcher、OOP-Klass 对象表 示系统...
Java jdk1.8环境一键安装配置.
《HotSpot实战》深入浅出地讲解了HotSpot虚拟机的工作原理,将隐藏在它内部的本质内容逐一呈现在读者面前,包括OpenJDK与HotSpot项目、编译和调试HotSpot的方法、HotSpot内核结构、Launcher、OOP-Klass对象表示系统...
【译】Java 14 Hotspot 虚拟机垃圾回收调优指南(csdn)————程序