Metaspace

Metaspace 大家应该很熟悉了,所有线程共享的一块内存区域,主要存放已被虚拟机加载的类定义,方法定义,常量等一些元数据信息,运行时常量池(Runtime Constant Pool)也是方法区的一部分,Class 文件中的常量池表(Constant Pool Table,里面各种字面量和符号引用),被类加载后就放入方法区的运行时常量池 。运行时常量池并不只有编译时才往里放东西,运行时也可以放新的常量,比如 String.intern()。有一个别名叫“非堆”。

jdk1.8以后直接用本地内存实现方法区,并改名叫 Metaspace。正因为用本地内存(native memory),所以它的最大内存可以达到机器内存的极限,但关于它的调优参数一直有个误解。

MetaspaceSize

-XX:MetaspaceSize 并不代表初始的 Metaspace 大小,在 oracle doc 中,有明确的解释

Class metadata is deallocated when the corresponding Java class is unloaded.
Java classes are unloaded as a result of garbage collection, and garbage collections may be induced to unload classes and deallocate class metadata.
When the space committed for class metadata reaches a certain level (a high-water mark), a garbage collection is induced.
After the garbage collection, the high-water mark may be raised or lowered depending on the amount of space freed from class metadata.
The high-water mark would be raised so as not to induce another garbage collection too soon.
The high-water mark is initially set to the value of the command-line option -XX:MetaspaceSize.
It is raised or lowered based on the options -XX:MaxMetaspaceFreeRatio and -XX:MinMetaspaceFreeRatio.
If the committed space available for class metadata as a percentage of the total committed space for class metadata is greater than -XX:MaxMetaspaceFreeRatio, then the high-water mark will be lowered.
If it's less than -XX:MinMetaspaceFreeRatio, then the high-water mark will be raised.

大致意思就是当 MetaspaceSize 接近一个指定水位(high-water mark)的时候,会引发垃圾回收,这个初始化的水位值就是 -XX:MetaspaceSize

另一方面,水位值会上下浮动,上浮主要是为了避免过早引发一次垃圾回收,而上下浮动主要由 两个参数控制

  • -XX:MaxMetaspaceFreeRatio:已提交的 Metaspace 空间中剩余可用的占全部提交空间的比例 大于 MaxMetaspaceFreeRatio ,说明 Metaspace 空间仍有富余,会降低水位。
  • -XX:MinMetaspaceFreeRatio:反之,如果比例小于 MinMetaspaceFreeRatio ,说明 Metaspace 空间比较紧张,会升高水位。

这说明如果你只指定 -XX:MetaspaceSize,然后再做 Metaspace oom实验,并不代表 gc 会在你指定的值发生,因为这个值会上下浮动。

最后再提下 -XX:MaxMetaspaceSize 就是字面意思,会给 MetaspaceSize 设一个上限,默认空间是无限的(default unlimited)。

-XX:MetaspaceSize 验证实验

前面说了,要做 Metaspace oom 实验还需要考虑 MaxMetaspaceFreeRatioMinMetaspaceFreeRatio 的设置,这次我的 gc 参数设为如下,都设为 0 是避免水位上下浮动:

-XX:+UseG1GC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:MetaspaceSize=8m -XX:MaxMetaspaceFreeRatio=0 -XX:MinMetaspaceFreeRatio=0

然后自定义一个大对象 OomObject

public class OomObject {String[] strings;public OomObject() {this(1);}/*** size,unit mb*/public OomObject(int size) {if (size <= 0) {size = 1;}strings = new String[size];for (int i = 0; i < size; i++) {strings[i] = new String(createObject());}}/*** create 1mb object** @return*/private byte[] createObject() {return new byte[1024 * 300];}
}

然后单元测试 会无限循环创建 OomObject 的子类(通过cglib,并且关闭缓存),这样会慢慢填充 MetaspaceSize,并且实时打印 MetaspaceSize log。

    @Testpublic void testMetaSpaceOom() throws InterruptedException {
//        ArrayList<Object> objects = new ArrayList<Object>();List<MemoryPoolMXBean> memoryPoolMXBeans = ManagementFactory.getMemoryPoolMXBeans();while (true) {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(OomObject.class);enhancer.setUseCache(false);enhancer.setCallback(new MethodInterceptor() {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)throws Throwable {return proxy.invokeSuper(obj, args);}});enhancer.create();Thread.sleep(200);for (MemoryPoolMXBean poolMXBean : memoryPoolMXBeans) {if (MemoryType.NON_HEAP.equals(poolMXBean.getType())) {MemoryUsage usage = poolMXBean.getUsage();if (poolMXBean.getName().contains("Metaspace")) {System.out.println(poolMXBean.getName() + ":" + usage.getCommitted());}}}}}

最后我们可以看到成果,在 MetaspaceSize 达到 8m 的时候,会触发 Metadata GC Threshold gc,验证了 -XX:MetaspaceSize 的作用。

···
Metaspace:8388608
Metaspace:8388608
2021-08-26T15:59:08.109+0800: [GC pause (Metadata GC Threshold) (young) (initial-mark), 0.0046983 secs][Parallel Time: 3.6 ms, GC Workers: 8][GC Worker Start (ms): Min: 36019.2, Avg: 36019.4, Max: 36020.0, Diff: 0.8][Ext Root Scanning (ms): Min: 0.0, Avg: 0.5, Max: 0.8, Diff: 0.8, Sum: 4.0]···

G1调优实践日记--被误解的MetaspaceSize相关推荐

  1. JVM性能调优实践——G1 垃圾收集器分析、调优篇

    前言 关于G1 GC以及其他垃圾收集器的介绍可以参考前一篇JVM性能调优实践--G1 垃圾收集器介绍篇.了解了G1垃圾收集器的运行机制之后,就可以针对一些GC相关参数来调整内存分配以及运行策略.下文的 ...

  2. 深入理解JVM虚拟机10:JVM常用参数以及调优实践

    本文转自[JVM常用参数以及调优实践](https://blog.csdn.net/a724888/article/details/78367780) JVM常用参数选项 jvm 可配置的参数选项可以 ...

  3. 软件性能测试分析与调优实践之路---性能测试系列-java gc调优

    性能测试中除了需要做好性能测试外,我们还需要做性能测试后的,性能调优,需要发现性能问题,也需要做性能调优,在做性能调优中,jvm的性能调优是经常遇到的一个. 随着jdk版本的迅速变化,jdk里面的GC ...

  4. MindSpore模型精度调优实践

    MindSpore模型精度调优实践 引论:在模型的开发过程中,精度达不到预期常常让人头疼.为了帮助用户解决模型调试调优的问题,为MindSpore量身定做了可视化调试调优组件:MindInsight. ...

  5. 实时数仓入门训练营:Hologres性能调优实践

    简介:<实时数仓入门训练营>由阿里云研究员王峰.阿里云高级产品专家刘一鸣等实时计算 Flink 版和 Hologres 的多名技术/产品一线专家齐上阵,合力搭建此次训练营的课程体系,精心打 ...

  6. B站Up主上传质量调优实践

    Up主上传的大量优质视频内容使得bilibili(B站)深受年轻用户的喜爱.bilibili视频云高级研发经理 唐君行在LiveVideoStack线上交流分享中详细介绍了B站为提供更流畅.稳定用户体 ...

  7. Web2.0网站性能调优实践(引用王宗义)

    Web2.0网站性能调优实践 当前web2.0革命风起云涌,web2.0强调服务,而服务最基本的要求是速度快和稳定,离开这两个谈功能强大和易用性都没有任何意义.本文介绍一些关于笔者运营一个web2.0 ...

  8. 基于Fabric的性能测试与调优实践

    1  Fabric 性能测试现状 通俗的来讲,区块链是一种按照时间顺序将数据区块以顺序相连的方式组合成的一种链式数据结构,并以密码学方式保证的不可篡改和不可伪造的分布式账本.比特币(Bitcoin). ...

  9. Azure SQL性能调优实践

    Azure SQL性能调优实践 注:blog具备时效性,所有内容都是在当前时间为准,截止时间2017-6-5 首先,创建了一个测试数据库 MaxAadventureWorkTest 使用了 示例数据库 ...

最新文章

  1. 基于农业物联网的感知数据获取和可视化系统
  2. 【杂谈】您想要的docker环境来了!
  3. 二分匹配(匈牙利算法)
  4. 130506datafile和tablespace offline区别
  5. 中国豪华的政府大楼VS破学校
  6. vs2008试用期到期解决办法
  7. 【英语】The Little Prince
  8. wordpress js 运行短代码_7个WordPress常用代码段(Code Snippets)
  9. Android开发:setAlpha()方法
  10. din字体是开源字体吗_字体 DIN 与工业标准
  11. 谷歌代码规范的中文版
  12. python arp断网攻击_arp断网攻击,小编教你arp断网攻击怎么解决
  13. 多线程并发编程知识点汇总
  14. DNS错误不能上网怎么办?电脑dns错误修复方法?
  15. php实现大文件分片上传
  16. 成长计划校园极客秀|基于OpenHarmony的智能阳台
  17. 笔记1-----校园网进知网步骤
  18. ffmpeg截取一段视频中一段视频
  19. 骑行318、 2016.7.25
  20. 对一支圆珠笔进行测试,要从哪些方面进行测试?

热门文章

  1. 优质的海鲜cc0高清摄影图片素材推荐,不容错过
  2. 【每日最爱一句】2013.06.25
  3. ACM--火星文--HDOJ 1075--What Are You Talking About--map
  4. java读早春韩愈,韩愈早春古诗赏析
  5. Python网络协议编程之HTTP协议详解
  6. 2019年区块链有什么规划
  7. KL散度及Python实现
  8. python读取图像的exif信息
  9. 拿什么拯救缺芯又“缺心”的科技产业?
  10. 阿里云购买ECS服务器,实例列表无实例