OpenJDK源码分析之DirectMemory大小(二)

OpenJDK源码包结构介绍

上文我们从JDK里面的java代码实现跟踪到了Runtime.getRuntime().maxMemory();这个Native方法,那么要理解这个方法如何实现,就需要下载OpenJDK的源码进行学习了。下面我们先介绍一下OpenJDK源码包的结构,避免我们在代码追踪时迷路:

OpenJDK 
—— corba:不流行的多语言、分布式通讯接口 
—— hotspot:Java 虚拟机 
—— jaxp:XML 处理 
—— jaxws:一组 XML web services 的 Java API 
—— jdk:java 开发工具包 
—— —— 针对操作系统的部分 
—— —— share:与平台无关的实现 
—— langtools:Java 语言工具 
—— nashorn:JVM 上的 JavaScript 运行时 

继续追踪Native方法

当我们要追踪Runtime.getRuntime().maxMemory();这个方法时,进入到jdk/src/share/native/java/lang里面,我们看到一些native方法

我们从Runtime.c开始再次从上往下找对应的代码路径

可以看出JVM_MaxMemory()方法是一个C或者C++定义和实现的方法,从头文件中追寻到jvm.cpp里面有实现

我们在Universe.hpp中看到如下方法:

现在追踪的路线都截止在了_collectedHeap这变量上,那么开始寻找修改_collectedHeap这个变量的地方,我们在Universe.cpp文件中看到有如下代码

jint Universe::initialize_heap() {

  if (UseParallelGC) {
#if INCLUDE_ALL_GCS
    Universe::_collectedHeap = new ParallelScavengeHeap();
#else  // INCLUDE_ALL_GCS
    fatal("UseParallelGC not supported in this VM.");
#endif // INCLUDE_ALL_GCS

  } else if (UseG1GC) {
#if INCLUDE_ALL_GCS
    G1CollectorPolicyExt* g1p = new G1CollectorPolicyExt();
    g1p->initialize_all();
    G1CollectedHeap* g1h = new G1CollectedHeap(g1p);
    Universe::_collectedHeap = g1h;
#else  // INCLUDE_ALL_GCS
    fatal("UseG1GC not supported in java kernel vm.");
#endif // INCLUDE_ALL_GCS

  } else {
    GenCollectorPolicy *gc_policy;

    if (UseSerialGC) {
      gc_policy = new MarkSweepPolicy();
    } else if (UseConcMarkSweepGC) {
#if INCLUDE_ALL_GCS
      if (UseAdaptiveSizePolicy) {
        gc_policy = new ASConcurrentMarkSweepPolicy();
      } else {
        gc_policy = new ConcurrentMarkSweepPolicy();
      }
#else  // INCLUDE_ALL_GCS
    fatal("UseConcMarkSweepGC not supported in this VM.");
#endif // INCLUDE_ALL_GCS
    } else { // default old generation
      gc_policy = new MarkSweepPolicy();
    }
    gc_policy->initialize_all();

    Universe::_collectedHeap = new GenCollectedHeap(gc_policy);
  }

可以看到_collectedHeap这个变量跟GC策略又关系,假设我们使用CMS策略来跟一遍代码。代码会执行到Universe::_collectedHeap = new GenCollectedHeap(gc_policy);我们在GenCollectedHeap这个类里面查找max_capacity();这个方法

通过查找_gens[i]找到

通过init方法,我们找到

在DefNewGeneration类里面找max_capacity()方法

可以看到最终的值为Xmx减去一个survivor的大小

得出结论

【1】堆外内存大小跟使用的GC策略有关系

【2】GenCollectedHeap是一种基于内存分代管理的内存堆管理器实现. 它一方面负责java对象的内存分配, 另一方面还得负责垃圾对象的回收, 而GC策略CollectorPolicy则是它的核心组件.这里,内存堆管理器GenCollectedHeap配置的GC策略实现GenCollectorPolicy的子类。

验证结论

我们如果想让直接内存为175M,那么指定-XX:SurvivorRatio=2

推荐阅读

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值