jvm-回收对象(二)

总所周知,Java将程序员从内存管理中解放出来,使得我们在编写代码的时候不用手动的分配和释放内存,内存管理的任务由JVM承担起来。本文就将讲解JVM在回收对象之前,如何判断一个对象是否应该被回收。

在此之前,我们先来复习一个和Java对象回收有关的知识,那便是finalize方法,这是一个在Object类中定义的方法,如果我们重写了finalize方法,那么在对象被回收之前将会调用finalize方法,如果我们在finalize方法中将对象和某个还在生命周期的对象关联上,那么这个对象还有可能在回收之前被复活,当然这种机会只有一次,当第二次遇到回收时,将不会再调用finalize方法。

下面我们正式介绍Java对象是否存活的判断算法——根搜索算法。这个算法的思路其实很简单,它把内存中的每一个对象都看作一个节点,并且定义了一些对象作为根节点“GC Roots”。如果一个对象中有另一个对象的引用,那么就认为第一个对象有一条指向第二个对象的边,如下图所示。JVM会起一个线程从所有的GC Roots开始往下遍历,当遍历完之后如果发现有一些对象不可到达,那么就认为这些对象已经没有用了,需要被回收。
在这里插入图片描述
JVM如何判断一个Java对象是否可以回收

根搜索算法图解

这个算法的关键就在于GC Roots的定义,教科书中给出了四种作为GC Roots的对象,首先第一种是虚拟机栈中的引用的对象,我们在程序中正常创建一个对象,对象会在堆上开辟一块空间,同时会将这块空间的地址作为引用保存到虚拟机栈中,如果对象生命周期结束了,那么引用就会从虚拟机栈中出栈,因此如果在虚拟机栈中有引用,就说明这个对象还是有用的,这种情况是最常见的。第二种是我们在类中定义了全局的静态的对象,也就是使用了static关键字,由于虚拟机栈是线程私有的,所以这种对象的引用会保存在共有的方法区中,显然将方法区中的静态引用作为GC Roots是必须的。第三种便是常量引用,就是使用了static final关键字,由于这种引用初始化之后不会修改,所以方法区常量池里的引用的对象也应该作为GC Roots。最后一种是在使用JNI技术时,有时候单纯的Java代码并不能满足我们的需求,我们可能需要在Java中调用C或C++的代码,因此会使用native方法,JVM内存中专门有一块本地方法栈,用来保存这些对象的引用,所以本地方法栈中引用的对象也会被作为GC Roots。

至此,我们已经了解了平时生成的大部分对象是如何被JVM标记为可回收的。但是在Java中,还存在一些其它的情况,这就要从引用讲起了。我们平时使用的Java对象通常认为只有两种状态,一种是被引用了,在程序中还在使用,另一种是没有被引用,可以被JVM回收。但实际上,Java中的引用一共有四种,它们分别是强引用、软引用、弱引用和虚引用,下面我们来分别介绍。

首先来说说强引用,强引用就是我们平常用的类似于“Object obj = new Object()”的引用,只要obj的生命周期没结束,或者没有显示地把obj指向为null,那么JVM就永远不会回收这种对象。

软引用相对强引用来说就要脆弱一点,JVM正常运行时,软引用和强引用没什么区别,但是当内存不够用时,濒临逸出的情况下,JVM的垃圾收集器就会把软引用的对象回收。在JDK中提供了SoftReference类来实现软引用,如下图的代码示例所示:
在这里插入图片描述
JVM如何判断一个Java对象是否可以回收

软引用代码示例

如上图代码,我们定义了SoftReferenceTest类,并重写了finalize方法,在main方法中我们往一个list里不断加值,使程序出现内存逸出的可能,只要我们将while循环中的阈值调大,就会输出finalize方法中的内容,调小就不会输出,下图便是调大时的输出。由于软引用自身的特点,所以比较适合作为应用的缓存。
在这里插入图片描述
JVM如何判断一个Java对象是否可以回收

软引用代码输出

弱引用比软引用更加脆弱,弱引用的对象将会在下一次的gc被回收,不管JVM内存被占用多还是少。在JDK中使用WeakReference来实现弱引用,代码示例如下图所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200701152950991.png

JVM如何判断一个Java对象是否可以回收

弱引用代码示例

上图代码中我们显示执行了一次gc,弱引用将会被回收,执行结果如下图:
在这里插入图片描述

JVM如何判断一个Java对象是否可以回收

弱引用代码输出

虚引用是最脆弱的引用,我们没有办法通过一个虚引用来获得对象,即使在没有gc之前。虚引用需要和一个引用队列配合使用,在JDK中提供了PhantomReference来实现虚引用,代码示例如下图:
在这里插入图片描述
JVM如何判断一个Java对象是否可以回收

虚引用代码示例

由于虚引用没有办法访问对象实例,所以我们无法通过对象实例来判断是否被回收,但是我们传入引用队列,在对象被真正清除时,将会被加入到引用队列中,referenceQueue.remove(2000)将会阻塞2秒等待对象入队列,并移除打印。可以看下图输出,可以看出第一次gc虽然执行了finalize方法,但是对象并没有马上被清除,而是在第二次gc的时候才真正被清除。这是由于PhantomReference的处理过程和上面的引用不同,如果重写了finalize方法,那么必须保证finalize方法运行完之后才能加入引用队列,所以如果将代码中的finalize方法取掉,那么在第一次gc之后就可以加入到引用队列。
在这里插入图片描述
JVM如何判断一个Java对象是否可以回收

虚引用代码输出

链接:https://blog.csdn.net/u011277123/article/details/53908315

热门文章

暂无图片
编程学习 ·

Unity性能优化之 Profiler

Profiler主界面 打开方法为上方工具条 Windows-Analysis-Profiler(我也正在学习此功能使用,如有那部分错了还请指出QVQ)左上角可以勾选我们要查看的部分 这里以内存和CPU做演示,选中左边的Memory后下方的内容框就会变化如图 unity会在运行时自动获取每一帧的内存占用数据项…
暂无图片
编程学习 ·

3D打印与互联网发展的探索

“互联网+3D打印+创意文化”模式崭露头角 互联网具备大众属性,3D打印技术及服务或许能结合互联网带来更多创新,通过互联网渠道带来全流程的在线、交互体验、互联网化来实时响应消费用户需求形成新的商业模式。 近日,国内一家3D打印综合性服务平台已悄然上线,为消费用户提供…
暂无图片
编程学习 ·

通过组键扫描使得Spring管理类的对象

通过组件扫描使得Spring管理类的对象。 如果User类需要使用Spring框架管理,必须声明User类所在的包,然后再用测试类中的AnnotationConfigApplicationContext的构造方法中将包名作为参数():import org.springframework.context.annotation.AnnotationConfigApplicationContex…
暂无图片
编程学习 ·

leetcode-123. 买卖股票的最佳时机 III

题目 给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。 注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。 示例 1: 输入: [3,3,5,0,0,3,1,4] 输出: 6 解释: 在第 4…
暂无图片
编程学习 ·

如何更好的使用大数据

在互联网时代,依靠大数据是未来的发展趋势。大数据分析现在非常流行,但是我们需要知道的是,大数据的价值体现在有效而正确的分析中。只有通过正确有效的分析工具和分析方法来解释现有的大数据,大数据才能为我们带来有价值的结果。今天,中琛魔方将教您如何有效运用大数据。…
暂无图片
编程学习 ·

如何重命名data.frame中的单个列?

本文翻译自:How to rename a single column in a data.frame? I know if I have a data frame with more than 1 column, I can use 我知道如果我有一个多于一列的数据框,我可以使用 colnames(x) <- c("col1","col2")to rename the columns. 重命名…
暂无图片
编程学习 ·

使用python下载文件

使用requestspython 3.71 下载指定文件 import requestsurl = https://images.jjxsw.la/images/mijjxswcom.gif req = requests.get(url) with open(a.swf, wb) as code:code.write(req.content)
暂无图片
编程学习 ·

git使用(二)部署本地项目到github

部署本地项目到github 初始化 打开Git Bash。 cd到项目文件夹。(直接把文件夹拖入到bash内即可) 执行初始化代码 git init项目文件夹会产生一个.git的文件夹 跟github仓库进行连接 格式:git remote add origin url地址(https或ssh)例如:git remote add origin git@github…
暂无图片
编程学习 ·

神经网络架构搜索——可微分搜索 (Noisy-DARTS)

神经网络架构搜索——可微分搜索 (Noisy-DARTS)动机FairDARTS: Sigmoid函数替换Softmax函数NoisyDARTS:skip-connection注入噪声方法实现如何加噪声?加入怎样的噪声?实验结果架构参数可视化CIFAR-10实验结果ImageNet实验结果消融实验有噪声 vs. 无噪声无偏噪声 vs. 有偏噪…
暂无图片
编程学习 ·

面向对象到底是什么

面向对象编程OOP,全称 Object Oriented Programming两个基础概念:类(class)和对象(object)一种编程范式或编程风格。它以类或对象作为组织代码的基本单元,并将封装、抽象、继承、多态四个特性,作为代码设计和实现的基石面向对象编程语言OOPL,全称 Object Oriented Pro…
暂无图片
编程学习 ·

centos误操作mv /* ../后恢复方法(二)

接上一篇文章:centos误操作mv /* ../后恢复方法(一)https://blog.csdn.net/hduxg/article/details/107066127我们已经把文件恢复并拷贝到了其他服务器上,目前暂时安全,这里来探索一下原因。我打开了之前误操作的目录,发现bin、boot、dev、etc,都被剪切到里面了。于是我又重…
暂无图片
编程学习 ·

排序算法之插入排序、希尔排序、归并排序(C#)

插入排序 两次for循环,外层从数组第二位i=1开始,内层for循环由i向前进行判断,大于则将该位置与遍历位置交换。此时注意,不能按i的位置获取元素,应将该元素暂存,因为交换时对应i位置元素值会变换。c#代码如下/// <summary>/// 插入排序/// </summary>/// <…
暂无图片
编程学习 ·

linux usb usbip驱动详解(二)

终于来到usbip驱动代码分析了!我们在做产品时,通常是先讨论方案、制定协议、编码和测试。usbip的方案是行得通的,它是从URB对象获取信息,然后从tcp发送出去的,URB是linux usb子系统里面用于抽象usb通信而精心设计的对象,只要server和client两边在恰当的时机分别隔断各自系…
暂无图片
编程学习 ·

Java语言基础(二)变量和数据类型

Java语言基础(二)二、变量和数据类型2.1 变量的基本概念2.2 变量的声明和使用2.3 变量使用是注意事项2.4 标识符的命名规则(笔试)关键字2.5 变量输入输出的案例实现2.6 变量输入输出案例的优化和手册介绍2.7 数据类型的分类2.8 常用的进制2.9 十进制与二进制之间的转换(1)正…
暂无图片
编程学习 ·

Volatile关键字

volatile关键字 volatile 关键字是java提供的一种轻量级同步机制。他能够保证可见性和有序性,但是不能保证原子性。 volatile可见性 可见性表示被这个关键字所修饰的实例,在被修改后,其他的线程均可见。```javaclass MyData { // 如果没有volatile关键字的话,那我们在修…
暂无图片
编程学习 ·

Netty-为什么选择 Netty

人工智能,零基础入门!http://www.captainbed.net/inner API 使用简单,开发门槛低;功能强大,预置了多种编解码功能,支持多种主流协议;定制能力强,可以通过 ChannelHandler 对通信框架进行灵活的扩展;性能高,通过与其它业界主流的 NIO 框架对比,Netty 的综合性能最优;…
暂无图片
编程学习 ·

LeetCode高频面试题记录

LeetCode高频面试题记录 K 个一组翻转链表 困难 class Solution { public:ListNode* reverseKGroup(ListNode* head, int k) {if (head == NULL) return NULL;ListNode *a = head;ListNode *b = head;for (int i = 0; i < k; i++) {//判断是否满足一组kif (b == NULL) retur…
暂无图片
编程学习 ·

VINS-Mono理论推导1

ReferenceVINS-Mono: A Robust and Versatile Monocular Visual-Inertial State Estimator. Quaternion Kinematics for Error-State KF. 预积分的推导 预积分是VINS-Mono中十分重要的一个步骤,主要涉及的是IMU的运动方程,下面对这部分进行一个简单的推导,主要使用的是ESKF…
暂无图片
编程学习 ·

目标跟踪环境配置(四):OTB配置安装 (从下载到绘图)

目标跟踪基础与智能前沿 点击上方链接,微信关注回复下方安装包对应的关键词,获得对应的百度云下载链接 论文原文 1) Online Object Tracking: A Benchmark 1、下载OTB数据集 1)官网下载地址(国内网速原因很慢): 2)百度云下载地址: 自动回复关键词“OTB” 2、预先安…