如何判断对象已经死亡

引用计数

给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加 1;当引用失效,计数器就减 1;任何时候计数器为 0 的对象就是不可能再被使用的。

这个方法实现简单,效率高,但是目前主流的虚拟机中并没有选择这个算法来管理内存,其最主要的原因是它很难解决对象之间相互循环引用的问题。 所谓对象之间的相互引用问题,如下面代码所示:除了对象 objA 和 objB 相互引用着对方之外,这两个对象之间再无任何引用。但是他们因为互相引用对方,导致它们的引用计数器都不为 0,于是引用计数算法无法通知 GC 回收器回收他们。

public class ReferenceCountingGc {Object instance = null;public static void main(String[] args) {ReferenceCountingGc objA = new ReferenceCountingGc();ReferenceCountingGc objB = new ReferenceCountingGc();objA.instance = objB;objB.instance = objA;objA = null;objB = null;}
}

可达性分析

这个算法的基本思想就是通过一系列的称为 “GC Roots” 的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连的话,则证明此对象是不可用的。 

注意:

即使在可达性分析法中不可达的对象,也并非是“非死不可”的,这时候它们暂时处于“缓刑阶段”,要真正宣告一个对象死亡,至少要经历两次标记过程;可达性分析法中不可达的对象被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行 finalize 方法。当对象没有覆盖 finalize 方法,或 finalize 方法已经被虚拟机调用过时,虚拟机将这两种情况视为没有必要执行。

被判定为需要执行的对象将会被放在一个队列中进行第二次标记,除非这个对象与引用链上的任何一个对象建立关联,否则就会被真的回收

常量:

假如在常量池中存在字符串 "abc",如果当前没有任何 String 对象引用该字符串常量的话,就说明常量 "abc" 就是废弃常量,如果这时发生内存回收的话而且有必要的话,"abc" 就会被系统清理出常量池。

类:

要判定一个类是否是“无用的类”的条件则相对苛刻许多。类需要同时满足下面 3 个条件才能算是 “无用的类” :

  • 该类所有的实例都已经被回收,也就是 Java 堆中不存在该类的任何实例。
  • 加载该类的 ClassLoader 已经被回收。
  • 该类对应的 java.lang.Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

引用

无论是通过引用计数法判断对象引用数量,还是通过可达性分析法判断对象的引用链是否可达,判定对象的存活都与“引用”有关。

JDK1.2 之前,Java 中引用的定义很传统:如果 reference 类型的数据存储的数值代表的是另一块内存的起始地址,就称这块内存代表一个引用。

JDK1.2 以后,Java 对引用的概念进行了扩充,将引用分为强引用、软引用、弱引用、虚引用四种(引用强度逐渐减弱)

1.强引用(StrongReference)

以前我们使用的大部分引用实际上都是强引用,这是使用最普遍的引用。如果一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回收它。当内存空间不足,Java 虚拟机宁愿抛出 OutOfMemoryError 错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足问题。

2.软引用(SoftReference)

如果一个对象只具有软引用,那就类似于可有可无的生活用品。如果内存空间足够,垃圾回收器就不会回收它,如果内存空间不足了,就会回收这些对象的内存。只要垃圾回收器没有回收它,该对象就可以被程序使用。软引用可用来实现内存敏感的高速缓存。

软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收,JAVA 虚拟机就会把这个软引用加入到与之关联的引用队列中。

3.弱引用(WeakReference)

如果一个对象只具有弱引用,那就类似于可有可无的生活用品。弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。不过,由于垃圾回收器是一个优先级很低的线程, 因此不一定会很快发现那些只具有弱引用的对象。

弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java 虚拟机就会把这个弱引用加入到与之关联的引用队列中。

4.虚引用(PhantomReference)

"虚引用"顾名思义,就是形同虚设,与其他几种引用都不同,虚引用并不会决定对象的生命周期。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收。

虚引用主要用来跟踪对象被垃圾回收的活动

虚引用与软引用和弱引用的一个区别在于: 虚引用必须和引用队列(ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。程序如果发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取必要的行动。

特别注意,在程序设计中一般很少使用弱引用与虚引用,使用软引用的情况较多,这是因为软引用可以加速 JVM 对垃圾内存的回收速度,可以维护系统的运行安全,防止内存溢出(OutOfMemory)等问题的产生

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/445081.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

算法(2)-二叉树的遍历(递归/迭代)python实现

二叉树的遍历1.深度优先DFS1.1 DFS 递归解法1.1.1先序遍历1.1.2中序遍历1.1.3后序遍历1.2 DFS迭代解法1.2.1先序遍历1.2.2中序遍历1.2.3后序遍历2.广度优先BFS3.二叉树的最大深度3.1递归3.2迭代4.翻转二叉树4.1递归4.1迭代5.合并两棵二叉树5.1递归5.2迭代有两种通用的遍历树的策…

利用posix_fadvise清理系统中的文件缓存

利用posix_fadvise清理系统中的文件缓存leoncom c/c,unix2011-08-03当我们需要对某段读写文件并进行处理的程序进行性能测试时,文件会被系统cache住从而影响I/O的效率,必须清理cache中的对应文件的才能正确的进行性能测试。通常清理内存可以采用下面的这…

空间分配

目前主流的垃圾收集器都会采用分代回收算法,因此需要将堆内存分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。 大多数情况下,对象在新生代中 eden 区分配。当 eden 区没有足够空间进行分配时,虚拟…

创建与打开IPC通道的POSIX和SYSTEM V方法

先说POSIX的吧: mq_open,sem_open,shm_open着三个函数用于创建或者打开一个IPC通道。 由此可见,消息队列的读写权限是任意的,然而信号灯就没有,…

软件测试基础知识

第一章 1.1 软件测试背景知识和发展史 互联网公司职位架构:产品 运营 技术 市场 行政软件测试:使用人工或自动化手段,来运行或测试某个系统的过程,其目的在于检验它是否满足规定的需求或弄清预期结果与实际结果之间的差别&#…

Jmeter-基础篇

常用压力测试工具对比 1、loadrunner 性能稳定,压测结果及细粒度大,可以自定义脚本进行压测,但是太过于重大,功能比较繁多 2、apache ab(单接口压测最方便) 模拟多线程并发请求,ab命令对发出负载的计算机…

shell一文入门通

简单来说“Shell编程就是对一堆Linux命令的逻辑化处理”。 W3Cschool 上的一篇文章是这样介绍 Shell的 hello world 学习任何一门编程语言第一件事就是输出HelloWord了!下面我会从新建文件到shell代码编写来说下Shell 编程如何输出Hello World。 (1)新建一个文件…

RPC编程

图 3 说明在客户机和服务器之间完成 RPC 涉及的步骤。 图 3. 在客户机和服务器之间完成 RPC 涉及的步骤服务器 RPC 应用程序初始化期间它会向 RPC 运行时库注册接口。需要注册接口是因为,客户机在向服务器发出远程过程调用时,要检查它是否与服务器兼容。…

synchronized使用和原理全解

synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种: 修饰一个方法 被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象; 修饰一个静态的方法 其作用的范围是整个…

算法(11)-leetcode-explore-learn-数据结构-链表的经典问题

leetcode-explore-learn-数据结构-链表31.反转一个链表2.移除链表元素3.奇偶链表4.回文链表5.小结本系列博文为leetcode-explore-learn子栏目学习笔记,如有不详之处,请参考leetcode官网:https://leetcode-cn.com/explore/learn/card/linked-l…

Linux线程池的设计

我设计这个线程池的初衷是为了与socket对接的。线程池的实现千变万化,我得这个并不一定是最好的,但却是否和我心目中需求模型的。现把部分设计思路和代码贴出,以期抛砖引玉。个人比较喜欢搞开源,所以大家如果觉得有什么需要改善的…

leetcode121买卖股票的最佳时机

给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。 注意你不能在买入股票前卖出股票。 示例 1: 输入: [7,1,5,3,6,…

epoll的内核实现

epoll是由一组系统调用组成。 int epoll_create(int size); int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout); select/poll的缺点在于&#xff1…

leetcode322 零钱兑换

给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。 示例 1: 输入: coins [1, 2, 5], amount 11 输出: 3 解释: 11 5 5 1 示例 2: 输入: coins [2],…

leetcode538 把二叉搜索树转换成累加树

给定一个二叉搜索树(Binary Search Tree),把它转换成为累加树(Greater Tree),使得每个节点的值是原来的节点值加上所有大于它的节点值之和。 对于每一个点来说,自己的父,和自己父的右子树都是大…

leetcode15 三数之和

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a b c 0 ?找出所有满足条件且不重复的三元组。 注意:答案中不可以包含重复的三元组。 例如, 给定数组 nums [-1, 0, 1,…

leetcode19. 删除链表的倒数第N个节点

给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。 示例: 给定一个链表: 1->2->3->4->5, 和 n 2. 当删除了倒数第二个节点后,链表变为 1->2->3->5. 说明: 给定的 n 保证是有效…

python模块(5)-Matplotlib 简易使用教程

Matplotlib简易使用教程0.matplotlib的安装1.导入相关库2.画布初始化2.1 隐式创建2.2 显示创建2.3 设置画布大小2.4 plt.figure()常用参数3.plt. 能够绘制图像类型3.1等高线3.2 箭头arrow4.简单绘制小demodemo1.曲线图demo2-柱状、饼状、曲线子图5.plt.plot()--设置曲线颜色,粗…

leetcode20 有效的括号

给定一个只包括 (,),{,},[,] 的字符串,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 注意空字符串可被认为是有效字符串。 示…

leetcode1 两数之和

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 示例: 给定 nums [2, 7, 11, 15], t…