java虚引用作用_深入理解Java中的引用(二)——强软弱虚引用

深入理解Java中的引用(二)——强软弱虚引用

在上一篇文章中介绍了Java的Reference类,本篇文章介绍他的四个子类:强引用、软引用、弱引用、虚引用。

强引用(StrongReference)

强引用是我们在代码中最普通的引用。示例代码如下:

Object o = new Object(); // 强引用

在JVM的GC算法中,如果一个对象具有强引用,那么JVM宁可抛出Out of Memory错误,垃圾回收器也不会去回收这个对象。

当在代码里显示的写o = null,或者该对象的引用作用域是在一个函数里,代码如下,当线程调用完test,就会退出方法栈,引用不存在,垃圾回收器才会在某个时刻回收Object对象。

public void test(){

Object o = new Object(); // 强引用

}

软引用(SoftReference)

如果一个对象有一个软引用,那么在内存足够的情况下,该对象就不会被垃圾回收器回收。网上有很多资料说软引用只会在内存空间不够用的情况下对象才会被回收。 那么什么时候才是内存不够用呢?

首先看一下SoftReference类的源码可以看到有两个字段。这两个字段的作用已经标注,这与JVM GC有什么关系呢?

/**

* 记录最近一次被GC的时间。

*/

static private long clock;

/**

* 每次调用get方法的时候更新

* 记录当前Reference最近一次被访问的时间

*/

private long timestamp;

一起看一下HotSpot的源码,对于软引用的回收策略见下面should_clear_reference函数。

// The oop passed in is the SoftReference object, and not

// the object the SoftReference points to.

bool LRUMaxHeapPolicy::should_clear_reference(oop p,

jlong timestamp_clock) {

jlong interval = timestamp_clock - java_lang_ref_SoftReference::timestamp(p);

assert(interval >= 0, "Sanity check");

// The interval will be zero if the ref was accessed since the last scavenge/gc.

if(interval <= _max_interval) {

return false;

}

return true;

}

上述代码中interval表示当前引用存活了多久。他的值就是对应上述java代码中的clock与timestamp相减。interval与_max_interval比较,如果大于 _max_interval,那么就和弱引用一样处理,如果小于就当做强引用处理。_max_interval的赋值函数如下:

// Capture state (of-the-VM) information needed to evaluate the policy

void LRUMaxHeapPolicy::setup() {

size_t max_heap = MaxHeapSize;

max_heap -= Universe::get_heap_used_at_last_gc();

max_heap /= M;

_max_interval = max_heap * SoftRefLRUPolicyMSPerMB;

assert(_max_interval >= 0,"Sanity check");

}

通过源码可见首先是max_heap减去上次GC之后剩余堆大小,如果上次GC之后还有很多剩余空间,说明内存空间不够用了,那么max_heap的值就越小,相应_max_interval也越小,软引用就越可能被回收。

软引用的一个作用是实现内存敏感的高速缓存。比如浏览器的后退按钮,

(1)如果网页浏览结束就进行内容的回收,则按后退查看前面浏览过的页面时,需要重新构建。

(2)如果将浏览过的网页存储到内存中会造成内存的大量浪费,甚至会造成内存溢出。

通过软引用可以解决该问题

Browser prev = new Browser(); // 获取页面进行浏览

SoftReference sr = new SoftReference(prev); // 浏览完毕后置为软引用

if(sr.get()!=null){

rev = (Browser) sr.get(); // 还没有被回收器回收,直接获取

}else{

prev = new Browser(); // 由于内存吃紧,所以对软引用的对象回收了

sr = new SoftReference(prev); // 重新构建

}

弱引用(WeakReference)

只具有弱引用的对象生命周期更短。当垃圾回收器发现了只有弱引用的对象时候,无论内存空间是否足够,都会被GC回收。当你偶尔需要引用某个对象,随时能获取该对象,但是不想介入该对象的生命周期的时候,就可以使用弱引用, 因为弱引用不会对对象的垃圾回收判断产生附加的影响。

当弱引用绑定的对象被垃圾回收的时候,JVM会把这个弱引用加入到相关联的ReferenceQueue中。

这里抛出两个问题:

(1)弱引用什么时候会被加入到ReferenceQueue中,由什么决定的呢?

(2)如果绑定的对象GC之后存活了下来,弱引用怎么知道这个对象的新地址呢?

第一种情况,GC扫描到只存在弱引用的时候就会把它放到链表里。还有第二种情况:一个对象既有强引用又有弱引用的情况

下面通过图片来解释上面两个问题:

e279b8b492aa

image.png

上图表示C同时存在两个引用:强引用A和弱引用B。

第一种情况:GC先扫描到A

这种情况下GC同时会扫描到C,A和C都会搬到Survivor区。然后扫描到B,发现B引用的C搬到到了新的Survivor,这个时候就把B也搬到Survivor,并把C的新地址更新到B,结果如下:

e279b8b492aa

image.png

第二种情况:GC先扫描到B

GC还是会先把B放到ReferenceQueue中,由于C还是存活的,所以B会被搬到Survivor中。然后扫描到A,A和C都会搬到Survivor中,GC结束的时候B所指向的对象就不对了,如下图所示

e279b8b492aa

image.png

该情况下会重新遍历ReferenceQueue,发现绑定的对象依然存活,C‘ 的指针是指向C的,于是就把B再指向C就可以了,同时因为C依然存活,把B从ReferenceQueue中移除。新的地址空间如下图所示:

e279b8b492aa

image.png

具体过程可以查看海纳知乎专栏。

虚引用(PhantomReference)

虚引用不会对对象的垃圾回收有任何附加影响,他与软引用和弱引用的一个区别在于:虚引用必须和引用队列 (ReferenceQueue)联合使用。查看他的构造方法可以看到必须与一个ReferenceQueue绑定,而且他的get方法返回的一直是null

public T get() {

return null;

}

public PhantomReference(T referent, ReferenceQueue super T> q) {

super(referent, q);

}

虚引用主要用在跟踪对象垃圾回收的状态。具体应用会在在下一节讲到DirectByteBuffer 与ThreadLoal回收的时候详细分析。

总结

关于强引用、软引用、弱引用与虚引用在垃圾回收时的区别可以用下图表示:

e279b8b492aa

image.png

下图总结了四种引用在其他方面的区别:

e279b8b492aa

image.png

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

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

相关文章

ruby 爬虫爬取拉钩网职位信息,产生词云报告

思路&#xff1a;1.获取拉勾网搜索到职位的页数 2.调用接口获取职位id 3.根据职位id访问页面&#xff0c;匹配出关键字 url访问采用unirest&#xff0c;由于拉钩反爬虫&#xff0c;短时间内频繁访问会被限制访问&#xff0c;所以没有采用多线程&#xff0c;而且每个页面访问时间…

idle扩展插件_Python3.4学习笔记之 idle 清屏扩展插件用法分析

本文实例讲述了Python3.4 idle 清屏扩展插件用法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;python idle 清屏问题的解决&#xff0c;使用python idle都会遇到一个常见而又懊恼的问题——要怎么清屏?在stackoverflow看到这样两种答案&#xff1a;1.在shell中输入…

内存堆和栈的区别

原文链接&#xff1a;http://www.cnblogs.com/lln7777/archive/2012/03/14/2396164.html -------------------------------------------------------------------------------- 在计算机领域&#xff0c;堆栈是一个不容忽视的概念&#xff0c;我们编写的C语言程序基本上都要用…

MYSQL安装和配置

Win10安装MySQL5.7.22 解压缩版&#xff08;手动配置 1.下载地址&#xff1a;https://dev.mysql.com/downloads/mysql/5.7.html#downloads 直接点击下载项 下载后&#xff1a; 2.可以把解压的内容随便放到一个目录&#xff0c;我的是如下目录&#xff08;放到C盘的话&#xff0…

apply()与call()的区别

一直都没太明白apply()与call()的具体使用原理&#xff0c;今日闲来无事&#xff0c;决定好好研究一番。 JavaScript中的每一个Function对象都有一个apply()方法和一个call()方法&#xff0c;它们的语法分别为&#xff1a; /*apply()方法*/ function.apply(thisObj[, argArray]…

java代码执行了两次_Java中JComboBox的itemStateChanged事件执行两次的解释

今天做项目&#xff0c;用到了JComboBox&#xff0c;即下拉列表框。为了在被选中的项发生改变时获得被选中的项&#xff0c;所以使用的ItemStateChanged事件&#xff0c;可是问题就来了&#xff0c;每次触发该事件&#xff0c;它都执行两次&#xff0c;屡试不爽。一开始以为是代…

spring与mybatis三种整合方法

原文链接&#xff1a;http://www.cnblogs.com/wangmingshun/p/5674633.html ------------------------------------------------------------------------------------------------- 1、采用MapperScannerConfigurer&#xff0c;它将会查找类路径下的映射器并自动将它们创建成…

please select a vaild python interpret

当 JetBrains PyCharm 2017.1.3 x64 遇到 please select a vaild python interpret 错误时&#xff1a; 进入PyCharm setting 选项&#xff0c;搜索 interpret

Grafana分析Nginx日志

配置Groub by -Terms时报错&#xff0c;提示需要设置fielddatatrue&#xff0c;报错内容大概如下&#xff1a; "Fielddata is disabled on text fields by default ... " 解决方法如下&#xff1a; https://www.elastic.co/guide/en/elasticsearch/reference/curren…

IDEA 更换主题

1、下载主题文件 百度或者谷歌 IDEA themes 网址有可能会变化。目前是 http://color-themes.com 选择自己喜欢的颜色&#xff0c;下载。 2、导入主题文件 File----Import Setting 导入下载的jar文件&#xff0c;一路确认&#xff0c;idea会自动重启。 3、选择主题 点击…

【CentOS 7笔记】cp、mv、文档查看方式

2019独角兽企业重金招聘Python工程师标准>>> 一. copy 常用cp -r/R #拷贝目录&#xff0c;递归 cp -i #覆盖时会提示&#xff0c;默认项 cp -p #保留源目录或源文件的属性 cp -b #源文目与目的文目建立链接&#xff0c;链接 cp -f #强制覆盖 cp -v …

php 情书,php趣味编程 - php输出笛卡尔情书的秘密

/*笛卡尔情书的秘密心形图案的实现。重点是心形函数ra(1-sin),据说这是笛卡尔死前寄出的最后一封情书内容。这里面隐藏着一个刻骨铭心的秘密&#xff1b;“一生只为等待能手绘这个函数给我的人”*/$width 500;$height 500;header("Content-type: image/gif");$img …

015. 深入JVM学习—Java引用类型

2019独角兽企业重金招聘Python工程师标准>>> 1. 引用类型划分 强引用&#xff1a;当内存不足时&#xff0c;JVM宁可出现“OutOfMemoryError”错误停止&#xff0c;也需要进行保存&#xff0c;并且不会将此空间回收。 软引用&#xff1a;当内存不足的时候&#xff0…

表正在被别的用户或进程使用_linux内核对进程的管理分为两个方面

嵌入式开发直播课 - linux内核通知链 - 创客学院直播室​www.makeru.com.cn众所周知&#xff0c;现在的分时操作系统能够在一个CPU上运行多个程序&#xff0c;让这些程序表面上看起来是在同时运行的。linux就是这样的一个操作系统。在linux系统中&#xff0c;每个被运行的程序实…

android studio生成签名导打包的方法

原文链接&#xff1a;http://blog.csdn.net/l_215851356/article/details/69914213 ---------------------------------如果图片失效了&#xff0c;见有道云笔记------------------- 方法一&#xff1a; 在android中。可以非常快速的生成签名文件.jsk文件。步骤如下&#xff1…

vbs脚本延时_Wincc的脚本进程执行问题

接到某同事B的电话&#xff0c;说是一段Wincc里面的VBS脚本出现了问题&#xff1a;A按钮和B按钮&#xff0c;要求A按钮点击后&#xff0c;对plc某变量写1并等待5s后写0&#xff0c;在这5s期间如果点击B按钮&#xff0c;同样是对另外一个变量如此操作&#xff0c;则plc在5s内检测…

微信小程序 - 非Form数据怎么发送到后端?

通过设置异步缓存&#xff0c;就可以做到 wx.setStorageSync(imgs,imglist); 最后的提交信息&#xff1a;

DjangoAdmin站点调整列表页展示

调整列表页展示 1 页大小 每页中显示多少条数据&#xff0c;默认为每页显示100条数据&#xff0c;属性如下&#xff1a; list_per_page1001&#xff09;打开booktest/admin.py文件&#xff0c;修改AreaAdmin类如下&#xff1a; class BookInfoAdmin(admin.ModelAdmin):list_per…

大华热成像netsdkdemo_千年博物,智慧展馆丨大华股份全力守护“华夏珍宝库”...

陕西历史博物馆作为我国第一座大型现代化国家级博物馆&#xff0c;以及首批国家一级博物馆和全国排名前五的国家顶级博物馆&#xff0c;被誉为“古都明珠 华夏宝库”&#xff0c;是讲述五千年中华文化的大学堂&#xff0c;是我国博物馆事业发展的重要里程碑。随着陕西历史博物馆…

最新php常用函数200个,180多个PHP常用函数总结

我们知道任何有效的 php 代码都有可能出现在函数内部&#xff0c;甚至包括其它函数和类定义。本文我们主要和大家分享180多个PHP常用函数总结&#xff0c;希望能帮助大家更高效的学习PHP。数学函数1.abs(): 求绝对值$abs abs(-4.2); //4.211输入: 数字输出: 绝对值数字2.ceil(…