JVM学习-垃圾回收

1
网上学习的JVM课程,跟随视频自己做的笔记

一、如何判断对象是否可以被回收:

1. 引用计数法:对象被其他对象引用计数+1,不再引用就-1,0就表示可以被回收掉了。
  • 弊端:如果两个对象互相引用,各自的计数都是1,但是没有其他对象引用他们,就不能被回收。在这里插入图片描述
2. 可达性分析算法:
  • 垃圾回收之前,会对堆内存进行扫描,来检测每个对象是否会被根对象(GC Root)直接或间接引用,如果是那么这个对象不能被回收,反之则可以回收。
  • 举个例子:像一串葡萄一样,如果把葡萄从顶部提起来,跟随葡萄一同起来的葡萄果代表不能被回收的对象,而那些断开散落的则是能被回收的对象。
  • 哪些对象可以被作为GC Root?
    可以通过eclipse提供的工具Memory Analyzer来分析。
    System Class(系统核心类)、Native Stack、Busy Monitor(正在加锁的对象)、Thread(活动线程类)、栈帧内使用的对象。
    比如一个方法内声明了List list = new ArrayList<>();则该ArrayList即可作为GC Root。
3. 四种引用(细分有五种)
3.1 强引用

Obj obj = new Obj();
只要所有GC Roots对象都不通过强引用引用该对象,该对象才能被回收。

3.2 软引用(SoftReference)
  • 仅有软引用引用该对象时,在垃圾回收后,内存仍不够才会回收软引用对象。
  • 可以配合引用队列来释放软引用自身
  • 适用场景:数据缓存
3.3 弱引用(WeakReference)
  • 仅有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象。
  • 可以配合引用队列类释放弱引用自身
3.4 虚引用(PhantomReference幽灵引用)
  • 必须配合引用队列使用,主要配合ByteBuffer使用,被引用对象回收时,会将虚引用入队列,由Reference Handler线程调用虚引用相关方法释放直接内存。
3.5 终结器引用(FinalReference)
  • 无需手动编码,但其内部配合引用队列使用,在垃圾回收时,终结器引用入队(被引用对象暂时没有被回收),再由Finalizer线程(优先级低)通过终结器引用找到被引用对象并调用他的finalize方法,第二次GC时才能回收被引用对象。

二、 垃圾回收算法

JVM会根据情况采用下面三种算法。

1. 标记清除(Mark Sweep)

先标记再清除,效率相对来说快,但是会产生内存碎片,造成内存不连续。
优点:效率高
缺点:会产生内存碎片

2. 标记整理(Mark Compact)

标记清除完会对内存进行整理, 将可用对象向前移动使内存更加连续,还要更新对象的引用地址,所以效率相对来说较低。
优点:不会产生碎片
缺点:效率相对较低

3. 复制(Copy)

将内存区域划分为两块区域,from区域和to区域,先找到存活的对象进行标记,将存活的对象复制到to并且进行内存整理,然后将from和to进行交换。
优点:不会产生碎片
缺点:占用双倍的内存空间

三、 分代垃圾回收机制

在这里插入图片描述

  1. 创建新的对象时,默认采用伊甸园的内存
  2. 当伊甸园内存不足时,会发生Minor GC,对伊甸园进行一次垃圾回收,并采用复制算法将对象存放在幸存区to,年龄+1(to和from会交换位置)
  3. 经过第一次垃圾回收之后,伊甸园的内存又充足了,当伊甸园内存再次不足时会发生第二次Minor GC,此时会对伊甸园和幸存区from进行垃圾回收,也会将存活的对象存放到to,年龄+1并交换to和from位置。
  4. 存活的对象不会一直在幸存区,当年龄超过一定的阈值(最大为15,因为是4bit,最大为1111)会认为该对象价值高经常被使用,会晋升至老年代。
  5. 当新生代和老年代内存都不足时会先尝试Minor GC,如果仍不足,会触发Full GC,来进行整个内存清理。
  6. 补充:GC时,会发生STW(stop the world)(因为采用复制算法,对象的地址会发生改变),暂停其他用户线程,等待垃圾回收结束,用户线程才恢复运行。Full GC的STW时间更长。

四、相关VM参数

在这里插入图片描述

五、垃圾回收器

1、串行垃圾回收器

在这里插入图片描述
开启指令:-XX:+UseSerialGC=Serial+SerialOld
Serial为新生代垃圾回收器,采用复制算法。
SerialOld为老年代,采用标记+整理算法。
都为单线程的,垃圾回收时都会STW。

2、吞吐量优先垃圾回收器

在这里插入图片描述
参数一:并行的垃圾回收器,JDK1.8默认的垃圾回收器。
参数二:采用自适应调整伊甸园,晋升阈值和幸存区大小。
两个目标:
参数三:计算公式:1/(1+ratio),比如radio是99,则公式得0.01,即100分钟内最多有1分钟来进行垃圾回收,如果达不到这个目标则会调整堆内存,一般是调大,来减少垃圾回收的次数,来提高系统吞吐量。一般设置19。
参数四:最大停留ms数,默认200ms。与上边是冲突的,因为如果上边有做出调大堆内存,那么停留时间可能就会变长,导致达不到这一目标。
这两个是冲突的。
参数五:控制垃圾回收时并行的线程数量。

3、响应时间优先的垃圾回收器(CMS)

在这里插入图片描述
-XX:+UseConcMarkSweepGC ~ -XX:+UseParNewGC ~ SerialOld
是工作在老年代基于标记清除算法的垃圾回收器,并发失败会降级为SerialOld串行垃圾回收器。
初始标记和重新标记会STW,初始标记只标记根对象,因为并发标记时用户线程也在执行,会产生新的垃圾,所以需要重新标记。