这篇文章非常棒:http://alinazh.blog.51cto.com/5459270/1276173

Java中四种引用:强、软、弱、虚引用

1.1、强引用
当我们使用new 这个关键字创建对象时,被创建的对象就是强引用,如Object object = new Object() 这个Object()就是一个强引用。如果一个对象具有强引用,垃圾回收器就不会去回收有强引用的对象,如当jvm内存不足时,具备强引用的对象,虚拟机宁可会报内存空间不足的异常来终止程序,也不会靠垃圾回收器去回收该对象来解决内存。

1.2、软引用

如果一个对象只具有软引用,则内存空间足够,垃圾回收器就不会回收它;

如果内存空间不足了,就会回收这些对象的内存。

只要垃圾回收器没有回收它,该对象就可以被程序使用。

软引用可用来实现内存敏感的高速缓存(下文给出示例)。

软引用可以和一个引用队列(ReferenceQueue)关联使用:

  1. String str = new String("test");
  2. ReferenceQueue<String> rq = new ReferenceQueue<>();
  3. SoftReference sf = new SoftReference(str,rq);

如果软引用(sf)所引用的对象(str)被垃圾回收器回收,Java虚拟机就会把这个软引用(sf)加入到与之关联的引用队列(rq)中,之后可以通过循环调用rq的poll()方法,来清除无用的软引用对象(sf)

如果软引用所引用的对象(str)还没有被垃圾回收器回收,则可以通过这个引用(sf)的get()方法重新获得对引用对象(str)的强引用.

1.3、弱引用
如果一个对象只具有弱引用,只要垃圾回收器在自己的内存空间中线程检测到了,就会立即被回收,对应内存也会被释放掉。相比软引用弱引用的生命周期要比软引用短很多。不过,如果垃圾回收器是一个优先级很低的线程,也不一定会很快就会释放掉软引用的内存。

通俗的来说就是:发生GC时必定回收弱引用指向的内存空间。

示例代码:

  1. public static void main(String[] args) {
  2. String string = new String("test");
  3. ReferenceQueue<String> rq = new ReferenceQueue<>();
  4. WeakReference<String> wr = new WeakReference<String>(string,rq);
  5. System.out.println(wr.get());
  6. string = null;
  7. System.gc();
  8. System.out.println(wr.get());
  9. }

运行结果:

  1. test
  2. null

1.4、虚引用

又称为幽灵引用或幻影引用,虚引用既不会影响对象的生命周期,也无法通过虚引用来获取对象实例,仅用于在发生GC时接收一个系统通知。

相关问题一、若一个对象的引用类型有多个,那到底如何判断它的可达性呢?其实规则如下:

  1. 单条引用链的可达性以最弱的一个引用类型来决定;
  2. 多条引用链的可达性以最强的一个引用类型来决定;

我们假设图2中引用①和③为强引用,⑤为软引用,⑦为弱引用,对于对象5按照这两个判断原则,路径①-⑤取最弱的引用⑤,因此该路径对对象5的引用为软引用。同样,③-⑦为弱引用。在这两条路径之间取最强的引用,于是对象5是一个软可及对象(当将要发生OOM时则会被回收掉)。

相关问题二、与引用相关联的引用队列的作用是什么

引用队列的作用:使用ReferenceQueue清除失去了引用对象的Reference(SoftReference,WeakReference等)
作为一个Java对象,SoftReference对象除了具有保存软引用的特殊性之外,也具有Java对象的一般性。所以,当软可及对象被回收之后,虽然这个SoftReference对象的get()方法返回null,但这个SoftReference对象已经不再具有存在的价值,需要一个适当的清除机制,避免大量SoftReference对象带来的内存泄漏。在java.lang.ref包里还提供了ReferenceQueue。如果在创建SoftReference对象的时候,使用了一个ReferenceQueue对象作为参数提供给SoftReference的构造方法,如:
  1. ReferenceQueue queue = new ReferenceQueue();
  2. SoftReference ref=new SoftReference(aMyObject, queue);
那么当这个SoftReference所软引用的aMyOhject被垃圾收集器回收的同时,ref所强引用的SoftReference对象被列入ReferenceQueue。也就是说,ReferenceQueue中保存的对象是Reference对象,而且是已经失去了它所软引用的对象的Reference对象。另外从ReferenceQueue这个名字也可以看出,它是一个队列,当我们调用它的poll()方法的时候,如果这个队列中不是空队列,那么将返回队列前面的那个Reference对象。
在任何时候,我们都可以调用ReferenceQueue的poll()方法来检查是否有它所关心的非强可及对象被回收。如果队列为空,将返回一个null,否则该方法返回队列中前面的一个Reference对象。利用这个方法,我们可以检查哪个SoftReference所软引用的对象已经被回收。于是我们可以把这些失去所软引用的对象的SoftReference对象清除掉。常用的方式为:
  1. SoftReference ref = null;
  2. while ((ref = (EmployeeRef) q.poll()) != null) {
  3. // 清除ref
  4. }
理解了ReferenceQueue的工作机制之后,我们就可以开始构造一个Java对象的高速缓存器了。下面是一个高速缓存器的代码:
  1. EmployeeCache 类:
  1. import java.lang.ref.ReferenceQueue;
  2. import java.lang.ref.SoftReference;
  3. import java.util.Hashtable;
  4.  
  5. public class EmployeeCache {
  6. static private EmployeeCache cache;
  7. private Hashtable<String, EmployeeRef> employeeRefs;
  8. private ReferenceQueue<Employee> q;
  9. private class EmployeeRef extends SoftReference<Employee>{
  10. private String _key="";
  11. public EmployeeRef(Employee em,ReferenceQueue<Employee> q) {
  12. super(em,q);
  13. _key=em.getId();
  14. }
  15. }
  16. private EmployeeCache() {
  17. employeeRefs = new Hashtable<>();
  18. q = new ReferenceQueue<>();
  19. }
  20.  
  21. public static EmployeeCache getInstance(){
  22. if(cache==null){
  23. cache = new EmployeeCache();
  24. }
  25. return cache;
  26. }
  27.  
  28. private void cacheEmployee(Employee em){
  29. cleanCache();
  30. EmployeeRef ref = new EmployeeRef(em, q);
  31. employeeRefs.put(em.getId(), ref);
  32. }
  33.  
  34. public Employee getEmployee(String id){
  35. Employee employee = null;
  36. if(employeeRefs.contains(id)){
  37. EmployeeRef ref = employeeRefs.get(id);
  38. employee = ref.get();
  39. }
  40.  
  41. if(employee == null){
  42. employee = new Employee(id);
  43. System.out.println("从信息中心获取新的对象");
  44. this.cacheEmployee(employee);
  45. }
  46. return employee;
  47. }
  48. private void cleanCache() {
  49. EmployeeRef ref = null;
  50. while((ref=(EmployeeRef) q.poll())!=null){
  51. employeeRefs.remove(ref._key);
  52. }
  53. }
  54. public void clearCache(){
  55. cleanCache();
  56. employeeRefs.clear();
  57. System.gc();
  58. System.runFinalization();
  59. }
  60. }

Employee类:

  1. import java.lang.ref.Reference;
  2. import java.lang.ref.ReferenceQueue;
  3. import java.lang.ref.SoftReference;
  4.  
  5. public class Employee {
  6. private String id;
  7. private String name;
  8. private String department;
  9. private String phone;
  10. private int salary;
  11. private String origin;
  12.  
  13. public Employee(String id) {
  14. this.id = id;
  15. getDataFromInfoCenter();
  16. }
  17.  
  18. private void getDataFromInfoCenter() {
  19.  
  20. }
  21.  
  22. public String getId() {
  23. String id = (int) (Math.random() * 10 + 1) + "";
  24. return id;
  25. }
  26. }
 

2、jdk中的引用实现类

代表软引用的类:java.lang.ref.SoftReference
代表弱引用的类:java.lang.ref.WeakReference
代表虚引用的类:java.lang.ref.PhantomReference
他们同时继承了:java.lang.ref.Reference
引用队列:java.lang.ref.ReferenceQueue,这个引用队列是可以三种引用类型联合使用的,以便跟踪java虚拟机回收所引用对象的活动。

附:相关源码

  1. /*
  2. * @(#)ReferenceQueue.java 1.23 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7.  
  8. package java.lang.ref;
  9.  
  10. /**
  11. * Reference queues, to which registered reference objects are appended by the
  12. * garbage collector after the appropriate reachability changes are detected.
  13. *
  14. * @version 1.23, 12/19/03
  15. * @author Mark Reinhold
  16. * @since 1.2
  17. */
  18.  
  19. public class ReferenceQueue<T> {
  20.  
  21. /**
  22. * Constructs a new reference-object queue.
  23. */
  24. public ReferenceQueue() { }
  25.  
  26. private static class Null extends ReferenceQueue {
  27. boolean enqueue(Reference r) {
  28. return false;
  29. }
  30. }
  31.  
  32. static ReferenceQueue NULL = new Null();
  33. static ReferenceQueue ENQUEUED = new Null();
  34.  
  35. static private class Lock { };
  36. private Lock lock = new Lock();
  37. private Reference<? extends T> head = null;
  38. private long queueLength = 0;
  39.  
  40. boolean enqueue(Reference<? extends T> r) { /* Called only by Reference class */
  41. synchronized (r) {
  42. if (r.queue == ENQUEUED) return false;
  43. synchronized (lock) {
  44. r.queue = ENQUEUED;
  45. r.next = (head == null) ? r : head;
  46. head = r;
  47. queueLength++;
  48. if (r instanceof FinalReference) {
  49. sun.misc.VM.addFinalRefCount(1);
  50. }
  51. lock.notifyAll();
  52. return true;
  53. }
  54. }
  55. }
  56.  
  57. private Reference<? extends T> reallyPoll() { /* Must hold lock */
  58. if (head != null) {
  59. Reference<? extends T> r = head;
  60. head = (r.next == r) ? null : r.next;
  61. r.queue = NULL;
  62. r.next = r;
  63. queueLength--;
  64. if (r instanceof FinalReference) {
  65. sun.misc.VM.addFinalRefCount(-1);
  66. }
  67. return r;
  68. }
  69. return null;
  70. }
  71.  
  72. /**
  73. * Polls this queue to see if a reference object is available. If one is
  74. * available without further delay then it is removed from the queue and
  75. * returned. Otherwise this method immediately returns <tt>null</tt>.
  76. *
  77. * @return A reference object, if one was immediately available,
  78. * otherwise <code>null</code>
  79. */
  80. public Reference<? extends T> poll() {
  81. synchronized (lock) {
  82. return reallyPoll();
  83. }
  84. }
  85.  
  86. /**
  87. * Removes the next reference object in this queue, blocking until either
  88. * one becomes available or the given timeout period expires.
  89. *
  90. * <p> This method does not offer real-time guarantees: It schedules the
  91. * timeout as if by invoking the {@link Object#wait(long)} method.
  92. *
  93. * @param timeout If positive, block for up <code>timeout</code>
  94. * milliseconds while waiting for a reference to be
  95. * added to this queue. If zero, block indefinitely.
  96. *
  97. * @return A reference object, if one was available within the specified
  98. * timeout period, otherwise <code>null</code>
  99. *
  100. * @throws IllegalArgumentException
  101. * If the value of the timeout argument is negative
  102. *
  103. * @throws InterruptedException
  104. * If the timeout wait is interrupted
  105. */
  106. public Reference<? extends T> remove(long timeout)
  107. throws IllegalArgumentException, InterruptedException
  108. {
  109. if (timeout < 0) {
  110. throw new IllegalArgumentException("Negative timeout value");
  111. }
  112. synchronized (lock) {
  113. Reference<? extends T> r = reallyPoll();
  114. if (r != null) return r;
  115. for (;;) {
  116. lock.wait(timeout);
  117. r = reallyPoll();
  118. if (r != null) return r;
  119. if (timeout != 0) return null;
  120. }
  121. }
  122. }
  123.  
  124. /**
  125. * Removes the next reference object in this queue, blocking until one
  126. * becomes available.
  127. *
  128. * @return A reference object, blocking until one becomes available
  129. * @throws InterruptedException If the wait is interrupted
  130. */
  131. public Reference<? extends T> remove() throws InterruptedException {
  132. return remove(0);
  133. }
  134.  
  135. }

ReferenceQueue

  1. /*
  2. * @(#)SoftReference.java 1.34 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7.  
  8. package java.lang.ref;
  9.  
  10. /**
  11. * Soft reference objects, which are cleared at the discretion of the garbage
  12. * collector in response to memory demand. Soft references are most often used
  13. * to implement memory-sensitive caches.
  14. *
  15. * <p> Suppose that the garbage collector determines at a certain point in time
  16. * that an object is <a href="package-summary.html#reachability">softly
  17. * reachable</a>. At that time it may choose to clear atomically all soft
  18. * references to that object and all soft references to any other
  19. * softly-reachable objects from which that object is reachable through a chain
  20. * of strong references. At the same time or at some later time it will
  21. * enqueue those newly-cleared soft references that are registered with
  22. * reference queues.
  23. *
  24. * <p> All soft references to softly-reachable objects are guaranteed to have
  25. * been cleared before the virtual machine throws an
  26. * <code>OutOfMemoryError</code>. Otherwise no constraints are placed upon the
  27. * time at which a soft reference will be cleared or the order in which a set
  28. * of such references to different objects will be cleared. Virtual machine
  29. * implementations are, however, encouraged to bias against clearing
  30. * recently-created or recently-used soft references.
  31. *
  32. * <p> Direct instances of this class may be used to implement simple caches;
  33. * this class or derived subclasses may also be used in larger data structures
  34. * to implement more sophisticated caches. As long as the referent of a soft
  35. * reference is strongly reachable, that is, is actually in use, the soft
  36. * reference will not be cleared. Thus a sophisticated cache can, for example,
  37. * prevent its most recently used entries from being discarded by keeping
  38. * strong referents to those entries, leaving the remaining entries to be
  39. * discarded at the discretion of the garbage collector.
  40. *
  41. * @version 1.34, 12/19/03
  42. * @author Mark Reinhold
  43. * @since 1.2
  44. */
  45.  
  46. public class SoftReference<T> extends Reference<T> {
  47.  
  48. /* Timestamp clock, updated by the garbage collector
  49. */
  50. static private long clock;
  51.  
  52. /* Timestamp updated by each invocation of the get method. The VM may use
  53. * this field when selecting soft references to be cleared, but it is not
  54. * required to do so.
  55. */
  56. private long timestamp;
  57.  
  58. /**
  59. * Creates a new soft reference that refers to the given object. The new
  60. * reference is not registered with any queue.
  61. *
  62. * @param referent object the new soft reference will refer to
  63. */
  64. public SoftReference(T referent) {
  65. super(referent);
  66. this.timestamp = clock;
  67. }
  68.  
  69. /**
  70. * Creates a new soft reference that refers to the given object and is
  71. * registered with the given queue.
  72. *
  73. * @param referent object the new soft reference will refer to
  74. * @param q the queue with which the reference is to be registered,
  75. * or <tt>null</tt> if registration is not required
  76. *
  77. */
  78. public SoftReference(T referent, ReferenceQueue<? super T> q) {
  79. super(referent, q);
  80. this.timestamp = clock;
  81. }
  82.  
  83. /**
  84. * Returns this reference object's referent. If this reference object has
  85. * been cleared, either by the program or by the garbage collector, then
  86. * this method returns <code>null</code>.
  87. *
  88. * @return The object to which this reference refers, or
  89. * <code>null</code> if this reference object has been cleared
  90. */
  91. public T get() {
  92. T o = super.get();
  93. if (o != null) this.timestamp = clock;
  94. return o;
  95. }
  96.  
  97. }

SoftReference

Java中四种引用:强、软、弱、虚引用的更多相关文章

  1. java中强,软,弱,虚引用 以及WeakHahMap

    java中强,软,弱,虚引用  以及WeakHahMap   一:强软引用: 参考:http://zhangjunhd.blog.51cto.com/113473/53092/进行分析   packa ...

  2. java中的强,软,弱,虚引用

    引用的应用场景 我们都知道垃圾回收器会回收符合回收条件的对象的内存,但并不是所有的程序员都知道回收条件取决于指向该对象的引用类型.这正是Java中弱引用和软引用的主要区别. 如果一个对象只有弱引用指向 ...

  3. java中四种引用类型(对象的强、软、弱和虚引用)

    对象的强.软.弱和虚引用在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象.也就是说,只有对象处于可触及(reachable)状态,程序才能使用它.从JDK 1.2 ...

  4. java中四种引用类型

    java中四种引用类型  今天看代码,里面有一个类java.lang.ref.SoftReference把小弟弄神了,试想一下,接触java已经有3年了哇,连lang包下面的类都不了解,怎么混.后来在 ...

  5. Java中四种引用的区分

    强引用(StrongReference) 强引用就是指在程序代码之中普遍存在的,比如下面这段代码中的object和str都是强引用: 1 2 Object object = new Object(); ...

  6. java中四种引用类型(转)

    今天看代码,里面有一个类java.lang.ref.SoftReference把小弟弄神了,试想一下,接触java已经有3年了哇,连lang包下面的类都不了解,怎么混.后来在网上查资料,感觉收获颇多, ...

  7. Java中四种访问权限总结

    一.Java中有四种访问权限, 其中三种有访问权限修饰符,分别为private.public.protected,还有一种不带任何修饰符(default). 1. private: Java语言中对访 ...

  8. java中四种操作(dom、sax、jdom、dom4j)xml方式详解与比较

    1)DOM(JAXP Crimson解析器)     DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准.DOM是以层次结构组织的节点或信息片断的集合.这个层次结构允许开发人员在树中寻找特 ...

  9. java中四种操作xml方式的比较

    1)DOM(JAXP Crimson解析器) DOM是用与平台和语言无关的方式表示XML文档的官方W3C标准.DOM是以层次结构组织的节点或信息片断的集合.这个层次结构允许开发人员在树中寻找特定信息. ...

随机推荐

  1. gdb汇编调试

    GDB调试汇编堆栈分析 代码: sudo apt-get install libc6-dev-i386命令安装所需库 进入之后先在main函数处设置一个断点,再run一下,使用disassemble指 ...

  2. java使用jsch连接linux

    由于项目需要使用java来linux进行管理,近一番查找,发现第三方jar包 jsch 可以轻松实现对linux的管理,(相关文档及例子请访问官网www.jcraft.com),故引进. 在网上搜索了 ...

  3. Appium UI自动化的那些梗

    @作者 彭海波 转载请注明出处 前言 由于需求的快速迭代和敏捷测试的要求,在测试过程中引入自动化成为必不可少的手段.作为一个互联网测试团队,我们自然也引入了自动化测试这个环节.在众多的测试框架中,我们 ...

  4. xhprof学习笔记

    一.简介 XHProf 是一个轻量级的分层性能测量分析器. 在数据收集阶段,它跟踪调用次数与测量数据,展示程序动态调用的弧线图. 它在报告.后期处理阶段计算了独占的性能度量,例如运行经过的时间.CPU ...

  5. jfinal相关

    1:jfinal工具类 1):密码加密工具 HashKit.md5(String password);2):数据缓存工具类 chacheKit3):获取项目路径工具类: PathKit 4):读取文件 ...

  6. 配合crond服务实现自定义周期备份MySQL数据库(使用innobackupex进行备份)

    备份 新建一个脚本/root/backup.py,内容如下: #!/usr/bin/env python# -*- coding: utf-8 -*- ''' 脚本作者:昨夜星辰 脚本作用:配合cro ...

  7. asp.net core获取自定义json的配置内容

    首先在主目录下建立:Iyibank.Web.json文件 里边的内容如下: { "ConnectionStrings": { "RedisCache": &qu ...

  8. 6.openssl rsautl和openssl pkeyutl

    rsautl是rsa的工具,相当于rsa.dgst的部分功能集合.可用于签名.验证.加密和解密文件.非对称密钥的密钥是随机生成的,因此不需要也无法指定salt参与加密. pkeyutl是非对称加密的通 ...

  9. I2C总线和S5PV210的I2C总线控制器

    一.什么是I2C通信协议? 1.物理接口:SCL + SDA (1)SCL(serial clock):时钟线,传输CLK信号,一般是I2C主设备向从设备提供时钟的通道. (2)SDA(serial ...

  10. python之路-Day8

    抽象接口 class Alert(object): '''报警基类''' def send(self): raise NotImplementedError class MailAlert(Alert ...