-XX:PretenureSizeThreshold的默认值和作用浅析

简介: -XX:PretenureSizeThreshold的默认值和作用浅析

一、背景

《深入理解Java虚拟机》第93页,3.6.2 大对象直接进入老年代。


讲到大对象主要指字符串和数组,虚拟机提供了一个-XX:PretenureSizeThreshold参数,大于这个值的参数直接在老年代分配。


这样做的目的是避免在Eden区和两个Survivor区之间发生大量的内存复制(新生代采用复制算法)。


但是这里没讲清楚默认值是多少,默认会不会“大”对象直接进入老年代。


二、解析

2.1 参考文章

找到了一篇相关问题的文章《Frequently Asked Questions about Garbage Collection in the HotspotTM JavaTM Virtual Machine》


第29条:Do objects ever get allocated directly into the old generation?


In 1.4.1 there two situations where allocation may occur directly into the old generation.


有两种情况,对象会直接分配到老年代。

If an allocation fails in the young generation and the object is a large array that does not contain any references to objects, it can be allocated directly into the old generation. In some select instances, this strategy was intended to avoid a collection of the young generation by allocating from the old generation.


如果在新生代分配失败且对象是一个不含任何对象引用的大数组,可被直接分配到老年代。


通过在老年代的分配避免新生代的一次垃圾回收。


There is a flag (available in 1.4.2 and later) l-XX:PretenureSizeThreshold= that can be set to limit the size of allocations in the young generation. Any allocation larger than this will not be attempted in the young generation and so will be allocated out of the old generation.


XX:PretenureSizeThreshold=<字节大小>可以设分配到新生代对象的大小限制。


任何比这个大的对象都不会尝试在新生代分配,将在老年代分配内存。


The threshold size for 1) is 64k words. The default size for PretenureSizeThreshold is 0 which says that any size can be allocated in the young generation.


PretenureSizeThreshold 默认值是0,意味着任何对象都会现在新生代分配内存。


2.2 实验解析

设置虚拟机参数


-Xms2048m

-Xmx2048m

-Xmn1024m

-XX:+UseConcMarkSweepGC


-XX:SurvivorRatio=8


-Xms表示初始化堆内存


-Xmx 表示最大堆内存


-Xmn表示新生代的内存


-XX:SurvivorRatio=8表示新生代的Eden占8/10,S1和S2各占1/10.


因此Eden的内存大小为:0.8*1024*1024*1024字节 约为819**1024*1024


上代码

public class Test {
    public static void main(String[] args) throws Exception {
        byte[] array = new byte[700 * 1024 * 1024];//734003216
        for (MemoryPoolMXBean memoryPoolMXBean : ManagementFactory.getMemoryPoolMXBeans()) {
            System.out.println(memoryPoolMXBean.getName() + "  总量:" + memoryPoolMXBean.getUsage().getCommitted() + "   使用的内存:" + memoryPoolMXBean.getUsage().getUsed());
        }
    }
}

可以看到应该被分配到了新生代的Eden区


Code Cache  总量:2555904   使用的内存:1206528

Metaspace  总量:4980736   使用的内存:3426872

Compressed Class Space  总量:524288   使用的内存:371280

Par Eden Space  总量:859045888   使用的内存:785546016

Par Survivor Space  总量:107347968   使用的内存:0

CMS Old Gen  总量:1073741824   使用的内存:0


将数组对象增加到大于Eden区内存大小


byte[] array = new byte[900 * 1024 * 1024];

会导致新生代分配失败,直接进入老年代


Code Cache  总量:2555904   使用的内存:1197824

Metaspace  总量:4980736   使用的内存:3426024

Compressed Class Space  总量:524288   使用的内存:371280

Par Eden Space  总量:859045888   使用的内存:34361864

Par Survivor Space  总量:107347968   使用的内存:0

CMS Old Gen  总量:1073741824   使用的内存:943718416


且此时通过jstat -gcutil vmpid命令查看垃圾回收状态,发现并没有YGC.


然后我们将字节数组改回 小于Eden去内存


byte[] array = new byte[700 * 1024 * 1024];

并添加启动参数-XX:PretenureSizeThreshold=100000000


Code Cache  总量:2555904   使用的内存:1172160

Metaspace  总量:4980736   使用的内存:3412552

Compressed Class Space  总量:524288   使用的内存:371280

Par Eden Space  总量:859045888   使用的内存:51542800

Par Survivor Space  总量:107347968   使用的内存:0

CMS Old Gen  总量:1073741824   使用的内存:734003216


发现即使新生代足够分配,大于这个值的大对象也直接在老年代分配。


从而印证了上面文档的说法。


三、总结

多查权威参考文档,参考价值更大。


多试验看效果,实践印象才更加深刻。


思路参考自:https://www.jianshu.com/p/f7cde625d849

相关文章
|
机器人
如何查询OpenAI账户余额?ChatGPT怎么查看账户余额的方法
ChatGPT是美国OpenAI研发的聊天机器人程序,也是最近火爆全网的热门应用和话题之王。很多用户在使用openai的时候不知道如何查询OpenAI账户余额?
2772 0
|
Linux 数据处理 Perl
深入探索Linux中的`more`命令
`more`命令是Linux下的文本查看器,适合查看长文件,分页显示内容,支持交互操作如空格(下一页)、回车(下一行)、q(退出)。参数包括:+&lt;num&gt;从指定行开始,/-&lt;num&gt;跳过行,/pattern搜索模式。示例:查看日志`more /var/log/syslog`,从第1000行开始`more +1000 file`,搜索关键词`more /var/log/syslog +/ERROR`。大文件可考虑使用`less`。结合`grep`等命令增强功能。
|
监控 Java Linux
CPU被打满/CPU 100%:高效诊断与优化策略
【8月更文挑战第28天】在日常的工作与学习中,遇到CPU使用率飙升至100%的情况时,往往意味着系统性能受到严重影响,甚至可能导致程序响应缓慢或系统崩溃。本文将围绕这一主题,分享一系列高效诊断与优化CPU使用的技术干货,帮助大家快速定位问题并恢复系统性能。
709 1
|
数据采集 机器学习/深度学习 分布式计算
从0到1搭建车企数字化营销中台(4):客户数据平台(CDP)
CDP作为数字化营销中台的核心数据引擎,承载着拉通客户全渠道、全旅程链路的数据,实现智能洞察和营销决策
3695 0
从0到1搭建车企数字化营销中台(4):客户数据平台(CDP)
|
消息中间件 存储 中间件
【SpringCloud Stream消息驱动、设计思想以及整合rabbitmq消息队列案例--学习笔记】
【SpringCloud Stream消息驱动、设计思想以及整合rabbitmq消息队列案例--学习笔记】
502 0
|
算法 Java
「译文」Java 垃圾收集参考手册(六):Concurrent Mark and Sweep
「译文」Java 垃圾收集参考手册(六):Concurrent Mark and Sweep
|
存储 分布式计算 JavaScript
Fury系列(四):一个比Kryo/Hessian快30~40倍的类型前后兼容序列化器
问题背景类型前后兼容是复杂业务场景序列化的常见需求。在快速迭代的业务场景当中,读写端经常发生对象字段发生变更:在线应用场景:线上SOFA/HSF应用提供服务给多个调用方,服务的滚动升级以及各个调用方独立更新都可能导致对象类型不一致的情况;在线服务场景:在线服务框架常驻不更改对象类型,但调用方业务逻辑变动独立更新导致对象字段跟服务端不一致;对象持久化场景:对象数据序列化后持久化写入存储(如Spark
892 0
Fury系列(四):一个比Kryo/Hessian快30~40倍的类型前后兼容序列化器
|
安全 Java
使用Java8新特性parallelStream遇到的坑
使用Java8新特性parallelStream遇到的坑
|
存储 Java
JDK13的新特性:AppCDS详解
JDK13的新特性:AppCDS详解
|
NoSQL 算法 网络安全
阿里云 Redis 开发规范
阿里云 Redis 开发规范
1795 0

热门文章

最新文章