Java种除了基本数据类型,其它数据类型都是引用的数据类型。而应用数据类型根据生命周期的长短又分为:强引用、弱引用、软引用和需引用(幻象引用),我们平时基本上只用到强引用类型,而其他的引用类型我们也就在面试中,或者平日阅读类库或其他框架源码的时候才能见到。

1.强引用

用到的new了一个对象就是强引用,例如 Object obj = new Object();

当JVM的内存空间不足时,宁愿抛出OutOfMemoryError使得程序异常终止也不会回收具有强引用的存活着的对象!

强引用对象回收:

当一个普通对象没有其他引用关系,只要超过了引用的作用域或者显示的将引用赋值为null时,你的对象就表明不是存活着,这样就会可以被GC回收了。当然回收的时间是不一定的具体得看GC回收策略。

2.软引用

软引用的生命周期比强引用短一些。软引用是通过SoftReference类实现的。

Object obj = new Object();

//SoftReference softObj = new SoftReference(obj);//转换为软引用

ReferenceQueue qu = new ReferenceQueue()

SoftReference softObj = new SoftReference(obj, qu);

obj = null; //去除强引用

这样就是一个简单的软引用使用方法。当JVM认为内存空间不足时,就回去试图回收软引用指向的对象,也就是说在JVM抛出OutOfMemoryError之前,会去清理软引用对象。软引用可以与引用队列(ReferenceQueue)联合使当softObj软引用的obj被GC回收之后,softObj 对象就会被塞到queue中,之后我们可以通过这个队列的poll()来检查你关心的对象是否被回收了,如果队列为空,就返回一个null。反之就返回软引用对象也就是softObj。软引用一般用来实现内存敏感的缓存,如果有空闲内存就可以保留缓存,当内存不足时就清理掉,这样就保证使用缓存的同时不会耗尽内存。例如图片缓存框架中缓存图片就是通过软引用的。

用途:比如考虑一个图像编辑器的程序。该程序会把图像文件的全部内容都读取到内存中,以方便进行处理。而用户也可以同时打开多个文件。当同时打开的文件过多的时候,就可能造成内存不足。如果使用软引用来指向图像文件内容的话,垃圾回收器就可以在必要的时候回收掉这些内存。

3.弱引用

Object obj = new Object();

WeakReference weakObj = new WeakReference(obj);

obj = null;

弱引用是通过WeakReference类实现的,它的生命周期比软引用还要短,也是通过get()方法获取对象。在GC的时候,不管内存空间足不足都会回收这个对象,同样也可以配合ReferenceQueue 使用,也同样适用于内存敏感的缓存。ThreadLocal中的key就用到了弱引用。

用途:

弱引用的作用在于解决强引用所带来的对象之间在存活时间上的耦合关系。弱引用最常见的用处是在集合类中,尤其在哈希表中。哈希表的接口允许使用任何Java对象作为键来使用。当一个键值对被放入到哈希表中之后,哈希表对象本身就有了对这些键和值对象的引用。如果这种引用是强引用的话,那么只要哈希表对象本身还存活,其中所包含的键和值对象是不会被回收的。如果某个存活时间很长的哈希表中包含的键值对很多,最终就有可能消耗掉JVM中全部的内存。

对于这种情况的解决办法就是使用弱引用来引用这些对象,这样哈希表中的键和值对象都能被垃圾回收。Java中提供了WeakHashMap来满足这一常见需求。

4.幻象引用

也称虚引用,是通过PhantomReference类实现的。任何时候可能被GC回收,就像没有引用一样。无法通过虚引用访问对象的任何属性或者函数。那就要问了要它有什么用?虚引用仅仅只是提供了一种确保对象被finalize以后来做某些事情的机制。比如说这个对象被回收之后发一个系统通知啊啥的。虚引用是必须配合ReferenceQueue 使用的,具体使用方法和上面提到软引用的一样。主要用来跟踪对象被垃圾回收的活动。

幽灵引用及其队列的使用情况并不多见,主要用来实现比较精细的内存使用控制,这对于移动设备来说是很有意义的。程序可以在确定一个对象要被回收之后,再申请内存创建新的对象。通过这种方式可以使得程序所消耗的内存维持在一个相对较低的数量。比如下面的代码给出了一个缓冲区的实现示例。

private byte[] data = new byte[0];

private ReferenceQueue queue = new ReferenceQueue();

private PhantomReference ref = new PhantomReference(data, queue);

public byte[] get(int size) {

if (size <= 0) {

throw new IllegalArgumentException("Wrong buffer size");

}

if (data.length < size) {

data = null;

System.gc(); //强制运行垃圾回收器

try {

queue.remove(); //该方法会阻塞直到队列非空

ref.clear(); //幽灵引用不会自动清空,要手动运行

ref = null;

data = new byte[size];

ref = new PhantomReference(data, queue);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

return data;

}

}

在上面的代码中,每次申请新的缓冲区的时候,都首先确保之前的缓冲区的字节数组已经被成功回收。引用队列的remove方法会阻塞直到新的幽灵引用被加入到队列中。不过需要注意的是,这种做法会导致垃圾回收器被运行的次数过多,可能会造成程序的吞吐量过低。

java 虚引用 作用_Java的强引用、弱引用、软引用和虚引用,以及用途相关推荐

  1. java引用队列_java的强引用、软引用、弱引用、幻象引用,引用队列总结

    java除了原始数据类型的变量,其他所有都是引用类型. 引用分为强引用.软引用.弱引用.幻象引用,这几种引用影响着对象的回收 强引用 强引用:形如Object object = new Object( ...

  2. java弱_Java 强、弱、软、虚,你属于哪一种?

    Java技术栈 www.javastack.cn 打开网站看更多优质文章 作者:CodeBear的园子 来源:www.cnblogs.com/CodeBear/p/12447554.html Java ...

  3. java int 传引用吗_Java的参数传递是「值传递」还是「引用传递」?

    关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题. 有人说Java中只有值传递,也有人说值传递和引用传递都是存在的,比较容易让人产生疑问. 关于值传递和引用传递其实需要分情况看待. ...

  4. Java 强、弱、软、虚,你属于哪一种?

    作者:CodeBear的园子 来源:www.cnblogs.com/CodeBear/p/12447554.html Java中的四种引用 Java中有四种引用类型:强引用.软引用.弱引用.虚引用. ...

  5. java关键字的作用_java关键字及其作用

    java关键字及其作用 java 关键字及其作用 一. 关键字总览:关键字 含义abstract 表明类或者成员方法具有抽象属性assert 用来进行程序调试boolean 基本数据类型之一,布尔类型 ...

  6. java 嵌套类 作用_java 嵌套类的分类、为什么使用嵌套类?

    java程序语言允许你在一个类里面再声明另一个类,这样的类成为嵌套类,说明如下:class OuterClass { ... class NestedClass { ... } } 术语:嵌套类分为两 ...

  7. java new string作用_java中直接new String对象?

    首先明确一点,在Java中==比较的是两个对象的地址,equals()比较的是两个对象的值,如果使用equals()来替换==,则两个输出结果都为true. 言归正传,为什么第一个返回为false? ...

  8. android的四种对象引用级别:强、弱、软、虚引用

    android中的强引用,弱引用,软引用,虚引用.代表了android中的对象引用级别,也即代表了java的垃圾回收机制,看可以简单理解为内存释放. 1.强引用:强引用是使用最普遍的引用.如果一个对象 ...

  9. java对象序列化作用_Java学习之——理解对象序列化

    Java的对象序列化就是把对象写入到输出流中,用来存储或传输:反序列化就是从输入流中读取对象.简单的来说是指将那些实现了Serializable接口的对象转换成一个字节序列,并能够在以后将这个字节序列 ...

最新文章

  1. cmd命令重定向到剪切板
  2. 云计算精华问答 | 边缘计算、雾计算、霾计算,它们究竟是什么?
  3. instagram架构_通过创建Instagram副本学习Laravel
  4. swift笔记1-点语法
  5. java系列5:如何使用创建的类
  6. Android 项目必备(四十一)-->Android 开发实战经验总结
  7. 极客导航 - 建站教程的背景
  8. 有限元计算软件Fenics安装使用笔记(2)
  9. Tar的详细用法(转自Linux伊甸园)
  10. 少量代码完成火山图绘制
  11. IAST安全扫描原理
  12. 用JavaScript写一个鼠标悬停变色事件
  13. android第三方拨号盘,Android开发-教你如何使用拨号盘
  14. 河北官方:邯郸涉县致4死5伤煤气泄漏事故涉嫌瞒报
  15. 丰巢“羊毛”,出在快递身上,让用户买单!
  16. 信号满格怎么显示无法连接服务器,Win7 32系统网络信号满格却无法连接上网怎么处理...
  17. 今天做了个5.1倒计时牌
  18. 手机开发实战99——MMS介绍6
  19. [MFC] 高仿Flappy bird 桌面版
  20. 实验一 运算器实验

热门文章

  1. 测试用例 集成测试增删改查_20年高级测试人员的进阶汇总
  2. oracle如何配置dns连接,图文详解添加DNS服务器的操作步骤
  3. data transformation python_Python数据分析(方睿)
  4. 戴口罩也能刷门禁?疫情下AnalyticDB亮出社区管理的宝藏神器!
  5. 《Stellaris》游戏分析报告
  6. OracleTimesten使用方法总结
  7. 经典文章解释apache与tomcat!看完秒懂
  8. Visual Studio 2008中常用快捷键
  9. Oracle技术牛人网站
  10. 前端三部曲之Html -- 1(html的基本结构和常见的meta标签的作用)