JVM的的GC如何判断对象是否死亡如何判断对象是否死亡?
因为热爱,所以坚持
文章下方有本文参考电子书和视频的下载地址下载地址哦~
这节我们主要讲垃圾收集的一些基本概念,先了解垃圾收集是什么、然后触发条件是什么、最后虚拟机如何判断对象是否死
亡。
一、前言一、前言
我们都知道Java和C++有一个非常大的区别就是Java有自动的垃圾回收机制,经过半个多世纪的发展,Java已经进入
了“自动化”时代,让使用者只需要注重业务逻辑的开发而不需要担心内存的使用情况。那么我们为什么还要学习Java的垃圾回
收机制呢?原因很简单:我们不想止于“增删改查工程师”这样的初级水平,一旦程序发生了内存溢出、内存泄漏等问题时,我
们可以用已掌握的知识更好的调节和优化我们的代码。在学这章节之前,默认大家已经了解并掌握了Java内存运行时的五个
区域的功能:方法区、Java堆、虚拟机栈、本地方法栈、程序计数器。还没有了解过的朋友请先看这里:JVM中五大内存区
域
二、判断对象是否死亡二、判断对象是否死亡
客官们可以先想一下,GC(垃圾回收机制)在清理内存的时候第一件事要做什么?肯定是要先判断内存中的对象是否已经死
亡,也就是再也不会被使用了,然后才会去回收这些对象。判断对象是否死亡通常会有两种办法:引用计数法引用计数法和可达性分析可达性分析。
2.1 引用计数法引用计数法
使用引用计数法,要先给每一个对象中添加一个计数器,一旦有地方引用了此对象,则该对象的计数器加1,如果引用失效
了,则计数器减1。这样当计数器为0时,就代表此对象没有被任何地方引用。这种方法实现简单,判定效率也很高,在大部
分情况下都是一个比较不错的方法。但是在Java虚拟机中并没有选用引用计数法来管理内存,其主要原因是它很难解决对象
之间相互引用的问题,如果两个对应互相引用,导致他们的引用计数都不为0,最终不能回收他们。我们来举个例子
class Person{
public Person lover = null;//定义一个爱人
private String name = "";//姓名
Person(String name){
this.name = name;
}
}
public class Demo {
public static void main(String[] args) {
Person liangshanbo = new Person("梁山伯");//创建一个人物:梁山伯
Person zhuyingtai = new Person("祝英台");//创建一个人物:祝英台
liangshanbo.lover = zhuyingtai;//设置梁山伯的爱人是祝英台
zhuyingtai.lover = liangshanbo;//设置祝英台的爱人是梁山伯
}
}
其中梁山伯和祝英台两个对象互相引用,因此如果使用引用计数法来判断对象是否死亡的话,垃圾回收机制是不能回收这两个
对象的。
2.2 可达性分析算法可达性分析算法
在大部分主流语言中都是通过此方法来判断对象是否存活的,这个算法的思想是通过一系列被称为“GC root”的对象作为起始
点,从这些节点开始向下搜索,走过的路径叫做引用链。如果一个对象没有通过引用链连接到GC root节点,则证明此对象是
不可用的,如下图所示,GC roots 是根节点,凡是能通过引用链连接上GC root 的Object 1,2,3,4都是被使用的对象。但是
Object 5,6,7却不能通过任何方式连接上根节点,因此判定Object 5,6,7为可回收的节点。