在 java 中, 大致有以下几种引用类型, 强引用(StrongReference), 软引用(SoftReference), 弱引用(WeakReference), 虚引用(PhantomReference)
--- 强引用 - FinalReference
强引用是平时最常见的, 类似诸如
String a = new String("helloworld");
这个 a 就是强引用类型, 最主要的一点是: 即使内存不够, 程序宁愿抛出异常, 也不会去进行回收
--- 软引用 - SoftReference
软引用 (softReference) 在强度上弱于强引用, 通过类 SoftReference 来表示. 它的作用是告诉垃圾回收器, 程序中的哪些对象是不那么重要, 当内存不足的时候是可以被暂时回收的. 当 JVM 中的内存不足的时候, 垃圾回收器会释放那些只被软引用所指向的对象. 如果全部释放完这些对象之后, 内存还不足, 才会抛出 OutOfMemory 错误. 软引用非常适合于创建缓存. 当系统内存不足的时候, 缓存中的内容是可以被释放的.
比如考虑一个图像编辑器的程序. 该程序会把图像文件的全部内容都读取到内存中, 以方便进行处理. 而用户也可以同时打开多个文件. 当同时打开的文件过多的时候, 就可能造成内存不足. 如果使用软引用来指向图像文件内容的话, 垃圾回收器就可以在必要的时候回收掉这些内存.
--- 弱引用 - WeakReference
弱引用的强度弱于软引用, 简单来说就是, 一旦某个引用不需要使用的时候, JVM 就会自动回收, 而程序员本身无须做其他操作, 在 Java 源码中的 java.util.WeakHashMap 中的 key 就是使用弱引用
--- 虚引用 - PhantomReference
在介绍虚引用之前, 要先介绍 Java 提供的对象终止化机制 (finalization). 在 Object 类里面有个 finalize 方法, 其设计的初衷是在一个对象被真正回收之前, 可以用来执行一些清理的工作. 因为 Java 并没有提供类似 C++ 的析构函数一样的机制, 就通过 finalize 方法来实现. 但是问题在于垃圾回收器的运行时间是不固定的, 以这些清理工作的实际运行时间也是不能预知的. 虚引用(phantom reference) 可以解决这个问题. 在创建虚引用 PhantomReference 的时候必须要指定一个引用队列. 当一个对象的 finalize 方法已经被调用了之后, 这个对象的虚引用会被加入到队列中. 通过检查该队列里面的内容就知道一个对象是不是已经准备要被回收了.
举个栗子
- package com.xxg;
- import java.io.Serializable;
- import java.lang.ref.PhantomReference;
- import java.lang.ref.ReferenceQueue;
- import java.lang.ref.SoftReference;
- import java.lang.ref.WeakReference;
- public class PhantomBuffer {
- public static void main(String[] args) throws InterruptedException {
- // 强引用类型: 变量 strongReference 对对象的引用为强引用
- User strongReference = new User("strongReference");
- System.out.println(strongReference.getName()); //strongReference
- // 弱引用类型: 变量 weakReference 对对象的引用为弱引用
- WeakReference<User> weakReference = new WeakReference<User>(new User("weakReference"));
- System.out.println(weakReference.get().getName()); //weakReference
- // 弱引用测试
- System.out.println(weakReference.get());//user 对象
- System.gc();// 调用 jvm 垃圾回收器(不一定立即执行)
- Thread.sleep(10000);// 阻塞线程 10 秒, 等待 gc 执行
- System.out.println(weakReference.get()); //null
- // 软引用类型: 变量 softReference 对对象的引用为软引用
- SoftReference<User> softReference = new SoftReference<User>(new User("softReference"));
- System.out.println(softReference.get().getName()); //softReference
- System.out.println(softReference.get()); //com.xxg.PhantomBuffer$User@6d06d69c
- // 虚引用类型:
- PhantomReference<User> phantomReference = new PhantomReference<User>(new User("phantomReference"), new ReferenceQueue<>());
- System.out.println(phantomReference.get()); //null
- }
- static class User implements Serializable{
- private static final long serialVersionUID = 1L;
- private String name;
- public User(String name){
- this.name = name;
- }
- public String getName(){
- return name;
- }
- public void setName(String name)
- {
- this.name = name;
- }
- }
- }
参考资料: Java 四种引用介绍及使用场景
来源: http://www.bubuko.com/infodetail-2909551.html