java gc 总结

垃圾查找

1.基于计数器

对象有引用计数,计数为0的,可以被收集

2.基于有向图

从gc root(栈、静态变量、JNI 变量)遍历,能访问的对象,不用被收集,其他的,可以被收集

因为计数器不能解决 互相引用的问题,一般都不使用这种算法

目前商业JVM 都是使用有向图算法 来找垃圾

找到了垃圾,下面开始要回收了

垃圾回收

1.基于复制

把存活对象复制到其他区域,当前区域整体释放

2.基于标记-清除

先标记可回收对象,再释放被回收对象,这种情况下,有内存碎片

3.基于标记-整理

先标记可回收对象,再把不可回收对象 压缩到当前回收域的一端,整体释放当前回收域剩下的区域, 能防止内存碎片

以上这3个算法是基础算法

还有一些具体的加速回收速度,减小停顿时间,增加吞吐量的算法

1.内存分代

不同存活时间的对象,放到不同的分代区域中,新生代/老生代

2.内存分区域

每个代中内存 再分为多个大小相同的区,按区收集垃圾,能减少碎片整理时间

3.执行分阶段

垃圾回收过程分为几个不同的阶段,能减小系统暂停时间

比如先标记垃圾对象,标记完后,发现暂停时间已经比较长了,那就先暂停执行GC,让工作线程先工作,等一段时间后,在执行下一阶段的GC流程

具体垃圾收集器,都是实现了上面某些算法

1.serial gc

串行收集器,单线程执行,追求低停顿时间,用于新生代收集

2.parnew gc

多线程版本的串行收集器,多线程执行,追求低停顿时间,用于新生代收集

3.parallel scavenge gc

并行收集器,多线程执行,追求高吞吐量,用于新生代收集

4.serial old gc

串行老生代收集器,单线程执行,追求低停顿时间,用于老生代收集

5.parallel old gc

并行老生代收集器,多线程执行,追求高吞吐量,用于老生代收集

6.cms gc

并发收集器,多线程执行,追求低停顿时间,用于老生代收集

7.g1 gc

g1收集器,多线程执行,追求低停顿时间,也追求高吞吐量,有点实时、高吞吐量的意思,既用于新生代收集,也用于老生代收集

这个GC 兼顾了停顿时间和吞吐量,是未来GC的方向,目前这个GC稳定性据说还有待验证,如果将来稳定了,大伙都用这个GC就好了

JVM参数和GC收集器的对应关系

UseSerialGC

虚拟机运行在Client 模式下的默认值,打开此开关后,使用Serial + Serial Old 的收集器组合进行内存回收

UseParNewGC

打开此开关后,使用ParNew + Serial Old 的收集器组合进行内存回收

UseConcMarkSweepGC

打开此开关后,使用ParNew + CMS + Serial Old 的收集器组合进行内存回收。

Serial Old 收集器将作为CMS 收集器出现Concurrent Mode Failure失败后的后备收集器使用

UseParallelGC

虚拟机运行在Server 模式下的默认值,打开此开关后,使用ParallelScavenge + Serial Old(PS MarkSweep)的收集器组合进行内存回收

UseParallelOldGC

打开此开关后,使用Parallel Scavenge + Parallel Old 的收集器组合进行内存回收

UseG1GC

打开此开关后,使用G1回收器 回收新生代和老生代内存

注意:指定GC回收器时 一般需要为新生代和老生代分别指定GC回收器,不过有些参数有默认行为,指定了一个参数,就相当于同时指定了 新/老 GC

默认情况下,老生代GC回收器会对pem space(永久代)进行回收,也就是发生full gc(major gc)时,会同时收集老生代和持久代的垃圾对象

GC优化主要针对垃圾回收这些具体算法来进行的

1.不管使用哪种GC,都会导致系统停止响应(stop-the-world),只是时间长短而已,要考虑响应时间和不丢包(UDP)

2.多核CPU尽量使用多线程GC,来减少停顿时间及提高吞吐量

3.吞吐量和停顿时间,一般是个矛盾体,追求吞吐量大,停顿时间就会长;追求停顿时间,吞吐量就小;看应用追求哪个指标,选择相应的算法

内存优化

不仅包括GC优化,也包括内存参数优化

1.内存性能参数优化,包括堆大小等等参数

2.GC优化

JVM优化

1.CPU

2.内存

3.IO

java性能调优

JVM性能分析(找瓶颈\找BUG)

JVM优化

代码优化/bug

操作系统优化

硬件(这个很少涉及)