logo

从测试到上线如何分析JVM运行状况及合理优化?


prtyaa
prtyaa 2023-12-28 15:27:28 22585 赞同 1 反对 0
分类: 资源
1、开发好系统之后的预估性优化 自行估算系统每秒大概多少请求,每个请求会创建多少对象,占用多少内存,机器应该选用什么样的配置,年轻代应该给多少内存,Young GC触发的频率,对象进入老年代的速率,老年代应该给多少内存,Full GC触发的频率。 这些东西其实是可以根据你自己写的代码,大致合理的预估一下的。 在预估完成之后,就可以先给自己的系统设置一些初始性的JVM参数 比如堆内存大小,年轻代大小,Eden和Survivor的比例,老年代的大小,大对象的阈值,大龄对象进入老年代的阈值,等等。

然后把存活对象都放入第一个Survivor区域中,也就是S0区域

接着垃圾回收器就会直接回收掉Eden区里剩余的全部垃圾对象,在整个这个垃圾回收的过程中全程会进入Stop the Wold状态,也就 是暂停系统工作线程,系统代码全部停止运行,不允许创建新的对象

只有这样,才能让垃圾回收器专心工作,找出来存活对象,回收掉垃圾对象

一旦垃圾回收全部完毕之后,也就是存活对象都进入了Survivor区域,然后Eden区都清空了,那么Young GC执行完毕,此时系统恢复 工作,继续在Eden区里创建对象。

下一次如果Eden区满了,就会再次触发Young GC,把Eden区和S0区里的存活对象转移到S1区里去,然后直接清空掉Eden区和S0区 中的垃圾对象

当然这个过程中系统是禁止运行的,处于Stop the World状态

负责Young GC的垃圾回收器有很多种,但是常用的就是ParNew垃圾回收器,他的核心执行原理就如上所述,只不过他运行的时候是 基于多线程并发执行垃圾回收的,

2、对象什么时候进入老年代?

1、对象在年轻代里躲过15次垃圾回收,年龄太大了,进入老年代
2、对象太大了,超过了一定的阈值,直接进入老年代,不走年轻代
3、一次Young GC过后存活对象太多了,导致Survivor区域放不下了,这批对象会进入老年代
4、可能几次Young GC过后,Surviovr区域中的对象占用了超过50%的内存,此时会判断如果年龄1+年龄2+年龄N的对象总和超过 了Survivor区域的50%,此时年龄N以及之上的对象都进入老年代,这是动态年龄判定规则

上面4个条件就是最常见的对象进入老年代的情况,那种长期存活的躲过15次Young GC的对象毕竟是少数的,大对象一般在特殊情况 下会有,对于那种加载大量数据长时间处理以及高并发的场景,很容易导致Young GC后存活对象过多的。


3、老年代的GC是如何触发的?

1、老年代自身可以设置一个阈值,有一个JVM参数可以控制,一旦老年代内存使用达到这个阈值,就会触发Full GC,一般建议调节大一 些,比如92%

2、在执行Young GC之前,如果判断发现老年代可用空间小于了历次Young GC后升入老年代的平均对象大小的话,那么就会在Young GC之前触发Full GC,先回收掉老年代一批对象,然后再执行Young GC。

3、如果Young GC过后的存活对象太多,Survivor区域放不下,就要放入老年代,要是此时老年代也放不下,就会触发Full GC,回收老年 代一批对象,再把这些年轻代的存活对象放入老年代中


4、正常情况下的系统

正常情况下的系统的ygc的频率

一般在几分钟一次Young GC,或者几十分钟一次Young GC,一次耗时在几毫秒到 几十毫秒的样子,都是正常的。

正常情况下的系统的full gc的频率

正常的Full GC频率在几十分钟一次,或者几个小时一次,这个范围内都是正常的,一次耗时应该在几百毫秒的样子。 所以大家如果观察自己线上系统就是这个性能表现,基本上问题都不太大。 当然,实际线上系统很多时候回遇到一些JVM性能问题,就是Full GC过于频繁,每次还耗时很多的情况,此时就需要一些优化了。

然后把存活对象都放入第一个Survivor区域中,也就是S0区域

接着垃圾回收器就会直接回收掉Eden区里剩余的全部垃圾对象,在整个这个垃圾回收的过程中全程会进入Stop the Wold状态,也就 是暂停系统工作线程,系统代码全部停止运行,不允许创建新的对象

只有这样,才能让垃圾回收器专心工作,找出来存活对象,回收掉垃圾对象

一旦垃圾回收全部完毕之后,也就是存活对象都进入了Survivor区域,然后Eden区都清空了,那么Young GC执行完毕,此时系统恢复 工作,继续在Eden区里创建对象。

下一次如果Eden区满了,就会再次触发Young GC,把Eden区和S0区里的存活对象转移到S1区里去,然后直接清空掉Eden区和S0区 中的垃圾对象

当然这个过程中系统是禁止运行的,处于Stop the World状态

负责Young GC的垃圾回收器有很多种,但是常用的就是ParNew垃圾回收器,他的核心执行原理就如上所述,只不过他运行的时候是 基于多线程并发执行垃圾回收的,

2、对象什么时候进入老年代?

1、对象在年轻代里躲过15次垃圾回收,年龄太大了,进入老年代
2、对象太大了,超过了一定的阈值,直接进入老年代,不走年轻代
3、一次Young GC过后存活对象太多了,导致Survivor区域放不下了,这批对象会进入老年代
4、可能几次Young GC过后,Surviovr区域中的对象占用了超过50%的内存,此时会判断如果年龄1+年龄2+年龄N的对象总和超过 了Survivor区域的50%,此时年龄N以及之上的对象都进入老年代,这是动态年龄判定规则

上面4个条件就是最常见的对象进入老年代的情况,那种长期存活的躲过15次Young GC的对象毕竟是少数的,大对象一般在特殊情况 下会有,对于那种加载大量数据长时间处理以及高并发的场景,很容易导致Young GC后存活对象过多的。


3、老年代的GC是如何触发的?

1、老年代自身可以设置一个阈值,有一个JVM参数可以控制,一旦老年代内存使用达到这个阈值,就会触发Full GC,一般建议调节大一 些,比如92%

2、在执行Young GC之前,如果判断发现老年代可用空间小于了历次Young GC后升入老年代的平均对象大小的话,那么就会在Young GC之前触发Full GC,先回收掉老年代一批对象,然后再执行Young GC。

3、如果Young GC过后的存活对象太多,Survivor区域放不下,就要放入老年代,要是此时老年代也放不下,就会触发Full GC,回收老年 代一批对象,再把这些年轻代的存活对象放入老年代中


4、正常情况下的系统

正常情况下的系统的ygc的频率

一般在几分钟一次Young GC,或者几十分钟一次Young GC,一次耗时在几毫秒到 几十毫秒的样子,都是正常的。

正常情况下的系统的full gc的频率

正常的Full GC频率在几十分钟一次,或者几个小时一次,这个范围内都是正常的,一次耗时应该在几百毫秒的样子。 所以大家如果观察自己线上系统就是这个性能表现,基本上问题都不太大。 当然,实际线上系统很多时候回遇到一些JVM性能问题,就是Full GC过于频繁,每次还耗时很多的情况,此时就需要一些优化了。

如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!

评价 1 条
  • zlj141319 2024-03-01 08:06
    赞同

    性能优化没有尽头

prtyaa
粉丝 1 资源 1949 + 关注 私信
最近热门资源
工业防火墙为啥不走寻常路?  637
窃密软件无孔不入?迪普科技防护策略为隐私数据筑牢防线  279
最近下载排行榜
工业防火墙为啥不走寻常路? 0
窃密软件无孔不入?迪普科技防护策略为隐私数据筑牢防线 0
作者收入月榜
1

prtyaa 收益363.15元

2

风晓 收益207.84元

3

IT-feng 收益198.17元

4

zlj141319 收益178.22元

5

777 收益172.06元

6

1843880570 收益171.31元

7

信创来了 收益103.8元

8

Fhawking 收益99.6元

9

克里斯蒂亚诺诺 收益91.08元

10

技术-小陈 收益79.05元

请使用微信扫码