jvm配置整理

本文详细介绍了JVM的内存配置,包括如何输出GC日志、调整内存大小以及如何优化吞吐量。讨论了新生代、老年代和永久代的内存分配,并提供了具体的参数设置建议,如-Xms、-Xmx、-Xmn、-XX:NewSize、-XX:MaxNewSize等。此外,还强调了Survivor空间的重要性,提出了防止Survivor溢出的策略,并探讨了并行垃圾收集线程的调优。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、内存

(1)输出GC日志

-XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:<filename>

-XX:+PrintGCTimeStamps输出从虚拟机启动后到gc发生时的经历的时间(秒)。-XX:+PrintGCDetails输出gc统计信息,-Xloggc:<filename>,gc统计信息保存文件。

 

例子:(-XX:+UseParallelOldGC or -XX:+UseParallelGC)

0.064: [GC (Allocation Failure) [PSYoungGen: 512K->480K(1024K)] 512K->572K(3584K), 0.0016558 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

0.064,发生gc的时间标签,单位是s;

GC标签,表明当前GC是一个新生代GC(即minor gc);

PSYoungGen,多线程的吞吐量优先的新生代垃圾收集器;

512K->480K(1024),512K是垃圾收集之前新生代内存占用大小,480K是垃圾收集之后,新生代内存占用大小。(1024K)是新生代的大小包括eden,survivor区;

512K->572K(3584K),表示整个java堆(新生代+老年代)在gc前后的内存占用;

0.0016558 secs,垃圾收集用时;

 

-XX:+PrintGCDateStamps输出具体格式的时间,YYYY-MM-DDTHH-MM-SS

 

(2)调整内存

HotSpot VM有三个主要的区域,新生代、老年代、永久代。新生代保存存活时间较短的对象,老年代保存存活时间较长的对象,永久代保存类元数据和静态变量等。-Xms 和-Xmx指定java堆的初始大小,和最大容量。为保证运行程序高吞吐量和低延迟,-Xms和-Xmx的值设置成一样,禁止动态扩展,动态扩展会引起Full GC。

 

-XX:NewSize=<n>[g|m|k]

-XX:MaxNewSize=<n>[g|m|k]

-Xmn<n>[g|m|k]

-Xmn设置的值,既是新生代的初始值,也是新生代的最大值,设置此值后新生代不动态扩展,因此-Xmn用在-Xms和-Xmx值一样大的情形下。

老年代一般都是隐式设置,初始化老年代大小是-Xms 减去 -XX:NewSize,最大老年代是-Xmx减-XX:MaxNewSize,当-Xms和-Xmx一样大时,老年代是-Xmx减去-Xmn的值。

 

-XX:PermSize=<n>[g|m|k]

-XX:MaxPermSize=<n>[g|m|k]

设置永久代和最大永久代。若为追求更好的性能,需把初始永久代和最大永久代设置成相同的值,避免动态扩展带来的Full GC。

 

当新生代、老年代、永久代已经存满了,此时,新的请求需要分配内存,就会发生gc(垃圾收集)。若是新生代不够了,就触发minor GC。当老年代装不下已经老化的对象,永久代被占满时会触发Full GC。

 

-XX:-ScavengeBeforeGC

配置-XX:-ScanvengeBeforeGC时,在Full GC期间不会进行Minor GC。

 

jmap -histo:live pid

此命令可能触发一次Full GC。

 

-Xms和-Xmx应被设置为(Full GC后)存活的老年代空间的3~4倍;新生代-Xmn应设置为存活老年代空间的1~1.5倍,老年代应设置为存活老年代的2~3倍;-XX:PermSize和-XX:MaxPermSize应设置为永久代存活空间的1.2~1.5倍。

 

例子如下:

46.620: [Full GC (Heap Inspection Initiated GC) [PSYoungGen: 273K->0K(1536K)] [ParOldGen: 1640K->1369K(2048K)] 1914K->1369K(3584K), [Metaspace: 4944K->4940K(1056768K)], 0.0071578 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]

1369K * 4 = 5476k,-Xms5476k,-Xmx5476k

1369 * 1.5 = 2053.5 , -Xmn2054k

1369 * 2 = 2738k,1369 * 3 = 4107k

4940 * 1.5 = 7410k,-XX:PermSize=7410k,-XX:MaxPermSize=7410k

 

二、调优吞吐量

(1)Throughput吞吐量

-XX:+UseParallelOldGC

-XX:+UseParallelGC

-XX:-UseAdaptiveSizePolicy

-XX:-UseAdaptiveSizePolicy禁用自适应大小调整。只有Throughput收集器,支持自适应大小调整。

 

-XX:SurvivorRatio=8

-XX:+PrintAdaptiveSizePolicy

-XX:+PrintAdaptiveSizePolicy可以生成更详细的Survivor空间占用日志,无论Survivor空间溢出,还是对象从新生代提升进入老年代统统在其中。

[PSYoungGen: 1525K->418K(1536K)] 2749K->2013K(5632K), 0.0007124 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

2020-04-17T16:23:54.683+0800: 23.084: [GC (Heap Inspection Initiated GC) AdaptiveSizePolicy::update_averages: survived: 313224 promoted: 98304 overflow: false

survived:313224是To Survivor空间中存活对象的大小;promoted:98304是由新生代提升到老年代对象的大小;overflow:false表示是否Survivor空间的对象溢出到老年代空间(to空间小,装不下eden和from去存活对象)。

 

(2)Survivor空间调优

调整survivor大小并不仅是将Survivor空间大小设置成某个值,或者调整为稍大于从GC日志中获得的最大存活对象的值那么简单。在增大Survivor空间时,应该保持Eden空间大小的恒定不变。按Survivor空间的增量,增大新生代空间,同时维持老年代空间大小不变。HotSpot虚拟机Minor GC之后,目标survivor空间的占用的默认值是50%。(但是,若内存占用要求或系统可用内存不允许这样设置,需确保调整后的老年代空间远大于活跃数据大小。推荐准则,老年代空间至少应该是活跃数据大小的1.5倍)

overflow溢出案例,下面列出了jvm配置,和gc日志

-Xms6m -Xmx6m -Xmn2m -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:-UseAdaptiveSizePolicy -XX:+PrintAdaptiveSizePolicy -Xl oggc:./gc.log

 

2020-04-17T17:31:31.861+0800: 0.408: [GC (Allocation Failure) AdaptiveSizePolicy::update_averages: survived: 499744 promoted: 173728 overflow: true

[PSYoungGen: 1512K->488K(1536K)] 2785K->1931K(5632K), 0.0007031 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

499744 / (50%) = 999488字节,大约1m,jvm调整如下(当然实际情况下SurvivorRatio不会是1):

-Xms7m -Xmx7m -Xmn3m -XX:SurvivorRatio=1 -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:-UseAdaptiveSizePolicy -XX:+PrintAdaptiveSizePolicy -Xloggc:./gc.log

 

-XX:TargetSurvivorRatio=<n>

目标Survivor空间的占用百分比,默认值是50%,如果应用程序的对象分配有大幅波动,将目标Survivor空间占用大小设置成大于50会导致Survivor空间溢出。

 

(3)调优并行垃圾收集线程

-XX:ParallelGCThreads=<n>

并行垃圾收集器使用的线程数,应依据系统上运行的应用程序数和底层硬件平台进行相应的调优。默认情况下并行垃圾收集线程数等于Java API Runtime.availableProcessors()的返回值(如果返回值小于等于8),否则其等于Runtime.avaliableProcessors()返回值的5/8。多个应用程序运行于同一系统时,设置并行垃圾收集线程的一个通用原则是用虚拟处理器的数目(Runtime.availableProcessors()的返回值)除以该系统上运行的应用程序数(假设应用程序的负荷和堆大小的情况相差不大)。如果负荷及java堆大小差异很大,那么为每个java应用设置不同权重,并据此设置并行线程数。

三、下一步

如果调优进行到这一步,仍无法达到应用程序的吞吐量要求,那就需要回顾应用程序的性能要求,修改应用程序、或者改变JVM的部署模式。一旦选择了一个方式,就可以继续新一轮的调优。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值