文章目录

  • 一、判断对象状态
  • 1.1 引用计数法
  • 1.2 可达性算法
  • 二、垃圾回收算法
  • 2.1 标记-清除算法
  • 2.2 复制算法
  • 2.3 标记-整理算法
  • 2.4 分代收集算法
  • 三、GC和Full GC的区别

一、判断对象状态

Java 的垃圾回收是指回收内存中已经“死亡”的对象所使用的内存空间,此处的死亡时是指该对象再也不会被使用,因此在进行垃圾回收之前需要先判断内存中对象的状态。虚拟机中用于判断对象状态的算法有两种:引用计数法和可达性算法。

1.1 引用计数法

引用计数法是一种比较简单直接的算法,即在虚拟机中保存每个对象的被引用次数,例如对象 A 被对象 B 引用,则对象 A 的引用次数加一;当对象 B 释放对对象 A 的引用时,对象 A 的引用次数减一。当某个对象的引用次数为 0 时表示该对象已经死亡,会在下一次垃圾回收时被系统回收。

缺点: 无法解决循环引用的问题,例如对象 A 引用了对象 B,而对象 B 中又引用了对象 A,此时对象 A 和对象 B 之间就形成了循环引用,两者的引用次数一直不为 0,也就一直无法被回收。

1.2 可达性算法

可达性算法又叫根搜索算法,该算法由每一个根节点触发,根据对象之间的引用关系遍历所有与根节点关联的对象节点,在遍历完成后那些没有被遍历到的对象即为死亡的对象,会在下一次垃圾回收时被系统回收。示例图如下:

java空间数据计算 java 内存计算_java


图中的对象 C 和对象 G 即为死亡的对象,因为没有任何路径与根节点相连,它们会在下一次垃圾回收时被回收。

在可达性算法中,以下四种对象可以作为根节点:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中中常量引用的对象
  • 本地方法栈中JNI(即native方法)引用的对象

二、垃圾回收算法

上面介绍了如何判断内存中对象状态,接下来介绍虚拟机在垃圾回收时是如何回收这些死亡的对象的。
垃圾回收主要有三种算法:标记-清除算法,标记-复制算法和标记-整理算法。

2.1 标记-清除算法

标记-清除算法即每次垃圾回收时直接从内存空间中回收那些已经死亡的对象,使用此算法进行垃圾回收会在内存中留下一段段不连续的大小不一致的内存空间,当需要创建新对象时,就从这些零碎的内存空间中寻找一片足够大的内存空间用于存放该对象。

缺点:会留下许多零碎的、难以管理的内存空间,造成内存浪费。

2.2 复制算法

复制算法将内存空间一分为二,每次只使用其中的一半内存,在这一半内存满了的时候就将这块内存中存活的对象复制到另一半的内存中,然后释放这一半的内存空间。

缺点:会浪费一半的内存空间。有可能遇到一半内存满了,并且这一半内存中的所有对象都是存活着的情况。

注:由于大部分对象的存活时间很短,因此大部分虚拟机按照 8:1:1 的比例将内存空间划分为 Eden 和两个 Survivor 空间,每次使用Eden和一块Survivor空间,垃圾回收时将存活的对象一次性复制到另一块Survivor空间上。

2.3 标记-整理算法

标记-清除算法即在垃圾回收时从内存空间中回收那些已经死亡的对象,然后将剩下的存活的对象整理到一起,留下一片连续的内存空间。即在标记-清除的基础上加上整理的步骤。

缺点:整理阶段,由于移动了可用对象,需要去更新引用。

2.4 分代收集算法

现代虚拟机中一般会对内存区域进行划分:新生代,老年代。然后根据各个年代的特点选择合适的收集算法:对于新生代,每次垃圾回收都会有大量的对象死去,因此可以选用复制算法,只需要付出少量存活对象的复制成本就可以完成垃圾回收;在老年代中,对象的存活率比较高,所以一般使用“标记-清除”算法或者“标记-整理”算法进行回收。

  • 大部分情况下,对象会在新生代的 Eden 区域中分配内存
  • 大对象(需要大量连续内存空间的Java对象)会直接进入老年代。
  • 新生代中的对象每经历一次GC,年龄就增加一岁,达到一定的年龄后就会移入到老年代中,一般默认阈值为15岁。
  • 动态对象年龄判断:当Survivor空间中相同年龄的所有对象的大小总和超过Survivor空间的一半时,Survivor空间中所有年龄大于等于该年龄的对象可以直接进入老年代,而不需要等待年龄达到阈值。
  • 空间分配担保机制:在分代收集算法中,老年代为新生代起担保作用,当新生代的内存空间满了会触发一次GC,在GC期间发现Survivor空间不足以存放存活的对象,那么此时这些存活的对象会通过担保机制进入老年代的空间。

三、GC和Full GC的区别

  • GC(或Minor GC):指发生在新生代的垃圾回收。
  • Full GC (或Major GC):指发生在老年代的垃圾回收。Full GC经常会伴随着一次GC,但是并不绝对。