OpenJDK源码分析之DirectMemory大小
Posted 彭薄
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
推荐阅读
以上是关于OpenJDK源码分析之DirectMemory大小的主要内容,如果未能解决你的问题,请参考以下文章