`
小滔哥
  • 浏览: 58995 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

Hotspot中Java Heap的构成与创建

    博客分类:
  • JVM
 
阅读更多
  • 1. JavaHeap 的构成

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

 

  • 3. 总结

      JVM 会根据传进来的参数选择 gc 算法, gc 算法确定后, CollectorPolicy 就会确定了,确定完 collectorpolicy 就能知道 GenerationSpec ,然后创建 GenCollectedHeap ,根据 GenerationSpec 初始化 JavaHeap 中的 YoungGen,OldGen,PermGen

分享到:
评论
1 楼 陌路千里 2016-12-28  
有所收获

相关推荐

    08-java11-hotspot-guide.pdf

    Java 11版本中的HotSpot虚拟机,与之前版本相比,引入了新的垃圾回收器(Epsilon垃圾回收器)、新的HTTP客户端API、支持新的HTTP/2协议等特性。 最后,文档强调,尽管Oracle的软件是为了普通用途的信息管理应用开发...

    jdk1.8 下载。 hotspot (包含源码)

    在JDK 1.8中,还有一项重要改进是 Nashorn JavaScript引擎的引入,这使得Java可以直接运行JavaScript代码,促进了Java与JavaScript之间的互操作性。 为了便于开发,JDK 1.8还包括了增强的调试工具,如JConsole和...

    翻译《Memory Management in the Java HotSpot™ Virtual Machine》

    《Memory Management in the Java HotSpot™ Virtual Machine》一文深入探讨了Java HotSpot虚拟机中的内存管理机制,这是Java性能优化的关键领域。HotSpot虚拟机是Oracle JDK和JRE的一部分,以其高性能和优化能力而...

    java 虚拟机 hotspot 源码

    java 虚拟机 hotspot 源码

    Troubleshooting Guide for Java SE 6 with HotSpot VM

    《Java SE 6与HotSpot VM故障排除指南》是Oracle公司于2008年11月发布的一份技术文档,旨在帮助开发人员、系统管理员和技术支持人员解决在使用Java Standard Edition 6 (Java SE 6) 和HotSpot虚拟机过程中遇到的各种...

    java-jdk-hotspot源码

    学习JDK 源码必备,提起HotSpot VM,相信所有Java程序员都知道,它是Sun JDK和OpenJDK中所带的虚拟机,也是目前使用范围最广的Java虚拟机。 但不一定所有人都知道的是,这个目前看起来“血统纯正”的虚拟机在最初...

    The_Java_HotSpot_Performance_Engine_Architecture

    ### Java HotSpot 性能引擎架构相关知识点 #### 一、引言与概览 **Java HotSpot 虚拟机**是 Sun 公司针对 Java 平台设计的一款高性能虚拟机,它作为 Java SE 平台的核心组件,为商业关键型应用提供了强大的支持。...

    [inside hotspot] java方法调用的StubCode1

    本文将详细介绍 HotSpot 中与 Java 方法调用相关的 StubCode,特别是通过 `JavaCalls` 类中的方法调用来理解其内部机制。 #### JavaCalls 类详解 在 HotSpot 的源代码中,`JavaCalls` 类位于 `hotspot/src/share/...

    hotspot-8.rar

    【标题】"hotspot-8.rar" 涉及的核心知识点是HotSpot虚拟机和JVM(Java Virtual Machine)的学习,这是一款由Oracle公司开发的Java虚拟机实现,广泛应用于Java程序的运行与优化。HotSpot是Java平台的重要组成部分,...

    HotSpot线程实现-线程创建1

    在HotSpot中,线程类型包括虚拟机工作线程(如GC线程)和用户自定义线程(即JavaThread,对应用户创建的`Thread`实例)。JavaThread是一个CHeapObj的子类,存储在C的堆中,不受垃圾回收管理。 3. **Linux内核层**:...

    《HotSpot实战》

    《HotSpot实战》这本书深入探讨了Java开发中的关键组件——HotSpot虚拟机。HotSpot是Oracle JDK和OpenJDK中的默认Java虚拟机,它在Java应用程序的运行时性能优化方面扮演着重要角色。以下是该书可能涵盖的一些核心...

    Memory Management in the Java HotSpot Virtual Machine.pdf

    本文档提供了Java HotSpot虚拟机(JVM)中内存管理的广泛概述,特别是在Sun公司的Java 2平台标准版(J2SE)5.0版本的发布中。文档描述了可供使用的垃圾收集器(Garbage Collectors),给出了关于如何选择和配置收集...

    The Java HotSpot VM.pdf

    《Java HotSpot 虚拟机》文件中包含了关于Java虚拟机(JVM)的深入讨论,尤其是在HotSpot虚拟机上的即时编译(JIT)技术,以及Java语言的最新发展。文件内容侧重于以下几个核心知识点: 1. **Java HotSpot虚拟机的...

    java openJDK 源码, Hotspot

    java openJDK 源码, Hotspot, 未编译, 原始代码, 直接zip压缩包, java openJDK 源码, Hotspot, 未编译, 原始代码, 直接zip压缩包, java openJDK 源码, Hotspot, 未编译, 原始代码, 直接zip压缩包

    jdk-8.0.302.8-hotspot

    【标题】"jdk-8.0.302.8-hotspot" 是Oracle公司发布的Java Development Kit(JDK)的一个版本,它包含了Java运行时环境(JRE)和用于开发Java应用程序的工具。这个特定的版本是8u302,意味着它是Java 8的更新302版,...

    JDK7底层C++源码及hotspot虚拟机源码

    《深入解析JDK7:基于C++的底层源码与HotSpot虚拟机剖析》 在IT领域,Java作为一门广泛使用的编程语言,其性能优化和内部机制一直是开发者关注的焦点。JDK7作为Java发展历程中的一个重要版本,引入了许多创新特性,...

    hotspot源码

    HotSpot VM,作为Java开发人员耳熟能详的名字,是Sun JDK和OpenJDK中的核心组件,它的普及程度无出其右。HotSpot以其高效性能、优秀的垃圾回收机制以及丰富的优化手段,赢得了全球Java开发者的一致青睐。本文将围绕...

    JVM Hotspot实现源码

    4. **虚拟机接口模块**:提供与Java语言交互的接口,包括JNI(Java Native Interface)和JVM TI(Java Virtual Machine Tool Interface),它们允许C/C++代码与Java代码交互,以及调试和监控工具接入。 5. **服务...

    hotspot 源码(JDK8)

    Hotspot实现了Java线程模型,并且优化了线程创建、调度和同步原语。通过源码,我们可以深入理解Java线程的实现,以及如何优化线程池和并发程序。 8. **性能监控与诊断工具** Hotspot提供了丰富的性能监控和诊断...

Global site tag (gtag.js) - Google Analytics