01-014 jvm垃圾回收调优

调优领域

1.内存
2.锁竞争
3.CPU占用
4.io

确定目标

Hotspot:
科学运算:高吞吐量
互联网项目:响应时间
后选择合适的回收器
CMS、G1(低延迟,吞吐量可调,JDK9)、ZGC(jdk12):低延迟
ParallelGC:高吞吐量
扩展:Zing:虚拟机,0停顿

最快的GC是不发生GC

查看full GC前后的内存占用,考虑下面几个问题
1.数据是不是太多?
2.数据表示是否太臃肿?
要什么查什么,对象大小Java中最小的object 16字节 Integer 24字节 int 4字节,能用基本类型就不要用包装类型
3.是否存在内存泄露?
static Map map
软引用、弱引用代替
第三方缓存实现:如Redis不受垃圾回收影响

新生代调优

1.新生代的特点
①所有的new 操作的内存分配非常廉价,new 伊甸园分配非常快
TLAB Thread-local allocation buffer(优先分配到伊甸园私有区域)
每个线程用自己私有的伊甸园内存进行内存分配,多个线程不会产生干扰;
②死亡对象的回收代价是零;
③大部分对象用过即死;
④minor GC的时间远远低于full GC(差1-2个数量级)。
新生代的优化空间更大一些

2.新生代越大越好吗?
空间太大,回收时间变长,老年代空间过少,容易触发full GC。
Oracle建议:young generation 占堆的25%-50%。
新生代尽可能大,新生代垃圾回收用复制算法,主要时间用来复制,但是存活的对象非常少,所以复制时间耗时但相对较短,标记时间和复制时间相比显得很少。
新生代能容纳所有【并发量*(一次请求响应产生的对象)】的数据

3.幸存区分配规则
①幸存区大到能保留【当前活跃对象+需要晋升对象】;
(如果幸存区小,存活时间短的晋升到老年代了,会延长对象存活时间,没必要)
②晋升阈值配置得当,让长时间存活的对象尽快晋升
在幸存区来回复制,浪费时间
最大晋升阈值:-XX:MaxTenuringThreshold = threshold
显示幸存区对象分配信息:-XX:+PrintTenuringDistribution

4.老年代调优
以CMS为例
1.CMS老年代内存越大越好,浮动垃圾导致内存不足会造成CMS并发失败,退化为serialOld 串行,效率很低。
2.先尝试不调优,运行一段时间没有full GC,那么系统应该没什么问题,即使发生了full GC ,先尝试新生代调优
3.观察发生fullGC时老年代内存占用,将老年代内存预设调大1/4-1/3,
-XX:CMSInitiatingOccupancyFraction = percent
值越低触发full GC越早(一般设置为75%-80%)

5.案例
①full GC 和minor GC特别频繁
分析:空间紧张,新生代幸存区晋升阈值变低,很多生存周期短的对象晋升到老年代。
解决:增大新生代内存空间,分配给幸存区空间增大,晋升阈值增大。
②请求高峰期发生full GC,单次暂停时间特别长(CMS)
分析:查看GC日志,重新标记阶段时间长,因为扫描整个内存(新生代+老年代)
解决:重新标记前对新生代的对象做一次垃圾清理,存活对象少了,重新标记时查找标记对象变少
-XX:+CMSScavengeBeforeRemark
③老年代内存充裕下,发生full GC(CMS jdk1.7)
分析:1.7前永久代作为方法区的实现,永久代空间不足会触发full GC,1.8元空间是操作系统的内存空间,垃圾回收不受Java控制
解决:增大永久代的初始值和最大值

学习整理于解密JVM.

发布了53 篇原创文章 · 获赞 0 · 访问量 391

猜你喜欢

转载自blog.csdn.net/weixin_40778497/article/details/103622821
今日推荐