java中对象的生存期_深入理解Java虚拟机-判断对象是否存活算法与对象引用

我们知道Java中的对象一般存放在堆中,但是总不能让这些对象一直占着内存空间,这些对象最终都会被回收并释放内存,那么我们如何判断对象已经成为垃圾呢?这篇文章会提出两种算法解决这个问题。另外,本文还要谈一谈对象引用相关的知识,这在面试中也是经常被问到的问题。

判断对象是否存活算法

引用计数算法

引用计数算法的原理比较简单,在对象中添加一个引用计数器,当有一个引用指向一个对象时,这个对象的引用计数器会加1,当引用不再指向对象时,引用计数器便减1。当引用计数器的值为0时,说明对象已经成为垃圾。

引用计数算法的优点是算法非常简单,效率也比较高。但是Java并没有使用这种算法管理内存,这是为什么呢?我们先来看看下面这段代码。

public class Demo {

public static void main(String[] args) {

Obj obj1 = new Obj();

Obj obj2 = new Obj();

obj1.instance = obj2;

obj2.instance = obj1;

obj1 = null;

obj2 = null;

}

}

class Obj {

public Obj instance;

public Obj() {

super();

}

}

我们看一下上面这段代码,两个对象obj1和obj2的instance分别指向对方,造成了循环引用。即便最后obj1和obj2都置为空,但它们的instance还是指向对方,如果我们使用这种算法,这两个对象势必无法回收,最终造成内存泄漏。因此,Java没有选择使用引用计数算法管理内存。

可达性分析算法(根搜索算法)

主流的商用编程语言(Java、C#以及上古语言Lisp)都是用这种算法进行对象是否存活的判断。

根搜索算法利用GC Roots作为起始节点集,从这些节点开始向下搜索,凡是能够到达的节点都是存活节点,不能到达的节点都不再会被使用,这些节点的对象都可以被回收。

Java技术体系中可以作为GC Roots的对象有以下几种:虚拟机栈(栈帧的本地变量表)中引用的对象

方法区中类静态属性引用的对象

方法区中常量引用的对象

本地方法栈中JNI(及native方法)引用的对象

虚拟机内部的引用,比如基本数据类型对应的Class对象,一些常驻的异常对象(如NullPointerException、OutOfMemoryError)等,还有类加载器。

被同步锁(synchronized)持有的对象

反映Java虚拟机内部情况的JMXBean、JVMTI注册的回调,本地代码缓存等

另外,需要补充的是,即便被可达性分析算法标记为不可达对象,这些对象也未必一定会被回收。事实上,被标记为不可达对象后,这个对象还需要经历第二次标记才可能会被宣布正式死亡。当第一次标记以后,会判断对象有没有必要执行finalize()方法。当对象没有覆盖finalize()方法或已经被虚拟机调用过的话,就被判定没有必要再继续执行了。当有必要执行finalize()方法时,这些对象会被放在名为F-Queue的队列中,随后虚拟机会创建一个线程去执行队列中的对象的finalize()方法。如果这些对象在收集器对F-Queue中对象标记前在finalize()方法中重新与引用链上的对象建立关系,比如将自己赋值给某个类变量就可以移出回收集合,免除被回收的命运。

对象引用

谈到引用,不得不提到前几天的考研复试,我的一位学弟在复试过程中被问到Java中有哪些引用,这几种引用有什么区别。被问到这道题时,他一时语塞,没有回答上来。不过好在没有因为这道题受到影响。今天我们就来谈一谈Java中的四种引用。强引用。强引用是我们平时使用最多的引用方法。Object obj = new Object()这就是一个典型的强引用实例,只要强引用关系还存在,即使系统内存不足,也不会回收这些对象。

软引用。软引用用来描述一些还有用,但不是必须的对象,使用SoftReference类来实现软引用。当系统内存不足时,会回收软引用关联的对象。

弱引用。弱引用通过WeakReference类来实现,即使内存充足,下一次垃圾收集时,弱引用对象也会被回收。

虚引用。虚引用又称“幽灵引用”或“幻影引用”,是最弱的一种对象引用,它使用PhantomReference类来实现。虚引用的作用是在关联的对象被回收时能收到一个系统通知。

喜欢的给个赞呗

了解更多可以关注我的公众号:SKY技术修炼指南

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值