Java的垃圾回收机制详细介绍
垃圾回收算法思想
- 引用计数
- 复制拷贝:将内存区域分为两块,一块存储对象,如果对象满了,那么将存活的对象移动到另外的一块区域中。(新生代中)
- 标记清除:先标记、然后再整理。会存在效率低下的问题,存在内存碎片。
- 标记整理:将存活的对象移动到另外一块区域,然后清除非存活的对象区域。(老年代中)
-XX:+UseSerialGC
只使用一个线程进行垃圾的回收。会暂停所有的用户线程。不适合服务器环境,类似于餐厅需要打扫垃圾,需要请客人出去,然后开始打扫垃圾。主要的收集器:Serial(Young) SerialOld(Old)
查看是否生效
开启后会使用Serial(Young区间,一个线程)+Serial Old(Old区用,一个线程)的收集器组合
表示:新生代、老年代都会使用串行回收收集器,新生代使用复制算法、老年代使用标记-整理算法。
测试
public static void main(String[] args) throws InterruptedException { String str="123"; while(true) { str+=str+new Random().nextInt(7777)+new Random().nextInt(8888); str.intern(); } }
添加JVM参数
-Xms10m -Xmx10m -XX:+PrintGCDetails -XX:+PrintCommandLineFlags -XX:+UseSerialGC
打印结果
-XX:InitialHeapSize=10485760 -XX:MaxHeapSize=10485760 -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseSerialGC
[GC (Allocation Failure) [$\color{#FF0000}{DefNew}$: 2677K->320K(3072K), 0.0051447 secs] 2677K->1266K(9920K), 0.0537604 secs] [Times: user=0.00 sys=0.00, real=0.05 secs]
[GC (Allocation Failure) [DefNew: 2836K->0K(3072K), 0.0050224 secs] 3782K->2673K(9920K), 0.0051220 secs] [Times: user=0.02 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 1461K->0K(3072K), 0.0034208 secs] 4134K->4080K(9920K), 0.0035157 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 1407K->0K(3072K), 0.0021344 secs] 5487K->5487K(9920K), 0.0022028 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC (Allocation Failure) [DefNew: 1460K->1460K(3072K), 0.0000475 secs][Tenured: 5487K->3375K(6848K), 0.0076576 secs] 6948K->3375K(9920K), [Metaspace: 2697K->2697K(1056768K)], 0.0083059 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
[GC (Allocation Failure) [$\color{#FF0000}{DefNew}$: 53K->0K(3072K), 0.0006282 secs][$\color{#FF0000}{Tenured}$: 6189K->4782K(6848K), 0.0062502 secs] 6242K->4782K(9920K), [Metaspace: 2697K->2697K(1056768K)], 0.0070148 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
[Full GC (Allocation Failure) [Tenured: 4782K->4765K(6848K), 0.0074241 secs] 4782K->4765K(9920K), [Metaspace: 2697K->2697K(1056768K)], 0.0075259 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOfRange(Unknown Source)
at java.lang.String.<init>(Unknown Source)
at java.lang.StringBuilder.toString(Unknown Source)
at com.test01.TextMain.main(TextMain.java:149)
Heap
def new generation total 3072K, used 108K [0x00000000ff600000, 0x00000000ff950000, 0x00000000ff950000)
eden space 2752K, 3% used [0x00000000ff600000, 0x00000000ff61b3c8, 0x00000000ff8b0000)
from space 320K, 0% used [0x00000000ff900000, 0x00000000ff900000, 0x00000000ff950000)
to space 320K, 0% used [0x00000000ff8b0000, 0x00000000ff8b0000, 0x00000000ff900000)
tenured generation total 6848K, used 4765K [0x00000000ff950000, 0x0000000100000000, 0x0000000100000000)
the space 6848K, 69% used [0x00000000ff950000, 0x00000000ffdf75c0, 0x00000000ffdf7600, 0x0000000100000000)
Metaspace used 2727K, capacity 4490K, committed 4864K, reserved 1056768K
class space used 299K, capacity 386K, committed 512K, reserved 1048576K
-XX:+UseSerialOldGC
已经被优化掉了,在Java8中配置这个常数会执行失败。
-XX:+UseParNewGC
多个线程并行的垃圾回收器,用户线程是暂停的。适合允许中途暂停,适合弱交互的场景。性能比串行好。
主要的收集器:ParNew(Young) Serial Old(Old)新生代使用复制算法,老年代使用标记-整理算法。
-XX:InitialHeapSize=10485760 -XX:MaxHeapSize=10485760 -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParNewGC [GC (Allocation Failure) [ParNew: 2676K->319K(3072K), 0.0011021 secs] 2676K->1285K(9920K), 0.0011538 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [ParNew: 2833K->49K(3072K), 0.0011102 secs] 3800K->2757K(9920K), 0.0011778 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [ParNew: 1509K->24K(3072K), 0.0009669 secs] 4218K->4138K(9920K), 0.0009956 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [ParNew: 1430K->6K(3072K), 0.0010982 secs] 5544K->5526K(9920K), 0.0011277 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [ParNew: 1465K->1465K(3072K), 0.0000128 secs][Tenured: 5520K->3603K(6848K), 0.0030239 secs] 6986K->3603K(9920K), [Metaspace: 2696K->2696K(1056768K)], 0.0030834 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [ParNew: 53K->2K(3072K), 0.0003297 secs][Tenured: 6415K->5009K(6848K), 0.0023247 secs] 6469K->5009K(9920K), [Metaspace: 2697K->2697K(1056768K)], 0.0027113 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC (Allocation Failure) [Tenured: 5009K->4762K(6848K), 0.0042073 secs] 5009K->4762K(9920K), [Metaspace: 2697K->2697K(1056768K)], 0.0042415 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOfRange(Unknown Source) at java.lang.String.<init>(Unknown Source) at java.lang.StringBuilder.toString(Unknown Source) at com.test01.TextMain.main(TextMain.java:149) Heap
par new generation total 3072K, used 108K [0x00000000ff600000, 0x00000000ff950000, 0x00000000ff950000) eden space 2752K, 3% used [0x00000000ff600000, 0x00000000ff61b3c8, 0x00000000ff8b0000) from space 320K, 0% used [0x00000000ff900000, 0x00000000ff900000, 0x00000000ff950000) to space 320K, 0% used [0x00000000ff8b0000, 0x00000000ff8b0000, 0x00000000ff900000) tenured generation total 6848K, used 4762K [0x00000000ff950000, 0x0000000100000000, 0x0000000100000000) the space 6848K, 69% used [0x00000000ff950000, 0x00000000ffdf6968, 0x00000000ffdf6a00, 0x0000000100000000) Metaspace used 2727K, capacity 4490K, committed 4864K, reserved 1056768K
class space used 299K, capacity 386K, committed 512K, reserved 1048576K
Java HotSpot(TM) 64-Bit Server VM warning: Using the ParNew young collector with the Serial old collector is deprecated and will likely be removed in a future release
-XX:+UseParallelGC
运行在Server端的默认模式,收集器采用Parallel Scavenge(可控制吞吐量)+Serial Old的收集器组合。
-XX:InitialHeapSize=10485760 -XX:MaxHeapSize=10485760 -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC [GC (Allocation Failure) [PSYoungGen: 1946K->502K(2560K)] 1946K->945K(9728K), 0.0012214 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [PSYoungGen: 2292K->480K(2560K)] 2735K->1972K(9728K), 0.0011636 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [PSYoungGen: 1919K->408K(2560K)] 7610K->6098K(9728K), 0.0005786 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [PSYoungGen: 408K->392K(2560K)] 6098K->6082K(9728K), 0.0004204 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC (Allocation Failure) [PSYoungGen: 392K->0K(2560K)] [ParOldGen: 5690K->3360K(7168K)] 6082K->3360K(9728K), [Metaspace: 2697K->2697K(1056768K)], 0.0068425 secs] [Times: user=0.06 sys=0.00, real=0.01 secs] [GC (Allocation Failure) [PSYoungGen: 40K->32K(2560K)] 6199K->6190K(9728K), 0.0003943 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC (Ergonomics) [PSYoungGen: 32K->0K(2560K)] [ParOldGen: 6158K->4759K(7168K)] 6190K->4759K(9728K), [Metaspace: 2698K->2698K(1056768K)], 0.0026643 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] 4759K->4759K(8704K), 0.0002609 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC (Allocation Failure) [PSYoungGen: 0K->0K(1536K)] [ParOldGen: 4759K->4742K(7168K)] 4759K->4742K(8704K), [Metaspace: 2698K->2698K(1056768K)], 0.0074698 secs] [Times: user=0.03 sys=0.00, real=0.01 secs] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOfRange(Unknown Source) at java.lang.String.<init>(Unknown Source) at java.lang.StringBuilder.toString(Unknown Source) at com.test01.TextMain.main(TextMain.java:149) Heap
PSYoungGen total 1536K, used 41K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000) eden space 1024K, 4% used [0x00000000ffd00000,0x00000000ffd0a498,0x00000000ffe00000) from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000) to space 1024K, 0% used [0x00000000ffe00000,0x00000000ffe00000,0x00000000fff00000) ParOldGen total 7168K, used 4742K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000) object space 7168K, 66% used [0x00000000ff600000,0x00000000ffaa1aa8,0x00000000ffd00000) Metaspace used 2728K, capacity 4490K, committed 4864K, reserved 1056768K
class space used 299K, capacity 386K, committed 512K, reserved 1048576K
-XX:+UseParallelOldGC
新生代中会用ParalleScavageGC,老年代中会用ParallelOldGC。新生代和老年代均为并行收集。
-XX:+UseConcMarkSweepGC
-
CMS(Concurrent Mark Sweep) 并发 用户线程和垃圾收集线程同时执行(有可能是并行,也有可能是并发),用户线程停顿的时间非常短,适合对响应时间有要求的场景。适合堆内存大、CPU核心多的服务器。
开启参数后将会使用ParNew(新生代)+CMS(老年代)+Serial Old的收集器组合,Serial Old将会在CMS出错的后备收集器。
-XX:InitialHeapSize=10485760 -XX:MaxHeapSize=10485760 -XX:MaxNewSize=3497984 -XX:MaxTenuringThreshold=6 -XX:NewSize=3497984 -XX:OldPLABSize=16 -XX:OldSize=6987776 -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseConcMarkSweepGC -XX:-UseLargePagesIndividualAllocation -XX:+UseParNewGC [GC (Allocation Failure) [ParNew: 2654K->319K(3072K), 0.0019591 secs] 2654K->1271K(9920K), 0.0020275 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [ParNew: 2802K->41K(3072K), 0.0014382 secs] 3754K->2698K(9920K), 0.0014976 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [ParNew: 1483K->20K(3072K), 0.0010418 secs] 4141K->4065K(9920K), 0.0010867 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (CMS Initial Mark) [1 CMS-initial-mark: 4045K(6848K)] 5453K(9920K), 0.0002463 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.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (CMS Final Remark) [YG occupancy: 1408 K (3072 K)][Rescan (parallel) , 0.0001095 secs][weak refs processing, 0.0000158 secs][class unloading, 0.0002540 secs][scrub symbol table, 0.0004311 secs][scrub string table, 0.0001428 secs][1 CMS-remark: 4045K(6848K)] 5453K(9920K), 0.0010734 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [CMS-concurrent-sweep-start] [GC (Allocation Failure) [ParNew: 1408K->5K(3072K), 0.0012094 secs] 5453K->5438K(9920K), 0.0012342 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [CMS-concurrent-sweep: 0.002/0.002 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [CMS-concurrent-reset-start] [CMS-concurrent-reset: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (Allocation Failure) [ParNew (promotion failed): 1446K->1445K(3072K), 0.0003263 secs][CMS: 4043K->3340K(6848K), 0.0035269 secs] 5490K->3340K(9920K), [Metaspace: 2697K->2697K(1056768K)], 0.0039165 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [GC (CMS Initial Mark) [1 CMS-initial-mark: 6116K(6848K)] 6116K(9920K), 0.0001493 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [CMS-concurrent-mark-start] [GC (Allocation Failure) [ParNew: 53K->2K(3072K), 0.0003118 secs][CMS[CMS-concurrent-mark: 0.001/0.002 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] (concurrent mode failure): 6116K->4728K(6848K), 0.0036244 secs] 6169K->4728K(9920K), [Metaspace: 2697K->2697K(1056768K)], 0.0040276 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] [Full GC (Allocation Failure) [CMS: 4728K->4712K(6848K), 0.0032040 secs] 4728K->4712K(9920K), [Metaspace: 2697K->2697K(1056768K)], 0.0032459 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOfRange(Unknown Source) at java.lang.String.<init>(Unknown Source) at java.lang.StringBuilder.toString(Unknown Source) at com.test01.TextMain.main(TextMain.java:149) Heap
par new generation total 3072K, used 108K [0x00000000ff600000, 0x00000000ff950000, 0x00000000ff950000) eden space 2752K, 3% used [0x00000000ff600000, 0x00000000ff61b3b8, 0x00000000ff8b0000) from space 320K, 0% used [0x00000000ff8b0000, 0x00000000ff8b0000, 0x00000000ff900000) to space 320K, 0% used [0x00000000ff900000, 0x00000000ff900000, 0x00000000ff950000) concurrent mark-sweep generation total 6848K, used 4712K [0x00000000ff950000, 0x0000000100000000, 0x0000000100000000) Metaspace used 2727K, capacity 4490K, committed 4864K, reserved 1056768K
class space used 299K, capacity 386K, committed 512K, reserved 1048576K
经历的过程:
优缺点
1 停顿时间短
2 垃圾回收线程与用户线程并发的执行时,会增大对堆内存的占用,如果回收线程不能在堆内存用尽之前执行垃圾回收,将会触发担保机制,及启动SerialGC,一个线程串行的进行回收,同时用户线程将会陷入等待,即Stop The World。
3 标记算法无法整理空间碎片,不得不通过担保机制对堆内存进行压缩。
G1
将堆内存分割成不同的区域然后并发的对其进行垃圾回收。(Java8开始)
垃圾回收器:UseG1GC(Old)
-
CMS一样能与应用程序并发执行。
-
不会产生很多内存碎片。
-
-
整体划分为各个不连续的内存区域,不存中绝对的新生代和老年代划分
-
查看默认值的垃圾收集器
java -XX:+PrintCommandLineFlags -version
输出
D:\ProgramFiles\Java\jdk1.8.0_181>java -XX:+PrintCommandLineFlags -version
-XX:InitialHeapSize=65279680 -XX:MaxHeapSize=1044474880 -XX:+PrintCommandLineFlags -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
java version "1.8.0_181" Java(TM) SE Runtime Environment (build 1.8.0_181-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
开始串行垃圾回收
-XX:+UseSerialGC
-
垃圾回收器选择
单核CPU或小内存
-XX:+UseSerialGC
多CPU,最大计算能力的采用
-XX:+UseParallelGC
对响应时间有要求的
-XX:+UseConcMarkSweepGC
收集器算法:新生代中的回收器均为复制算法,老年代中CMS采用的是标清算法,老年代中其他均为标整算法。
本文地址:https://blog.csdn.net/BtWangZhi/article/details/104202156
上一篇: java8新特性(java8内置的四大函数式接口)
下一篇: Java之IO包实现文件读写操作