JVM调优

本文围绕JVM调优展开,介绍了减少全局变量和大对象使用、设置堆大小、选择合适垃圾回收器等调优方法,探讨了年轻代和年老代大小设置的影响及选择依据,还给出线程堆栈设置建议。此外,通过三个案例分析了JVM内存控制、直接内存溢出及GC停顿等问题及解决办法。

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

JVM调优:

1、 减少使用全局变量和大对象

2、设置新生代的大小和老年代的大小(默认堆最大物理内存的1/4)

3、选择合适的垃圾回收器(如果回收停顿时间优先的可以采用(parnew和CMS(标记清除,会有内存碎片,效率高)),如果吞吐量优先可以采用,parallel Scavenge)(复制算法)和parallel Old(标记整理,效率低))

4、 堆栈大小默认为1M。可以后期优化

(1)针对JVM堆的设置,一般可以通过-Xms -Xmx限定其最小、最大值, 避免 JVM 反复重新申请内存,为了防止垃圾收集器在最小、最大之间收缩堆而产生额外的时间,我们通常把最大、最小设置为相同的值

   (2)年轻代和年老代将根据默认的比例(1:2)分配堆内存。

   (3)年轻代和年老代设置多大才算合理?这个我问题毫无疑问是没有答案的,否则也就不会有调优。我们观察一下二者大小变化有哪些影响

  • 更大的年轻代必然导致更小的年老代,大的年轻代会延长普通GC的周期,但会增加每次GC的时间;小的年老代会导致更频繁的Full GC
  • 更小的年轻代必然导致更大年老代,小的年轻代会导致普通GC很频繁,但每次的GC时间会更短;大的年老代会减少Full GC的频率
  • 如何选择应该依赖应用程序对象生命周期的分布情况:如果应用存在大量的临时对象,应该选择更大的年轻代;如果存在相对较多的持久对象,年老代应该适当增大。但很多应用都没有这样明显的特性,在抉择时应该根据以下两点:(A)本着Full GC尽量少的原则,让年老代尽量缓存常用对象,JVM的默认比例1:2也是这个道理 (B)通过观察应用一段时间,看其他在峰值时年老代会占多少内存,在不影响Full GC的前提下,根据实际情况加大年轻代,比如可以把比例控制在1:1。但应该给年老代至少预留1/3的增长空间

  (4)在配置较好的机器上(比如多核、大内存),可以为年老代选择并行收集算法: -XX:+UseParallelOldGC ,默认为Serial收集

  (5)线程堆栈的设置:每个线程默认会开启1M的堆栈,用于存放栈帧、调用参数、局部变量等,对大多数应用而言这个默认值太了,一般256K就足用。理论上,在内存不变的情况下,减少每个线程的堆栈,可以产生更多的线程,但这实际上还受限于操作系统。

案例1:

    控制JVM内存的大小,过大的堆会造成GC时间增长。使用超大的堆的前提是,有把握把应用程序的FullGC频率控制的足够低,至少低到不会影响用户使用,譬如十几个小时乃至一天才会出现一次FullGC。控制FullGC频率的关键是看应用中绝大多数对象能否符合“ 朝生夕死”的原则。即大多数对象的生产时间不应该太长,尤其是不能用成批量的、长生存时间的大对象产生。

案例2:

    直接内存溢出,直接内存不能像新生代和老年代那样,发现空间不足了就通知收集器进行垃圾回收,它只能等待老年代满了之后FullGC,然后顺便的帮它清理掉内存的废弃对象。

案例3:

    业务要去每10分钟加载一个约80M的数据文件到内存进行数据分析,这些数据会在内存中形成超过100完个HashMap Entry,这段时间MinorGC就会造成500毫秒的停顿,80M的数据会将Eden区域填满,GC发生之后,新生代绝大部分对象依然存活,如果采用复制算法,这个算法的高效是建立在大部分对象都是朝生夕死的特性上,如果存活对象太多,将把这些对象复制到Survivor。解决方式:1、通过更改程序。2、从GC调优的角度,将Survivor

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值