一、背景


Java的内存回收不需要程序员负责,JVM会在必要时启动Java GC完成垃圾回收。Java以便我们控制对象的生存周期,提供给了我们四种引用方式,引用强度从强到弱分别为:强引用、软引用、弱引用、虚引用。

二、简介


1. 强引用 StrongReference

StrongReference是Java的默认引用形式,使用时不需要显示定义。任何通过强引用所使用的对象不管系统资源有多紧张,Java GC都不会主动回收具有强引用的对象。

public class StrongReferenceTest {public static int M = 1024*1024;public static void printlnMemory(String tag){Runtime runtime = Runtime.getRuntime();int M = StrongReferenceTest.M;System.out.println("\n"+tag+":");System.out.println(runtime.freeMemory()/M+"M(free)/" + runtime.totalMemory()/M+"M(total)");}public static void main(String[] args){StrongReferenceTest.printlnMemory("1.原可用内存和总内存");//实例化10M的数组并与strongReference建立强引用byte[] strongReference = new byte[10*StrongReferenceTest.M];StrongReferenceTest.printlnMemory("2.实例化10M的数组,并建立强引用");System.out.println("strongReference : "+strongReference);System.gc();StrongReferenceTest.printlnMemory("3.GC后");System.out.println("strongReference : "+strongReference);//strongReference = null;后,强引用断开了strongReference = null;StrongReferenceTest.printlnMemory("4.强引用断开后");System.out.println("strongReference : "+strongReference);System.gc();StrongReferenceTest.printlnMemory("5.GC后");System.out.println("strongReference : "+strongReference);}
}

运行结果:

2. 弱引用 WeakReference

如果一个对象只具有弱引用,无论内存充足与否,Java GC后对象如果只有弱引用将会被自动回收。

public class WeakReferenceTest {public static int M = 1024*1024;public static void printlnMemory(String tag){Runtime runtime = Runtime.getRuntime();int M = WeakReferenceTest.M;System.out.println("\n"+tag+":");System.out.println(runtime.freeMemory()/M+"M(free)/" + runtime.totalMemory()/M+"M(total)");}public static void main(String[] args){WeakReferenceTest.printlnMemory("1.原可用内存和总内存");//创建弱引用WeakReference<Object> weakRerference = new WeakReference<Object>(new byte[10*WeakReferenceTest.M]);WeakReferenceTest.printlnMemory("2.实例化10M的数组,并建立弱引用");System.out.println("weakRerference.get() : "+weakRerference.get());System.gc();StrongReferenceTest.printlnMemory("3.GC后");System.out.println("weakRerference.get() : "+weakRerference.get());}
}

运行结果:

3. 软引用 SoftReference

软引用和弱引用的特性基本一致, 主要的区别在于软引用在内存不足时才会被回收。如果一个对象只具有软引用,Java GC在内存充足的时候不会回收它,内存不足时才会被回收。

public class SoftReferenceTest {public static int M = 1024*1024;public static void printlnMemory(String tag){Runtime runtime = Runtime.getRuntime();int M = StrongReferenceTest.M;System.out.println("\n"+tag+":");System.out.println(runtime.freeMemory()/M+"M(free)/" + runtime.totalMemory()/M+"M(total)");}public static void main(String[] args){SoftReferenceTest.printlnMemory("1.原可用内存和总内存");//建立软引用SoftReference<Object> softRerference = new SoftReference<Object>(new byte[10*SoftReferenceTest.M]);SoftReferenceTest.printlnMemory("2.实例化10M的数组,并建立软引用");System.out.println("softRerference.get() : "+softRerference.get());System.gc();SoftReferenceTest.printlnMemory("3.内存可用容量充足,GC后");System.out.println("softRerference.get() : "+softRerference.get());//实例化一个4M的数组,使内存不够用,并建立软引用//free=10M=4M+10M-4M,证明内存可用量不足时,GC后byte[10*m]被回收SoftReference<Object> softRerference2 = new SoftReference<Object>(new byte[4*SoftReferenceTest.M]);SoftReferenceTest.printlnMemory("4.实例化一个4M的数组后");System.out.println("softRerference.get() : "+softRerference.get());System.out.println("softRerference2.get() : "+softRerference2.get());}
}

运行结果:

4. 虚引用 PhantomReference

从PhantomReference类的源代码可以知道,它的get()方法无论何时返回的都只会是null。所以单独使用虚引用时,没有什么意义,需要和引用队列ReferenceQueue类联合使用。当执行Java GC时如果一个对象只有虚引用,就会把这个对象加入到与之关联的ReferenceQueue中。

public class PhantomReferenceTest {public static int M = 1024*1024;public static void printlnMemory(String tag){Runtime runtime = Runtime.getRuntime();int M = PhantomReferenceTest.M;System.out.println("\n"+tag+":");System.out.println(runtime.freeMemory()/M+"M(free)/" + runtime.totalMemory()/M+"M(total)");}public static void main(String[] args) throws InterruptedException {PhantomReferenceTest.printlnMemory("1.原可用内存和总内存");byte[] object = new byte[10*PhantomReferenceTest.M];PhantomReferenceTest.printlnMemory("2.实例化10M的数组后");//建立虚引用ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();PhantomReference<Object> phantomReference = new PhantomReference<Object>(object,referenceQueue);PhantomReferenceTest.printlnMemory("3.建立虚引用后");System.out.println("phantomReference : "+phantomReference);System.out.println("phantomReference.get() : "+phantomReference.get());System.out.println("referenceQueue.poll() : "+referenceQueue.poll());//断开byte[10*PhantomReferenceTest.M]的强引用object = null;PhantomReferenceTest.printlnMemory("4.执行object = null;强引用断开后");System.gc();PhantomReferenceTest.printlnMemory("5.GC后");System.out.println("phantomReference : "+phantomReference);System.out.println("phantomReference.get() : "+phantomReference.get());System.out.println("referenceQueue.poll() : "+referenceQueue.poll());//断开虚引用phantomReference = null;System.gc();PhantomReferenceTest.printlnMemory("6.断开虚引用后GC");System.out.println("phantomReference : "+phantomReference);System.out.println("referenceQueue.poll() : "+referenceQueue.poll());}
}

运行结果:

三、小结


强引用是 Java 的默认引用形式,使用时不需要显示定义,是我们平时最常使用到的引用方式。不管系统资源有多紧张,Java GC都不会主动回收具有强引用的对象。 弱引用和软引用一般在引用对象为非必需对象的时候使用。它们的区别是被弱引用关联的对象在垃圾回收时总是会被回收,被软引用关联的对象只有在内存不足时才会被回收。 虚引用的get()方法获取的永远是null,无法获取对象实例。Java GC会把虚引用的对象放到引用队列里面。可用来在对象被回收时做额外的一些资源清理或事物回滚等处理。 由于无法从虚引获取到引用对象的实例。它的使用情况比较特别,所以这里不把虚引用放入表格进行对比。这里对强引用、弱引用、软引用进行对比:

引用类型 GC时JVM内存充足 GC时JVM内存不足
强引用 不被回收 不被回收
弱引用 被回收 被回收
软引用 不被回收 被回收

Java 中的四种引用类型相关推荐

  1. Java中的四种引用类型

    1.Java中四种引用类型:强软弱虚 面试:强引用和弱引用的区别? 1.1 强引用 普通变量赋值即为强引用,如 A a = new A(); 强引用的回收特点: 当内存空间不足,Java虚拟机宁愿抛出 ...

  2. java object 引用类型_java中的四种引用类型

    java中的四种引用类型 一.强引用 强引用是最常见的,把一个对象赋给一个引用变量,这个引用变量就是一个强引用.当一个对象被强引用变量引用时,他处于可达状态,它是不会被GC回收的,即使该对象以后永远不 ...

  3. Java 中的四种引用

    垃圾收集器与内存分配策略参考目录: 1.判断Java 对象实例是否死亡 2. Java 中的四种引用 3.垃圾收集算法 4. Java9中的GC 调优 5.内存分配与回收策略 在进行垃圾回收之前,虚拟 ...

  4. java中的四种代码块

    原文链接: java中的四种代码块_Munt的博客-CSDN博客_java中代码块 在java中用{}括起来的称为代码块,代码块可分为以下四种: 一.简介 1.普通代码块: 类中方法的方法体 2.构造 ...

  5. java 代码块_详解java中的四种代码块

    在java中用{}括起来的称为代码块,代码块可分为以下四种: 一.简介 1.普通代码块: 类中方法的方法体 2.构造代码块: 构造块会在创建对象时被调用,每次创建时都会被调用,优先于类构造函数执行. ...

  6. java ref 应用类型_Java中的四种引用类型比较

    1.引用的概念 引用这个概念是与JAVA虚拟机的垃圾回收有关的,不同的引用类型对应不同的垃圾回收策略或时机. 垃圾收集可能是大家感到难于理解的较难的概念之一,因为它并不能总是毫无遗漏地解决Java运行 ...

  7. java中引用类型_您真的了解Java中的4种引用类型吗?

    Java中提供了四个级别的引用:SoftReference,FinalReference,WeakReference和PhantomReference.在四种引用类型中,只有FinalReferenc ...

  8. Java中的四种Reference

    首先要大致了解 Java 的几种引用类型.如下图所示,JDK 1.2 之后新增了 Reference 的概念,给开发人员提供了与 GC 交互的一种渠道. <深入理解 Java 虚拟机>中对 ...

  9. java中有几种内部类,Java中的四种内部类

    四种内部类 在Java 中,可以将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类.广泛意义上的 内部类一般来说包括这四种:静态内部类.匿名内部类.成员内部类和局部内部类,下面我们一一介绍 ...

最新文章

  1. python 装饰器 参数-python装饰器的详细解析
  2. 云计算的认识和看法_云计算的个人理解与体会
  3. mixly编程怎样音乐_华人留学生开发首个古汉语编程语言,实现易经算命、圆周率计算,Github获赞14.7k...
  4. 将hadoop源代码导入eclipse
  5. ZOJ - 4114 Flipping Game(dp+组合数学)
  6. c# 获取当前活动窗口句柄,获取窗口大小及位置
  7. Could not open lock file /var/lib/apt/lists/lock - open (13: Permission denied)
  8. linux shell 原理,linux下shell的工作原理
  9. Visual Studio Code C++配置文件
  10. uwsgi03----直接部署
  11. redis多种模式部署(持续更新)
  12. HDU1401 Solitaire
  13. 我最喜爱的九位历史人物 - 曹操(Space搬家)
  14. 如何JOPtionPane的showConfirmDialog对话框button设置监视器
  15. 女孩不是拜金,是败给了生活
  16. JS复制input内容
  17. 华为领衔,“5G+摄像头”拿下双影帝,多家国产手机凭借拍照入围MWC最佳演员...
  18. docker 清理磁盘
  19. 将两个ISO文件挂载至同一个虚拟光驱
  20. 2021年智能制造工程设计与应用类赛项:离散行业自动化方向(1)

热门文章

  1. 8Manage PPM助力中投证券 项目管理向数字化转型
  2. mysql启动warning: World-writable config file
  3. 微信支付8·8无现金日超1亿人次、近70万家门店参与
  4. Oracle 表空间信息
  5. 【java】静态代码块
  6. 警告:failed to load the sqljdbc_auth.dll cause no sqljdbc_auth in java.library.path
  7. 傻瓜教程:asp.net(c#) 如何配置authentication,完成基于表单的身份验证
  8. 高效并发处理之libevent
  9. AIDL注意细节 简单Demo
  10. python knnsearch_sklearn之KNN详解+GridSearchCV使用方法