Java GC相关的文章有很多,本文只做概要性总结,主要内容来源于<深入理解Java虚拟机>。
对象存活性判定用于确定一个对象是死是活,死掉的对象则需要被垃圾回收。主要包括的方法:
可达性分析的基本思想是:
通过一系列的称为”GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链项链时,则证明此对象是不可用的。
在Java中有很多种类的对象可以作为GC Roots,例如类静态属性引用的对象。
确定了哪些对象是需要回收之后,就可以运用各种垃圾收集算法收集这些对象,例如直接回收内存,或者回收并移动整理内存。
主要包括:
如上,Java Hotspot虚拟机实现中将堆内存分为3大区域,即新生代、老年代、永久代。新生代中又分了eden、survivor0及survivor1,采用复制算法;老年代则采用标记清除及标记整理;永久代存放加载的类,类似于代码段,但同样会发生GC。
垃圾收集算法在实现时会略有不同,不同的实现称为垃圾收集器。不同的垃圾收集器适用的范围还不一样,有些收集器仅能用于新生代,有些用于老年代,有些新生代老年代都可以被使用。垃圾收集器可通过JVM启动参数指定。
上图中展示了新生代(年轻代)和老年代可用的各种垃圾收集器,图中的连线表示两种收集器可以配合使用。
JVM有些参数组合了各种收集器,例如:
UseConcMarkSweepGC
:使用ParNew + CMS + Serial Old收集器UseParallelGC
,运行在server模式下的默认值,使用Parallel Scavenge + Serial Old 收集器生产服务器一般会配置GC日志,以在故障时能够分析问题所在,一般的应用可配置以下JVM参数:
-XX:+UseParallelGC -XX:+DisableExplicitGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:./logs/gc.log
输出日志类似:
1456772.057: [GC [PSYoungGen: 33824K->96K(33920K)] 53841K->20113K(102208K), 0.0025050 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
1456863.534: [GC [PSYoungGen: 33824K->96K(33920K)] 53841K->20113K(102208K), 0.0020050 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
1456962.061: [GC [PSYoungGen: 33824K->128K(33920K)] 53841K->20145K(102208K), 0.0014150 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
1456772.057
,自JVM启动后的时间值GC
表示本次进行的是一次minor GC,即年轻代中的GCPSYoungGen
垃圾收集器类型,这里是Parallel Scavenge33824K->96K(33920K)
,收集前后新生代大小,33920K
为新生代总大小(eden+ 1 survivor)53841K->20113K(102208K)
,堆总大小及GC前后大小0.0025050 secs
,GC时停顿时间JVM GC相关的有一些策略值得注意: