Java Reference & ReferenceQueue一览

Overview

The java.lang.ref package provides more flexible types of references than are otherwise available, permitting limited interaction between the application and the Java Virtual Machine (JVM) garbage collector. It is an important package, central enough to the language for the language designers to give it a name that starts with "java.lang", but it is somewhat special-purpose and not used by a lot of developers. This package was added in J2SE 1.2.

Java has an expressive system of references and allows for special behavior for garbage collection. A normal reference in Java is known as a "strong reference." The java.lang.ref package defines three other types of references — soft, weak, and phantom references. Each type of reference is designed for a specific use.

Reference in JAVA

Base

Strong Reference,强引用,即java标准的引用方式,表示GC从 Root Set 开始向下扫描,可以找到对应的 Strong Reference。
FinalReference 作为 java.lang.ref 里的一个不能被公开访问的类,实际上,FinalReference 代表的正是 Java 中的强引用。

Referent,被包装为 Weak, Soft, Phantom Reference的对象引用称之为 referent。

Soft Reference ,软引用。它是除strong外,生命周期最长的一种 Reference,只有当JVM Heap中充满Strong References,
Full GC无法为heap腾出更多空间而即将抛出OOM时,SoftReferences会被GC回收。

Weak Reference,弱引用。当一个referent,在运行时没有同时被强,软引用,只被Weak Reference自身引用,且Weak Reference
从 Root Set 可达,则该referent会被GC回收。

WR的作用,一般是为referent提供一个被回收的凭据,结合ReferenceQueue可以让程序在第一时间得到referent被回收的事件,
从而做一些额外的clean操作。

Phanton Reference, 是一种特殊的Reference,正如他的名字所表达的,幻影引用,他可以像幻影一样附着在referent上。
当GC在遍历引用关系时,如果发现被phantom reference包装过的referent不存在strong, weak, soft引用时(就是除phantom外
没有任何引用,幻影的由来),GC会将 phantom reference 放入 Reference queue。以便程序在另一边通过queue的remove/poll
方法,感知referent被GC回收的事件。

feature

Soft Reference Keeps objects alive provided there’s enough memory. to keep objects alive even after clients have removed their references (memory-sensitive caches), in case clients start asking for them again by key. After a first gc pass, the JVMdecides it still needs to reclaim more space. java.lang.ref.SoftReference
Weak Reference Keeps objects alive only while they’re in use (reachable) by clients. Containers that automatically delete objects no longer in use. After gc determines the object is only weakly reachable java.lang.ref.WeakReference
java.util.WeakHashMap
Phantom Reference Lets you clean up after finalization but before the space is reclaimed (replaces or augments the use offinalize()) Special clean up processing After finalization. java.lang.ref.PhantomReference

important

按理说,Soft Reference 与 Weak Reference都可以用来实现缓存,只是失效策略不同,一个是内存不足时清理,一个是随意清理

另外WeakHashMap并不适用于缓存,详见weakHashMap解析

Overview the relationship between Reference&ReferenceQueue

ReferenceQueue是作为 JVM GC与上层Reference对象管理之间的一个消息传递方式,允许注册一些监听器来获取回收状态

class#java.lang.ref.Reference

reference objects are implemented in close cooperation with the garbage collector

Overview

 1  /* A Reference instance is in one of four possible internal states:
 2        一个Reference实例有以下4种内部状态
 3      *
 4      *       Active: Subject to special treatment by the garbage collector.  Some
 5      *       time after the collector detects that the reachability of the
 6      *       referent has changed to the appropriate state, it changes the
 7      *       instance‘s state to either Pending or Inactive, depending upon
 8      *       whether or not the instance was registered with a queue when it was
 9      *       created.  In the former case it also adds the instance to the
10      *       pending-Reference list.  Newly-created instances are Active.
11      *       当垃圾回收器探测到引用的可达性变成某些适合的状态的时候,
12      *       它会将该内部状态变成Pending或者Inactive,
13      *       这取决于在实例化这个Reference对象的时候是否传入了ReferenceQueue。
14      *     如果传入了,那么它同时会将该实例添加到pending-Reference列表中。
15      *     新创建的引用对象是Active
16      *
17      *       Pending: An element of the pending-Reference list, waiting to be
18      *       enqueued by the Reference-handler thread.  Unregistered instances
19      *       are never in this state.
20      *       一个在Pend-Reference列表中的元素,正等待着Reference-handler线程将他入队。
21      *       未注册的实例不会出现在这个状态。
22      *
23      *       Enqueued: An element of the queue with which the instance was
24      *       registered when it was created.  When an instance is removed from
25      *       its ReferenceQueue, it is made Inactive.  Unregistered instances are
26      *       never in this state.
27      *       当一个实例从它的ReferenceQueue中被删除时,它变成Inactive状态。
28      *       未注册的instance不会
29      *
30      *       Inactive: Nothing more to do.  Once an instance becomes Inactive its
31      *       state will never change again.
32      *       不会再做任何改变。一旦某个实例变成了Inactive态,它的状态不会再有任何改变。
33      *
34      * The state is encoded in the queue and next fields as follows:
35      *
36      *       Active: queue = ReferenceQueue with which instance is registered, or
37      *       ReferenceQueue.NULL if it was not registered with a queue; next =
38      *       null.
39      *
40      *       Pending: queue = ReferenceQueue with which instance is registered;
41      *       next = Following instance in queue, or this if at end of list.
42      *
43      *       Enqueued: queue = ReferenceQueue.ENQUEUED; next = Following instance
44      *       in queue, or this if at end of list.
45      *
46      *       Inactive: queue = ReferenceQueue.NULL; next = this.
47      *
48      * With this scheme the collector need only examine the next field in order
49      * to determine whether a Reference instance requires special treatment: If
50      * the next field is null then the instance is active; if it is non-null,
51      * then the collector should treat the instance normally.
52      *
53      * 以这种方式,收集器只需要检查next字段,以决定是否该引用实例应该被特殊处理
54      * 如果下一个字段是null,说明该实例为active
55      * 如果不是null,说明回收器应该立刻处理该实例
56      *
57      * To ensure that concurrent collector can discover active Reference
58      * objects without interfering with application threads that may apply
59      * the enqueue() method to those objects, collectors should link
60      * discovered objects through the discovered field.
61      *
62      * 为了保证并发收集器可以再不受应用程序线程调用enqueue()发放的影响下,发现active reference
63      * 收集器应该吧已经发现的objects通过discovered 字段表示。
64      *
65      */

Inner Field 非static

T referent

Treated specially by GC

是该引用实例真正指向的对象,为了避免和reference同名,名字叫做referent

ReferenceQueue<? super T> queue
引用队列,通知队列(使用方法具体见后文)

Reference next
链表指针,是GC里面的pending list

Reference<T> discovered

used by VM

Global Field ,static

Lock lock
一个空对象,用于锁同步

     /* Object used to synchronize with the garbage collector.  The collector
     * must acquire this lock at the beginning of each collection cycle.  It is
     * therefore critical that any code holding this lock complete as quickly
     * as possible, allocate no new objects, and avoid calling user code.
     * 这是垃圾回收器用来同步的对象。在垃圾回收周期之前,回收器需要获取这个锁。
     * 因此,任何持有该锁的对象应该尽快执行完,尽量不要分配新对象,避免调用用户代码
     */

Reference<T> pending

所谓的pending链表,依赖于reference的next指针实现,大部分对于该链表的操作都是通过vm执行

ReferenceHandler#Class

implement Runable

监听(wait/notify)pending链表,通过将pending链表的元素enque来实现监视器模式,以便回调各个reference注
册的queue上面的的监听者(调用remove或者poll方法)

 1   for (;;) {
 2
 3                 Reference r;
 4                 synchronized (lock) {
 5                     if (pending != null) {
 6                         //删除pending列表的该对象
 7                         r = pending;
 8                         Reference rn = r.next;
 9                         pending = (rn == r) ? null : rn;
10                         r.next = r;
11                     } else {
12                         try {
13                             lock.wait(); //该wait由VM来notify
14                         } catch (InterruptedException x) { }
15                         continue;
16                     }
17                 }
18
19                 // Fast path for cleaners
20                 // 钩子
21                 if (r instanceof Cleaner) {
22                     ((Cleaner)r).clean();
23                     continue;
24                 }
25
26                 ReferenceQueue q = r.queue;
27                 //将该对象入队
28                 //加入ReferenceQueue中的链表中,见下文
29                 if (q != ReferenceQueue.NULL) q.enqueue(r);
30             }

static块

启动ReferenceHandler 设置为最高优先级并且为守护进程

Interface

Reference(T referent)

默认构造器

Reference(T referent, ReferenceQueue<? super T> queue)

带有ReferenceQueue的构造器

T get()

获取该referent

void clear()

清空

boolean isEnqueued()

是否入队,根据queue和next指针来判断

boolean enqueue()

入队方法,VM不会调用该方法,暂时不知道谁来调用

class#java.lang.ref.ReferenceQueue

Overview

Reference queues, to which registered reference objects are appended by the
garbage collector after the appropriate reachability changes are detected.

引用队列,将Reference Object注册到该队列上,使得当垃圾回收器改变其到某些状态的时候能够被探测到。

总之,这是一个观察引用对象回收的东西

通过wait/notify实现的阻塞和非阻塞调用~ 

该操作涉及一些并发知识哦~

Inner Field

//队列头
volatile Reference<? extends T> head = null;

//队列长度
long queueLength = 0;

Interface

enqueue

Called only by Reference Class

调用入队操作,删除元素的对该队列的引用,将元素插入头,增加长度,lock.notify

remove

阻塞调用(lock.wait),获取一个元素。

poll

非阻塞调用。

基于Reference和ReferenceQueue实现的WeakHashMap

REFERENCE

  1. 深入探讨 java.lang.ref 包@IBMer
  2. 话说ReferenceQueue
  3. Java Reference概念整理
  4. 深入理解ReferenceQueue GC finalize Reference
  5. 深入理解java的finalize
  6. Understanding Weak References
时间: 2024-10-16 09:00:45

Java Reference & ReferenceQueue一览的相关文章

Java面试题一览

Java面试题一览 原文地址:https://www.cnblogs.com/renxiuxing/p/10141967.html

Java Reference Types

References Java provides two different types/classes of Reference Objects: strong and weak. Weak Reference Objects can be further divided into soft and phantom. Strong Reference StringBuilder builder = new StringBuilder(); This is the default type/cl

Java Reference 源码分析

Reference对象封装了其它对象的引用,可以和普通的对象一样操作,在一定的限制条件下,支持和垃圾收集器的交互.即可以使用Reference对象来引用其它对象,但是最后还是会被垃圾收集器回收.程序有时候也需要在对象回收后被通知,以告知对象的可达性发生变更.  Java提供了四种不同类型的引用,引用级别从高到低分别为FinalReference,SoftReference,WeakReference,PhantomReference.其中FinalReference不对外提供使用.每种类型对应着

理解java reference

Java世界泰山北斗级大作<Thinking In Java>切入Java就提出“Everything is Object”.在Java这个充满Object的世界中,reference是一切谜题的根源,所有的故事都是从这里开始的. Reference是什么? 如果你和我一样在进入Java世界之前曾经浪迹于C/C++世界,就一定不会对指针陌生.谈到指针,往日种种不堪回首的经历一下子涌上心头,这里不是抱怨的地方,让我们暂时忘记指针的痛苦,回忆一下最初接触指针的甜蜜吧!还记得你看过的教科书中,如何讲

What Influences Method Call Performance in Java?--reference

reference from:https://www.voxxed.com/blog/2015/02/too-fast-too-megamorphic-what-influences-method-call-performance-in-java/ Whats this all about then? Let’s start with a short story. I proposed a change on the a Java core libs mailing list to overri

.net项目架构改造之搭建基于java环境配置一览【上】

最近公司做了一个项目,需要嵌套在千牛的客户端上,项目代码必须上阿里的聚石塔,全程采用基于docker的自动化部署,我们的项目是基于.net架构.很遗憾 的是基于windows的docker上部署在访问淘宝自身的api接口,总是会时不时的各种超时,阿里小二也整个一个星期没解决,给出的理由很简单,基于windows的docker 的服务也才引入不久,还有稳定性问题. 在选择docker镜像时把自己技术的tomcat顶的高高在上,卧槽,双重1w点暴击,预计.net架构用在这上面后面会有各种坑... 改

WeakReference Reference ReferenceQueue

public class WeakReference<T> extends Reference<T> { public WeakReference(T referent) { super(referent); } public WeakReference(T referent, ReferenceQueue<? super T> q) { super(referent, q); } } public abstract class Reference<T> {

MySql数据类型和Java数据类型对应一览

类型名称 显示长度 数据库类型 JAVA类型 JDBC类型索引(int) 描述             VARCHAR L+N VARCHAR java.lang.String 12   CHAR N CHAR java.lang.String 1   BLOB L+N BLOB java.lang.byte[] -4   TEXT 65535 VARCHAR java.lang.String -1               INTEGER 4 INTEGER UNSIGNED java.la

java reference(转)

http://blog.163.com/[email protected]/blog/static/112987702200962211145825/ 在Java中的引用类型,是指除了基本的变量类型之外的所有类型,所有的类型在内存中都会分配一定的存储空间(形参在使用的时候也会分配存储空间,方法调用完成之后,这块存储空间自动消失), 基本的变量类型只有一块存储空间(分配在stack中), 而引用类型有两块存储空间(一块在stack中,一块在heap中), 方法形参的值传递(引用)是指形参和传进来的