-XX:PretenureSizeThreshold的默认值和作用浅析-阿里云开发者社区

开发者社区> 明明如月> 正文

-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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
10014 0
-XX:PretenureSizeThreshold的默认值和作用浅析
-XX:PretenureSizeThreshold的默认值和作用浅析
52 0
阿里云服务器ECS远程登录用户名密码查询方法
阿里云服务器ECS远程连接登录输入用户名和密码,阿里云没有默认密码,如果购买时没设置需要先重置实例密码,Windows用户名是administrator,Linux账号是root,阿小云来详细说下阿里云服务器远程登录连接用户名和密码查询方法
11587 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
10880 0
Reset按钮在回发之后就不起作用
今天突然发现Reset按钮在回发之后就不起作用了,清不掉TextBox里的值。    网上搜了一下,只有问题,没有答案。csdn上一个老帖子里说和ViewState之类的有关,把我还搞得晕乎乎的,想想reset按钮怎么也就是一个客户端的控件,和服务器端根本不搭界,怎么可能呢?ViewState怎么也得到了服务器端才开始解析呀。
865 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
13814 0
阿里云ECS云服务器初始化设置教程方法
阿里云ECS云服务器初始化是指将云服务器系统恢复到最初状态的过程,阿里云的服务器初始化是通过更换系统盘来实现的,是免费的,阿里云百科网分享服务器初始化教程: 服务器初始化教程方法 本文的服务器初始化是指将ECS云服务器系统恢复到最初状态,服务器中的数据也会被清空,所以初始化之前一定要先备份好。
7339 0
+关注
明明如月
阿里巴巴 资深Java开发工程师
343
文章
1
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载