算法分成标记和清除两个阶段,先标记出要回收的对象,然后统一回收这些对象。形如:
优点:
简单
缺点是:
效率不高,标记和清除的效率都不高
标记清除后会产生大量不连续的内存碎片,从而导致在分配大对象时触发GC
把内存分成两块完全相同的区域,每次使用其中一块,当一块使用完了,就把这块上还存活的对
象拷贝到另外一块,然后把这块清除掉,目前大部分商业虚拟机都采用这种算法来回收新生代。形如
由于复制算法在存活对象比较多的时候,效率较低,且有空间浪费,因此老年代一般不会选用复制算法,老年代多选用标记整理算法。
标记过程跟标记清除一样,但后续不是直接清除可回收对象,而是让所有存活对象都向一端移动,然后直接清除边界以外的内存。形如:
收集算法只是内存回收的方法,垃圾收集器就来具体实现这些这些算法并实现内存回收。不同厂商、不同版本的虚拟机实现差别很大,HotSpot中包含的收集器如下图所示:
1:是一个单线程的收集器,在垃圾收集时,会Stop-the-World
2:优点是简单,对于单cpu,由于没有多线程的交互开销,可能更高效,是默认的Client模式下的新生代收集器
3:使用-XX:+UseSerialGC来开启会使用:Serial + Serial Old 的收集器组合
4:新生代Serial使用复制算法,老年代Serial Old 使用标记-整理算法
GC日志实例:
[GC (Allocation Failure) [DefNew: 640K->64K(704K), 0.0024945 secs] 640K->488K(1984K), 0.0025664 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 702K->63K(704K), 0.0020210 secs] 1127K->570K(1984K), 0.0020686 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 628K->60K(704K), 0.0014406 secs] 1134K->829K(1984K), 0.0014826 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 671K->0K(704K), 0.0015055 secs][Tenured: 1429K->1429K(1472K), 0.0038983 secs] 1440K->1429K(2176K), [Metaspace: 3206K->3206K(1056768K)], 0.0054827 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [DefNew: 1017K->0K(1152K), 0.0013329 secs][Tenured: 2429K->2429K(2576K), 0.0031020 secs] 2447K->2429K(3728K), [Metaspace: 3206K->3206K(1056768K)], 0.0045146 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [DefNew: 1040K->1040K(1216K), 0.0000219 secs][Tenured: 2429K->2730K(2752K), 0.0035755 secs] 3470K->3430K(3968K), [Metaspace: 3206K->3206K(1056768K)], 0.0036585 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [Tenured: 2730K->2701K(2752K), 0.0044666 secs] 3849K->3801K(3968K), [Metaspace: 3206K->3206K(1056768K)], 0.0045212 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[Full GC (Allocation Failure) [Tenured: 2701K->2701K(2752K), 0.0031365 secs] 3801K->3801K(3968K), [Metaspace: 3206K->3206K(1056768K)], 0.0031855 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
1:ParNew收集器其实就是Serial收集器的多线程版本。它使用多线程来进行垃圾回收。
2:在并发能力好的CPU环境里,它停顿的时间要比串行收集器短;但对于单cpu或并发能力较弱的CPU,由于多线 程的交互开销,可能比串行回收器更差
3:是Server模式下首选的新生代收集器,且能和CMS收集器配合使用
4:使用-XX:+UseParNewGC来开启会使用:ParNew + Serial Old的收集器组合
5:-XX:ParallelGCThreads:指定线程数,最好与CPU数量一致
6:使用复制算法
GC日志实例:
GC (Allocation Failure) [ParNew: 640K->64K(704K), 0.0012610 secs] 640K->506K(1984K), 0.0013403 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew: 702K->63K(704K), 0.0008789 secs] 1145K->605K(1984K), 0.0009153 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew: 627K->63K(704K), 0.0006648 secs] 1169K->909K(1984K), 0.0007063 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew: 673K->22K(704K), 0.0005780 secs][Tenured: 1493K->1493K(1664K), 0.0026303 secs] 1519K->1493K(2368K), [Metaspace: 3206K->3206K(1056768K)], 0.0034575 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew: 937K->105K(1152K), 0.0006858 secs] 2431K->2399K(3644K), 0.0007502 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew: 1123K->1123K(1152K), 0.0000196 secs][Tenured: 2293K->2393K(2492K), 0.0041983 secs] 3417K->3394K(3644K), [Metaspace: 3206K->3206K(1056768K)], 0.0042940 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [Tenured: 2694K->2694K(2752K), 0.0028808 secs] 3794K->3794K(3968K), [Metaspace: 3206K->3206K(1056768K)], 0.0029321 secs] [Times: user=0.02 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [Tenured: 2694K->2701K(2752K), 0.0047404 secs] 3794K->3701K(3968K), [Metaspace: 3206K->3206K(1056768K)], 0.0047801 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [Tenured: 2701K->2701K(2752K), 0.0029718 secs] 3801K->3801K(3968K), [Metaspace: 3206K->3206K(1056768K)], 0.0030227 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Allocation Failure) [Tenured: 2701K->2701K(2752K), 0.0043294 secs] 3801K->3801K(3968K), [Metaspace: 3206K->3206K(1056768K)], 0.0043789 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
是一个应用于新生代的、使用复制算法的、并行的收集器,跟ParNew很类似,但更关注吞吐量
(CPU吞吐量就是运行应用代码的时间/总运行时间,这种收集器能最高效率的利用CPU,适合运行后台
应用)
1:使用-XX:+UseParallelGC来开启新生代Parallel Scavenge收集器
2:使用-XX:+UseParallelOldGC来开启老年代使用Parallel Old收集器,使用Parallel Scavenge +
Parallel Old的收集器组合
3:-XX:GCTimeRatio:指定运行应用代码的时间占总时间的比例,默认99,即1%的时间用来进行垃圾收集
4:-XX:MaxGCPauseMillis:设置GC的最大停顿时间
5:新生代Parallel Scavenge使用复制算法,老年代Parallel Old使用标记-整理算法
GC日志实例:
[GC (Allocation Failure) [PSYoungGen: 511K->488K(1024K)] 511K->496K(1536K), 0.0009177 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 1000K->504K(1024K)] 1008K->584K(1536K), 0.0020611 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 1014K->504K(1024K)] 1094K->656K(1536K), 0.0021773 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 917K->488K(1024K)] 1069K->1000K(2048K), 0.0008948 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 996K->504K(1024K)] 1508K->1548K(2560K), 0.0008398 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Ergonomics) [PSYoungGen: 504K->0K(1024K)] [ParOldGen: 1044K->1419K(2560K)] 1548K->1419K(3584K), [Metaspace: 3205K->3205K(1056768K)], 0.0096908 secs] [Times: user=0.03 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [PSYoungGen: 512K->428K(1024K)] 1931K->2047K(3584K), 0.0004567 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [PSYoungGen: 936K->496K(1024K)] 2555K->2523K(3584K), 0.0005715 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[Full GC (Ergonomics) [PSYoungGen: 496K->0K(1024K)] [ParOldGen: 2027K->2419K(2560K)] 2523K->2419K(3584K), [Metaspace: 3205K->3205K(1056768K)], 0.0052797 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[Full GC (Ergonomics) [PSYoungGen: 508K->500K(1024K)] [ParOldGen: 2419K->2418K(2560K)] 2928K->2919K(3584K), [Metaspace: 3205K->3205K(1056768K)], 0.0081769 secs] [Times: user=0.03 sys=0.00, real=0.01 secs]
[Full GC (Ergonomics) [PSYoungGen: 500K->500K(1024K)] [ParOldGen: 2518K->2518K(2560K)] 3019K->3019K(3584K), [Metaspace: 3205K->3205K(1056768K)], 0.0032858 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
1:分为四个阶段
初始标记:只标记GC Roots能直接关联到的对象
并发标记:进行GC Roots Tracing的过程
重新标记:修正并发标记期间,因程序运行导致标记发生变化的那一部分对象
并发清除:并发回收垃圾对象
2:在初始标记和重新标记两个阶段还是会发生Stop-the-World
3:使用标记清除算法,也是一个使用多线程并发收集的垃圾收集器
4:最后的重置线程,指的是清空跟收集相关的数据并重置,为下一次收集做准备
5:优点:低停顿、并发执行
6:缺点:
(1)并发执行,对CPU资源压力大
(2)无法处理 在处理过程中 产生的垃圾,可能导致FGC
(3)采用的标记清除算法会导致大量碎片,从而在分配大对象是可能触发FGC
7:可设置的参数有:
-XX:+UseConcMarkSweepGC:使用ParNew + CMS + Serial Old的收集器组合,Serial Old将作为CMS出错的后 备收集器
-XX:+ParallelCMSThreads:设定CMS的线程数量,默认是(ParallelGCThreads+3)/4
-XX:+CMSInitiatingOccupancyFraction:设置CMS收集器在老年代空间被使用多少后触发回收,默认68%
-XX:+UseCMSCompactAtFullCollection:设置CMS收集器在完成垃圾收集后是否要进行一次内存碎片的
整理,默认是开启的
-XX:+CMSFullGCsBeforeCompaction:设定进行多少次CMS垃圾收集后,进行一次内存整理
-XX:+CMSClassUnloadingEnabled:允许对类元数据进行收集
-XX:+UseCMSInitiatingOccupancyOnly:表示只在到达阀值的时候,才进行CMS收集
GC日志实例:
[GC (Allocation Failure) [ParNew: 1081K->128K(1216K), 0.0030805 secs] 1081K->564K(2112K), 0.0031878 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew: 1208K->127K(1216K), 0.0010856 secs] 1644K->1189K(2688K), 0.0011187 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (CMS Initial Mark) [1 CMS-initial-mark: 1062K(1472K)] 1289K(2688K), 0.0003326 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[CMS-concurrent-mark-start]
[GC (Allocation Failure) [ParNew: 1146K->45K(1216K), 0.0011206 secs] 2208K->2185K(3840K), 0.0011612 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [ParNew: 1064K->1064K(1216K), 0.0000359 secs][CMS[CMS-concurrent-mark: 0.001/0.003 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
(concurrent mode failure): 2140K->2529K(2624K), 0.0052513 secs] 3205K->3129K(3840K), [Metaspace: 3206K->3206K(1056768K)], 0.0053702 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[Full GC (Allocation Failure) [CMS: 2729K->2706K(2752K), 0.0054262 secs] 3849K->3806K(3968K), [Metaspace: 3206K->3206K(1056768K)], 0.0054999 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[Full GC (Allocation Failure) [CMS: 2706K->2706K(2752K), 0.0037150 secs] 3806K->3806K(3968K), [Metaspace: 3206K->3206K(1056768K)], 0.0037640 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (CMS Initial Mark) [1 CMS-initial-mark: 2706K(2752K)] 3806K(3968K), 0.0001726 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[CMS-concurrent-mark-start]
[CMS-concurrent-mark: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[CMS-concurrent-preclean-start]
[CMS-concurrent-preclean: 0.001/0.001 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
G1是一款面向服务端应用的收集器,与其它收集器相比,具有如下特点:
1:G1能充分利用多CPU、多核环境硬件优势,尽量缩短STW
2:G1仍然采用分代的思想,对存活时间较长,经过多次GC仍存活的对象,有不同的处理方式,以获取更好的收集效果
3:G1整体上采用标记-整理算法,局部是通过复制算法,不会产生内存碎片。
4:G1把内存划分成多个独立的区域(Region),保留了新生代和老年代,但它们不再是物理隔离的,而是一部分Region 的集合,且不需要Region是连续的
5:G1的停顿可预测,能明确制定在一个时间段内,消耗在垃圾收集上的时间不能超过多长时间。
6:G1跟踪各个Redion里面垃圾堆的价值大小,在后台维护一个优先列表,每次根据允许的时间来回收价值最大的区 域,从而保证在有限时间内的高效收集
7:跟CMS类似,也分为四个阶段
初始标记:只标记GC Roots能直接关联到的对象
并发标记:进行GC Roots Tracing的过程
最终标记:修正并发标记期间,因程序运行导致标记发生变化的那一部分对象
筛选回收:根据时间来进行价值最大化的回收
8:使用和配置G1
a:-XX:+UseG1GC:开启G1
b:-XX:+MaxGCPauseMillis=n:最大GC停顿时间,这是个软目标,
JVM将尽可能(但不保证)停顿小于这个时间
c:-XX:+InitiatingHeapOccupancyPercent=n:堆占用了多少的时候就触发GC,默认为45
d:-XX:NewRatio=n:默认为2
e:-XX:SurvivorRatio=n:默认为8
f:-XX:MaxTenuringThreshold=n:新生代到老年代的岁数,默认是15
g:-XX:ParallelGCThreads=n:并行GC的线程数,默认值会根据平台不同而不同
h:-XX:ConcGCThreads=n:并发GC使用的线程数
i:-XX:G1ReservePercent=n:设置作为空闲空间的预留内存百分比,以降低目标空间溢出的
风险,默认值是10%
j:-XX:G1HeapRegionSize=n:设置的G1区域的大小。值是2的幂,范围是1MB到32MB。目标是
根据最小的 Java 堆大小划分出约 2048 个区域。
GC日志实例:
[GC pause (G1 Evacuation Pause) (young), 0.0014859 secs]
[Parallel Time: 1.2 ms, GC Workers: 4]
[GC Worker Start (ms): Min: 185.0, Avg: 185.0, Max: 185.0, Diff: 0.0]
[Ext Root Scanning (ms): Min: 0.3, Avg: 0.4, Max: 0.5, Diff: 0.2, Sum: 1.6]
[Update RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
[Processed Buffers: Min: 0, Avg: 0.0, Max: 0, Diff: 0, Sum: 0]
[Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
[Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
[Object Copy (ms): Min: 0.5, Avg: 0.6, Max: 0.7, Diff: 0.2, Sum: 2.5]
[Termination (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
[Termination Attempts: Min: 1, Avg: 1.3, Max: 2, Diff: 1, Sum: 5]
[GC Worker Other (ms): Min: 0.1, Avg: 0.1, Max: 0.1, Diff: 0.1, Sum: 0.4]
[GC Worker Total (ms): Min: 1.1, Avg: 1.1, Max: 1.1, Diff: 0.0, Sum: 4.4]
[GC Worker End (ms): Min: 186.1, Avg: 186.1, Max: 186.1, Diff: 0.0]
[Code Root Fixup: 0.0 ms]
[Code Root Purge: 0.0 ms]
[Clear CT: 0.0 ms]
[Other: 0.3 ms]
[Choose CSet: 0.0 ms]
[Ref Proc: 0.1 ms]
[Ref Enq: 0.0 ms]
[Redirty Cards: 0.0 ms]
[Humongous Register: 0.0 ms]
[Humongous Reclaim: 0.0 ms]
[Free CSet: 0.0 ms]
[Eden: 1024.0K(1024.0K)->0.0B(1024.0K) Survivors: 0.0B->1024.0K Heap: 1024.0K(2048.0K)->664.1K(2048.0K)]
[Times: user=0.00 sys=0.00, real=0.00 secs]