JVM垃圾回收与内存调优

1.JVM垃圾回收

GC的基本原理:将内存中不再被引用的对象进行回收,GC中用于回收的方法称为收集器。垃圾:不再被引用的对象。

对新生代的对象的收集称为minor GC;
对旧生代的对象的收集称为Full GC;
程序中主动调用System.gc()的GC为Full GC

如何判断可回收对象
1、引用计数算法
每当一个地方引用它时,计数器+1;引用失效时,计数器-1;计数值=0——不可能再被引用。

2、可达性分析算法:
向图,树图,把一系列“GC Roots”作为起始点,从节点向下搜索,路径称为引用链,当一个对象到GC Roots没有任何引用链相连,即不可达时,则证明此对象时不可用的。

注:在Java中可作为GCRoots的对象:
1)虚拟机栈(栈帧中的本地变量表)中引用的对象;
2)方法区中类静态属性引用的对象;
3)方法区中常量引用的对象;
4)本地方法栈中JNI引用的对象。

内存泄漏

内存泄露的原因:1)全局集合;2)缓存;3)ClassLoader
检查List,map等集合对象是否有使用完后,未清除的问题。List、Map等集合对象会始终存有对对象的引用,使得对象不能被GC回收
程序中保留着对永远不再使用的对象的引用。因此这些对象不会被GC回收,却一直占用内存空间却毫无用处。即:1)对象是可达的;2)对象是无用的。满足这两个条件即可判定为内存泄漏。
内存溢出
检查代码有否有死循环或者递归调用
检查是否有大循环重复产生新对象实体
检查数据库查询中,是否有一次获取全部数据的查询。一般来说,如果一次取十万条记录,就可能引起内存溢出。

垃圾回收算法
分代收集算法中堆空间被分为新生代和老年代。因为新生代中对象的存活率比较低,所以一般采用复制算法,老年代的存活率一般比较高,一般使用”标记-清理”或者”标记-整理”算法进行回收。
垃圾收集器
serial垃圾收集器
1.整个扫描和复制过程采用单线程的垃圾收集器,能与 CMS 收集器配合
2.“Stop The World”,它进⾏垃圾收集时,必须暂停其他所有的⼯作线程,直到它收集结束。
3.适用与单CPU,新生代空间较小及对暂停时间要求不高的应用,是client默认的GC方式。
4.可以通过-XX:+UseSerialGC来强制指定
在这里插入图片描述
ParNew收集器
1.并⾏的 多线程收集,能与 CMS 收集器配合
2.Stop The World
3.-XX: ParallelGCThreads 参数来限制垃圾收集的线程数
4.多线程操作存在上下⽂切换的问题,所以建议将-XX: ParallelGCThreads设置成和CPU核数相 同,如果设置太多的话就会产⽣上下⽂切换消耗
在这里插入图片描述
Parallel Scavenge收集器
1.并行回收收集器,又称“吞吐量优先”收集器。⽬标是达到 可控制的吞吐(Throughput)
2.并⾏的多线程收集器,使用复制算法的收集器
3.-XX:MaxGCPauseMillis参数GC停顿时间,500MB ——>300MB,这个参数配置太⼩的话会发生频繁GC
4.-XX:GCTimeRatio参数,99%

Serial old收集器
单线程的垃圾收集器,使⽤"标记–整理"算法
Parallel old收集器
Parallel Scavenge收集器的老年代版本,使⽤多线程+标记整理算法
CMS (Concurrent Mark Sweep)收集器
1.以获取最短回收停顿时间为⽬标的收集器
2.基于“标记-清除”算法实现的
3.可以使用-XX:+UseConeMarkSweepGC指定
3.步骤流程
初始标记(CMS initial mark) -----标记⼀下 GC Roots 能直接关联到的对象,速度很快
并发标记(CMS concurrent mark --------并发标记阶段就是进行 GC RootsTracing 的过程
重新标记(CMS remark) -----------为了修正并发标记期间因用户程序导致标记产⽣变动的标 记录
并发清除(CMS concurrent sweep)
4.CMS垃圾收集器缺点
无法处理浮动垃圾,程序在进⾏并发清除阶段⽤户线程所产生的新垃圾
标记-清除导致空间碎⽚
在这里插入图片描述
G1收集器
1.基于“标记⼀整理”算法实现为主和Region之间采⽤复制算法实现的垃圾收集
2.非常精确地控制停顿
G1收集器可以在几乎不牺牲吞吐量的前提下完成低停顿的内存回收,这是由于它能够极力避免全区域的垃圾收集,之前的收集器进行收集的范围都是整个新生代或老年代,而G1将整个Java堆(包括新生代、老年代)划分为多个大小固定的独立区域(Region),并且跟踪这些区域里面的垃圾堆积程度,在后台维护一个优先列表,每次根据允许的收集时间,优先回收垃圾最多的区域(这就是Garbage First名称的由来)。区域划分、有优先级的区域回收,保证了G1收集器在有限的时间内可以获得最高的收集效率。
3.步骤流程
初始标记(Initial Marking) --标记⼀下 GC Roots 能直接关联到的对象
并发标记(Concurrent Marking)—从GC Root 开始对堆中对象进⾏可达性分析,找出存活 的对象,这阶段耗时较长,但可与⽤户程序并发执行
最终标记(Final Marking) —为了了修正在并发标记期间因用户程序继续运作而导致标记产⽣生 变动的那⼀部分标记记录。每个 Region 都有⼀个与之对应的 Remembered Set,虚拟机将这段时间对象变化记录在线程 Remembered Set Logs ⾥面,最终标记阶段需要把 Remembered Set Logs的数据合并到 Remembered Set 中
筛选回收(Live Data Counting and Evacuation)
4.通过-XX:G1HeapRegionSize指定分区大小
在这里插入图片描述
在这里插入图片描述

最后来讲一下垃圾回收流程。
1、新建的对象,大部分存储在Eden中
2、当Eden内存不够,就进行Minor GC释放掉不活跃对象;然后将部分活跃对象复制到Survivor中(如Survivor1),同时清空Eden区
3、当Eden区再次满了,将Survivor1中不能清空的对象存放到另一个Survivor中(如Survivor2),同时将Eden区中的不能清空的对象,复制到Survivor1,同时清空Eden区
4、重复多次(默认15次):Survivor中没有被清理的对象就会复制到老年区(Old)
5、当Old达到一定比例,则会触发Major GC释放老年代
6、当Old区满了,则触发一个一次完整的垃圾回收(Full GC)
7、如果内存还是不够,JVM会抛出内存不足,发生oom,内存泄漏。

5. 内存调优

调优目的:减少GC的频率尤其是Full GC的次数,过多的GC会占用很多系统资源影响吞吐量。特别要关注Full GC,因为它会对整个堆进行整理。

主要手段:JVM调优主要通过配置JVM的参数来提高垃圾回收的速度,合理分配堆内存各部分的比例。

导致Full GC的几种情况和调优策略:

旧生代空间不足
调优时尽量让对象在新生代GC时被回收、让对象在新生代多存活一段时间不要创建过大的对象及数组避免直接在旧生代创建对象
持久代(Pemanet Generation)空间不足
增大Perm Gen空间,避免太多静态对象
统计得到的GC后晋升到旧生代的平均大小大于旧生代剩余空间
控制好新生代和旧生代的比例
System.gc()被显示调用
垃圾回收不要手动触发,尽量依靠JVM自身的机制

堆内存比例不良设置会导致什么后果:

1)新生代设置过小

一是新生代GC次数非常频繁,增大系统消耗;二是导致大对象直接进入旧生代,占据了旧生代剩余空间,诱发Full GC

2)新生代设置过大

一是新生代设置过大会导致旧生代过小(堆总量一定),从而诱发Full GC;二是新生代GC耗时大幅度增加

一般说来新生代占整个堆1/3比较合适

3)Survivor设置过小

导致对象从eden直接到达旧生代,降低了在新生代的存活时间

4)Survivor设置过大

导致eden过小,增加了GC频率

另外,通过**-XX:MaxTenuringThreshold=n来控制新生代存活时间**,尽量让对象在新生代被回收

JVM提供两种较为简单的GC策略的设置方式:

1)吞吐量优先

JVM以吞吐量为指标,自行选择相应的GC策略及控制新生代与旧生代的大小比例,来达到吞吐量指标。这个值可由-XX:GCTimeRatio=n来设置

2)暂停时间优先

JVM以暂停时间为指标,自行选择相应的GC策略及控制新生代与旧生代的大小比例,尽量保证每次GC造成的应用停止时间都在指定的数值范围内完成。这个值可由-XX:MaxGCPauseRatio=n来设置

JVM常见配置

堆设置
-Xms:初始堆大小
-Xmx:最大堆大小
-XX:NewSize=n:设置年轻代大小
-XX:NewRatio=n:设置年轻代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
-XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5
-XX:MaxPermSize=n:设置持久代大小

垃圾回收统计信息
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:filename

参考:https://blog.csdn.net/hequan199411/article/details/81915884

发布了29 篇原创文章 · 获赞 0 · 访问量 1650

猜你喜欢

转载自blog.csdn.net/glamour2015/article/details/104241942