配置 -xx:pretenuresizethreshold 需要在启动 jvm 时指定该参数,并设置一个具体的字节数值。该参数仅对 serial 和 parallel 垃圾收集器生效,用于规定对象在 eden 区直接分配到大内存空间(old gen)的大小阈值,超过此阈值的对象将直接在 old gen 分配,从而减少 minor gc 的次数。

哪些收集器支持 PretenureSizeThreshold?
只有 Serial 和 Parallel Scavenge 收集器支持 -XX:PretenureSizeThreshold 参数。如果使用 CMS 或 G1 收集器,该参数会被忽略,因为它们的内存管理策略不同。CMS 采用标记-清除算法,G1 则基于 Region 划分,两者都不依赖固定的大对象直接进入 Old Gen 的简单规则。

JVM_OPTS="-Xms512m -Xmx512m -Xmn256m -XX:+UseParallelGC -XX:PretenureSizeThreshold=10485760"
上述命令中,-XX:+UseParallelGC 启用了 Parallel Scavenge 收集器,-XX:PretenureSizeThreshold=10485760 设置了阈值为 10MB。当程序尝试分配一个大于 10MB 的对象时,JVM 会尝试直接在 Old Gen 中分配该对象,而不是先在 Eden 区分配。
如何验证 PretenureSizeThreshold 是否生效?
可以通过编写一个简单的 Java 程序来验证该参数的效果。程序将分配不同大小的对象,并观察 GC 日志或堆转储文件,确认大对象是否直接进入了 Old Gen。

import java.util.ArrayList;
import java.util.List;
public class PretenureTest {
public static void main(String[] args) {
// 分配一个小于阈值的小对象
byte[] smallObj = new byte[1024 * 1024]; // 1MB
// 分配一个大于阈值的大对象
byte[] largeObj = new byte[11 * 1024 * 1024]; // 11MB
System.out.println("Small object allocated.");
System.out.println("Large object allocated.");
// 防止 JIT 优化掉未使用的变量
System.gc();
}
}
运行上述程序时,使用之前设置的 JVM 参数。通过 jstat -gcutil 观察 GC 频率,或使用 jmap -histo:live 查看堆中对象的分布。如果配置正确,11MB 的大对象应直接出现在 Old Gen 中,而不会在 Eden 区经历多次 Minor GC 后才晋升。
PretenureSizeThreshold 的实际应用场景是什么?
该参数适用于那些存在大量固定大小且生命周期较长的对象的场景。例如,在处理大型二进制数据、缓存图片或视频片段时,如果这些对象的大小相对稳定且远大于默认阈值,设置 PretenureSizeThreshold 可以减少 Young Gen 的 GC 压力,提升系统吞吐量。然而,需要注意的是,过大的阈值可能导致 Old Gen 迅速填满,引发 Full GC,因此需要根据实际业务需求和堆大小进行合理调整。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











