JVM灵魂拷问系列之垃圾回收


JVM灵魂拷问系列之垃圾回收

1. 垃圾回收发生在哪些区域?

JVM内存模型中, 线程共享区域 会发生垃圾回收,也就是 堆内存方法区

线程独占区域的内存,会随着线程的消亡而销毁,不需要垃圾回收

2. 说说JVM在哪些情况下会进行垃圾回收?

Eden区域/永久代内存满了会进行垃圾回收

一般有通过两种方式来判断:引用计数法可达性分析

2.1 引用计数法

通过对象的引用计数器来判断该对象是否被引用,被其他地方引用一次+1,反之-1,值为0表示没有引用可回收

缺点:循环引用的情况无法解决,所以Java没用使用引用计数法

2.2 可达性分析

以根对象为起点向下搜索,走过的路径为引用链,如果对象到根对象没用引用链相连,则认定这个对象不可达,是可以回收,如图Object5和Object7是可回收的

哪些对象可以作为根对象

  1. 虚拟机栈(栈帧中的本地变量表)引用的对象
  2. 方法区类静态属性引用的对象
  3. 方法区常量引用的对象
  4. 本地方法栈中JNI(即Native方法)引用的对象

3. 说说强引用、软引用、弱引用和虚引用,在垃圾回收时会发生什么?

  1. 强引用:平时使用的引用,Object o = new Object();,只要强引用在对象就不会被回收.哪怕出现内存溢出也不回收
  2. 软引用:SoftReference sf = new SoftReference<>(“hello”);一般是描述一些有用但非必需的对象。内存不足才回收
    软引用比较适合用来实现缓存,比如网页缓存图片缓存等等
  3. 弱引用:WeakReference sf = new WeakReference<>(“hello”);一般是描述一些有用但非必需的对象。不管内存是否不足都会被回收
  4. 虚引用:任何时候都可能被回收,主要用来跟踪被回收的活动,一般跟引用引用队列配合使用

4.说说JVM的垃圾回收算法?对象什么时候转移到老年代?

首先,我们需要了解一个原则:JVM一边运行代码一边判断和清理垃圾对象是不现实的,所以提到垃圾回收都会说一个概念: Stop The World,意思是JVM会停止工作线程的运行来进行垃圾回收 -> 发生小小的卡顿

例子:聚会(程序运行)不断产生垃圾,清洁工清理垃圾(垃圾收集器),如果聚会不停止(程序不短暂暂停),则清洁工就没办法进入场地清理垃圾,打扫好屋子

JVM使用 分代收集算法 来进行垃圾回收,根据不同区域使用不同垃圾回收算法,既可以有效清除垃圾对象,又提高了垃圾回收的效率

这里省略另一种算法 增量算法:每次只收集一小片区域的垃圾(每次回收全部垃圾系统停顿更长,此算法可减小系统停顿)

4.1 年轻代垃圾回收算法-复制算法

Minor/Young GC

98%的对象都会很快消亡,所以 大多数对象的生命周期都很短

流程:对象在创建时,一般会先存放到Eden,Eden满了之后就会触发垃圾回收,会把Eden中存活对象拷贝到S1中,清理Eden区域的所有对象。如果Eden区域又满时,会把Eden区域和S1的存活对象复制到S2区域,再清楚所有Eden区域和S1区域的对象。如此反复..

优点:性能好、无碎片
缺点:内存利用率低

4.2 老年代垃圾回收算法-标记清除/标记整理算法

老年代的对象都是被长期引用的,老年代的垃圾回收比较慢,一般是年轻代垃圾回收的10倍以上

新创建的对象也有可能直接进入老年代

  1. 对象大于JVM参数-XX:PretenureSizeThreshold的阈值时,直接分配到老年代
  2. 新生代的空间不足以存放该对象

老年代的垃圾回收:Major GC

执行Major GC时一般都伴随这Minor GC,所以老年代回收约等于Full GC。

Major GC 触发条件

  1. 老年代空间不足
  2. 元空间不足
  3. 某一对象晋升到老年代但是老年代空间不足
  4. 显式调用System.gc()方法,可以使用-XX:+DisableExplicitGC来忽略此调用

标记清除算法

  1. 使用 可达性分析 标记可回收对象
  2. 清除可回收对象

优点:实现简单
缺点:清除后会存在内存碎片,例如图中情况下,如果想分配一个连续三个内存空间的数组,则图中的内存块无法做到

标记整理算法

  1. 使用 可达性分析 标记可回收对象
  2. 把存活对象移动到一端
  3. 清除可回收对象

优点:无内存碎片
缺点:对比标记清除开销大

4.3 对象什么时候转移到老年代

  1. 经过 15次Young GC还存活 的对象会转移到老年代。例如Spring容器里管理的对象实例,被Spring容器引用,所以长期存活转移到老年代
  2. 新创建的大对象,如果Eden区域放不下,则会转移到老年代
  3. S区域放不下 的对象会转移到老年代

5. GC简单汇总图

Full GC待补充

6. 常用的垃圾回收器

parnew + CMS

目前主流的jdk版本使用的组合

parnew: 新生代垃圾回收器,使用多线程去回收垃圾对象,使用复制算法
CMS:老年代垃圾回收器,是一个并发收集器,使用标记清除算法

G1分代垃圾回收器

jdk新版本使用的垃圾回收器


评论
  目录