JVM学习笔记GC——JAVA语言的垃圾回收
Posted 九死九歌
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM学习笔记GC——JAVA语言的垃圾回收相关的知识,希望对你有一定的参考价值。
一、垃圾回收概述
1 什么是GC,为何要GC?
2 早期垃圾回收
3 Java的垃圾回收机制
二、垃圾回收的相关算法
1 垃圾回收算法的概述
垃圾回收分为标记阶段和清除阶段,标记阶段找垃圾,清除阶段清掉找到的垃圾。
标记阶段使用的算法有引用计数算法、可达性算法。
清除阶段使用的算法有标记-清除算法、复制算法、标记-压缩算法。
2 标记阶段:引用计数算法
3 标记阶段:可达性分析算法
4 对象的finalization机制
有趣的代码——对象复活记
public class Test
public static Test test;
@Override
protected void finalize() throws Throwable
super.finalize();
System.out.println("finalizing...");
test = this;
public static void main(String[] args) throws InterruptedException
test = new Test();
test = null;
System.gc();
Thread.sleep(500);
if (test != null)
System.out.println("I am alive:)");
else
System.out.println("I am gg:(");
test = null;
System.gc();
if (test != null)
System.out.println("I am alive:)");
else
System.out.println("I am gg:(");
5 清除阶段:标记 - 清除算法
6 清除阶段:复制算法
我们很容易想到,幸存者区便使用的是复制算法。因为新生代死亡率高,导致复制算法的缺点不明显,而优势倍增。
7 清除阶段:标记 - 压缩算法
8 对比清除阶段三种算法
9 分代收集算法
10 增量收集算法
11 分区算法
三 、垃圾回收的相关概念
1 System.gc()
我们来看一个有意思的代码:
public class Test
public static void main(String[] args)
new Test();
System.gc();
// System.runFinalization();
@Override
protected void finalize() throws Throwable
super.finalize();
System.out.println("Override finalize");
·运行结果便是有可能执行析构函数也有可能没有执行析构函数,也就是没有进行gc,这也就说明System.gc()只是提醒虚拟机进行GC,但不一定就会马上GC。
若将main函数第三行解除注释,便会执行fianlize方法,因为第三行调用的这个函数会强制执行引用对象的析构函数。
2 内存溢出与内存泄露
内存溢出:
内存泄漏:
内存泄漏的举例:
3 STW - Stop The World
另外,STW期间,多个垃圾回收线程可能是串行的,也可能是并行的。另外也有可能不进行STW,用户线程和垃圾回收线程一起运行。
4 安全点与安全区域
安全点:
安全区域:
5 JAVA中的各种引用
强引用是哪怕OOM都不回收。
软引用是要OOM才回收。
弱引用是只要GC就回收。
6 强引用:永不回收
强引用的特点:
7 软引用:内存不足才回收
若内存足够,则不会回收软引用可触及对象。
// 创建强引用
ClassName strongRef = new ClassName(args);
// 创建弱引用
SoftReference<ClassName> softRef = new SoftReference<ClassName>(new ClassName(args));
8 弱引用:发现即回收
只要一进行GC,管你是个啥都回收。
9 虚引用:对象回收跟踪
10 终结器引用
最不常用的一种引用。
了解即可,这不是重点。
四、垃圾回收器
1 垃圾回收器的分类
![其他分类方式![](https://img-blog.csdnimg.cn/31933fed451145689ecaa6b052032d28.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5Lmd5q275Lmd5q2M,size_20,color_FFFFFF,t_70,g_se,x_16)
2 垃圾回收器的性能指标
下图中的这三项指的是上图中标红的三项指标。
3 垃圾回收器的发展迭代史
七款经典垃圾回收器
4 垃圾回收器之间的组合关系
对上图中彩色虚线的说明。
5 如何查看默认的垃圾回收器
6 Serial与Serial Old回收器:串行回收
7 ParNew回收器:并行回收
下图是Serial Old和ParNew组合式GC
8 Parallel和Parallel Old回收器:吞吐量优先
相关参数的设置:
9 CMS的概述与工作原理
CMS的工作原理:
10 CMS的特点与弊端分析
CMS的优势与弊端:
11 CMS的参数设置
12 认识G1垃圾回收器
13 G1的优势和不足
① 并行与并发 ② 分代收集
③ 空间整合
④ 可预测的停顿时间模型
G1的缺点:
14 G1的参数设置
G1的性能调优:
15 G1在生产环境的适用场景
16 分区(region)的使用介绍
分区有点像分页哦。
17 G1的主要回收环节
Remembered Set记忆集:用来回收跨代回收问题。
每个对象的成员变量固然会记录他们引用了谁,而每个记忆集则记录了这个对象被哪个对象所引用。当然若两个对象来自同一个region则无需在记忆集中记录。
18 G1垃圾回收过程的详细说明
过程一:新生代GC
过程二:并发标记过程
过程三:混合回收
过程四:Full GC
19 G1垃圾回收的优化建议
20 七大经典垃圾回收器的总结
21 常用的GC日志参数的设置
22 GC日志中垃圾回收数据的分析
MinorGC日志:
FullGC日志:
将VM options填入并运行如下代码:
/**
* <b>VM options:</b><br/>
* <code> -Xms20M</code><br/>
* <code> -Xmx20M</code><br/>
* <code> -Xmn10M</code><br/>
* <code> -XX:+PrintGCDetails</code><br/>
* <code> -XX:SurvivorRatio=8</code><br/>
* <code> -XX:+UseSerialGC</code><br/>
*/
public class Test
public static final int _1M = 1024;
public static void main(String[] args)
byte[] a1 = new byte[2 * _1M];
byte[] a2 = new byte[2 * _1M];
byte[] a3 = new byte[2 * _1M];
byte[] a4 = new byte[4 * _1M];
先在jdk7环境下运行,输出如下:
[GC (Allocation Failure) [DefNew: 8158K->603K(9216K), 0.0148287 secs] 8158K->6747K(19456K), 0.0162353 secs] [Times: user=0.01 sys=0.00, real=0.02 secs]
Heap
def new generation total 9216K, used 4865K [0x00000000fec00000, 0x00000000ff600000, 0x00000000ff600000)
eden space 8192K, 52% used [0x00000000fec00000, 0x00000000ff029778, 0x00000000ff400000)
from space 1024K, 58% used [0x00000000ff500000, 0x00000000ff596ce0, 0x00000000ff600000)
to space 1024K, 0% used [0x00000000ff400000, 0x00000000ff400000, 0x00000000ff500000)
tenured generation total 10240K, used 6144K [0x00000000ff600000, 0x0000000100000000, 0x0000000100000000)
the space 10240K, 60% used [0x00000000ff600000, 0x00000000ffc00030, 0x00000000ffc00200, 0x0000000100000000)
Metaspace used 3183K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 343K, capacity 388K, committed 512K, reserved 1048576K
首先注意第3行写着新生代内存大小是9216KB,即9MB,然而我们设置的新生代大小是10MB,这是因为这里只算了Eden和一个Survivor的大小。
如图,前三个变量已经快要挤满了Eden,第四个变量进不来,然而Survivor他也进不去,于是新生代进行一次GC,三个2MB变量自然无法进入Survivor,于是进入Tenured。所以从log中我们也能看到老年代占用了6MB(那三个2MB),Eden则占用了4MB
如果在jdk8中运行,结果如下:
可见jdk8与jdk7垃圾回收过程存在不同。
23 新时代的Epsilon和Shenandoah
jdk11中的一些新特性:Epsilon与ZGC
jdk12中的Shenandoah:
24 革命性的ZGC
吞吐量测试数据:
延迟时间测试数据:
以上是关于JVM学习笔记GC——JAVA语言的垃圾回收的主要内容,如果未能解决你的问题,请参考以下文章