当前位置: 移动技术网 > IT编程>开发语言>Java > Java GC的理解

Java GC的理解

2020年07月17日  | 移动技术网IT编程  | 我要评论

1. 判断垃圾对象

在进行垃圾回收之前,先判断哪些对象应该被回收,将其标志出来。java提供两种策略:

1. 1 引用计数法

当一个对象有一次引用时,计数+1。计数为0时,代表该对象没有任何引用,将其标志。但无法解决循环引用问题。如下图,堆中两个对象相互引用,但栈中没有引用指向它们,此时他们的计数都为1,不能被回收,但实际上他们已经为垃圾数据。

1.2 GC Roots可达性分析

以GC Roots对象做为起点,如果该起点与某个对象没有有可达性的连接,则代表该对象可被回收。
在这里插入图片描述
可做为GC Roots的对象:

  • 虚拟机栈中引用的对象
  • 方法区中常量引用的对象
  • 方法区中类静态属性引用的对象
  • 本地方法栈中JNI(即一般说的Native方法)中引用的对象

2. 垃圾回收算法

将堆内存分为新生代和老年代。因为新生代只有少量对象存活,通常使用复制算法;而老年代对象存活率高,通常使用标志 - 清楚算法或者标志 - 整理算法

2.1 标志 - 清除算法

该方法效率高,直接把标记好的对象清除,把占用的空间置为可用。但是会产生碎片化的内存,导致没有足够大的空间存储大内存对象。

2.2 复制算法

将新生代分为三个区(Eden、Survivor1,Survivor 2,空间占比8:1:1 )。

  1. 第一次new出来的对象放在Eden区
  2. 第一次GC算法后,将没被回收的对象放到survivor1区,且年龄+1,同时清空Eden区所有对象
  3. 第二次new出来的对象放在Eden区
  4. 第二次GC算法后,将没被回收的对象放到survivor2区,且年龄+1,同时清空Eden区和survivor2区所有对象
  5. 依次循环
  6. 当年龄达到一定值(CMS规定6,PS、PO规定12),将存活对象放入老年代。

2.3 标志 - 整理算法

将已标志的对象一边清除,一遍整理,使得GC过后,内存还能连续,解决碎片化问题。
在这里插入图片描述

3. 常用的垃圾回收器

3.1 Serial、Serial Old

串行回收器:停止当前所有工作线程,启动一个GC线程进行垃圾回收。GC线程回收完成后,工作线程方可继续执行。Serial是新生代的回收器,使用的是复制回收算法,Serial Old是老年代的回收器,使用的是标记 - 清除算法或者标记 - 整理算法。(jdk1.1,jdk1.2默认回收器)
在这里插入图片描述

3.2 Parallel Scavenge、Parallel Old

并行回收器(PS、PO):串行回收器的多线程版本,停止所有工作线程后,启动多个GC线程去进行回收工作。Parallel Scavenge是新生代的回收器,Parallel Old是老年代的回收器 (jdk1.8默认回收器)
在这里插入图片描述

3.3 Parnew、CMS

ParNew: 针对新生代的回收器,停止所有工作线程后,启动多个GC线程进行回收工作(同Parallel Scavenge,只不过Parallel Scavenge是与Parallel Old搭配使用的,ParNew是与CMS搭配使用的)
在这里插入图片描述
CMS(Concurrent Mark Sweep): 针对老年代的回收器

  1. 初始标记(CMS initial mark):停止所有工作线程,标记 GC Roots 能直接关联到的对象(使工作线程的停顿时间降到最低)
  2. 并发标记(CMS concurrent mark):找出其他未标记的存活对象,此时与工作线程并发执行,所以会出现误标,漏标现象
  3. 重新标记(CMS remark):修正并发标记期间出现误标,漏标的现象
  4. 并发清除(CMS concurrent sweep):将未标志的对象清除,不整理压缩内存空间,因此会产生碎片化
    在这里插入图片描述

3.4 G1

todo

本文地址:https://blog.csdn.net/qq_36390175/article/details/107352625

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网