`
maosheng
  • 浏览: 560251 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java 中的4 种引用

    博客分类:
  • Java
阅读更多

Java 中一共有4 种类型的引用 :

StrongReference SoftReference WeakReference 以及 PhantomReference .

4 种类型的引用与 GC 有着密切的关系让我们逐一来看它们的定义和使用场景 :
1.Strong Reference        
StrongReference
Java的默认引用实现它会尽可能长时间的存活于 JVM 内,当没有任何对象指向它时 GC 执行后将会被回收

Java代码:

  @Test

  public void strongReference() {

   Object referent = new Object();

  

   /**

    * 通过赋值创建 StrongReference

    */

   Object strongReference = referent;

  

   assertSame(referent, strongReference);

  

   referent = null;

   System.gc();

  

   /**

    * StrongReference GC 后不会被回收

    */

   assertNotNull(strongReference);

  }

 

2.WeakReference & WeakHashMap
WeakReference
是一个弱引用当所引用的对象在 JVM 内不再有强引用时, GC weak reference 将会被自动回收

Java代码:

  @Test

  public void weakReference() {

   Object referent = new Object();

   WeakReference<Object> weakRerference = new WeakReference<Object>(referent);

 

   assertSame(referent, weakRerference.get());

  

   referent = null;

   System.gc();

  

   /**

    * 一旦没有指向 referent 的强引用, weak reference GC 后会被自动回收

    */

   assertNull(weakRerference.get());

  }


WeakHashMap
使用 WeakReference 作为 key一旦没有指向 key 的强引用, WeakHashMap GC 后将自动删除相关的 entry

Java代码:

  @Test

  public void weakHashMap() throws InterruptedException {

   Map<Object, Object> weakHashMap = new WeakHashMap<Object, Object>();

   Object key = new Object();

   Object value = new Object();

   weakHashMap.put(key, value);

 

   assertTrue(weakHashMap.containsValue(value));

  

   key = null;

   System.gc();

  

   /**

    * 等待无效 entries 进入 ReferenceQueue 以便下一次调用 getTable 时被清理

    */

   Thread.sleep(1000);

  

   /**

    * 一旦没有指向 key 的强引用, WeakHashMap GC 后将自动删除相关的 entry

    */

   assertFalse(weakHashMap.containsValue(value));

  }

 

3.SoftReference
SoftReference
WeakReference 的特性基本一致,最大的区别在于 SoftReference 会尽可能长的保留引用直到 JVM 内存不足时才会被回收(虚拟机保证), 这一特性使得 SoftReference 非常适合缓存应用

Java代码:

  @Test

  public void softReference() {

   Object referent = new Object();

   SoftReference<Object> softRerference = new SoftReference<Object>(referent);

 

   assertNotNull(softRerference.get());

  

   referent = null;

   System.gc();

  

   /**

    *  soft references 只有在 jvm OutOfMemory 之前才会被回收, 所以它非常适合缓存应用

    */

   assertNotNull(softRerference.get());

  }

 

4.PhantomReference
Phantom Reference(幽灵引用) WeakReference SoftReference 有很大的不同因为它的 get() 方法永远返回 null, 这也正是它名字的由来

Java代码:

  @Test

  public void phantomReferenceAlwaysNull() {

   Object referent = new Object();

   PhantomReference<Object> phantomReference = new PhantomReference<Object>(referent, new ReferenceQueue<Object>());

  

   /**

    * phantom reference get 方法永远返回 null

    */

   assertNull(phantomReference.get());

  }

  

一个永远返回 null reference 要来何用请注意构造 PhantomReference 时的第二个参数 ReferenceQueue(事实上 WeakReference & SoftReference 也可以有这个参数)
PhantomReference
唯一的用处就是跟踪 referent  何时被 enqueue ReferenceQueue .

5.RererenceQueue
当一个 WeakReference 开始返回 null 时,它所指向的对象已经准备被回收,这时可以做一些合适的清理工作.   将一个 ReferenceQueue 传给一个 Reference 的构造函数, 当对象被回收时, 虚拟机会自动将这个对象插入到 ReferenceQueue 中, WeakHashMap 就是利用 ReferenceQueue 来清除 key 已经没有强引用的 entries.

Java代码:

 


6.PhantomReference  vs WeakReference
PhantomReference 
有两个好处, 其一, 它可以让我们准确地知道对象何时被从内存中删除, 这个特性可以被用于一些特殊的需求中(例如 Distributed GC  XWork google-guice 中也使用 PhantomReference 做了一些清理性工作
).

其二, 它可以避免 finalization 带来的一些根本性问题, 上文提到 PhantomReference 的唯一作用就是跟踪 referent 何时被 enqueue ReferenceQueue 但是 WeakReference 也有对应的功能, 两者的区别到底在哪呢
?
这就要说到 Object finalize 方法, 此方法将在 gc 执行前被调用, 如果某个对象重载了 finalize 方法并故意在方法内创建本身的强引用这将导致这一轮的 GC 无法回收这个对象并有可能

引起任意次 GC 最后的结果就是明明 JVM 内有很多 Garbage OutOfMemory 使用 PhantomReference 就可以避免这个问题, 因为 PhantomReference 是在 finalize 方法执行后回收的,也就意味着此时已经不可能拿到原来的引用也就不会出现上述问题当然这是一个很极端的例子, 一般不会出现.

7.
对比


Soft vs Weak vs Phantom References

Type

Purpose

Use

When GCed

Implementing Class

Strong Reference

An ordinary reference. Keeps objects alive as long as they are referenced.

normal reference.

Any object not pointed to can be reclaimed.

default

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 JVM decides 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


8.
小结
一般的应用程序不会涉及到 Reference 编程, 但是了解这些知识会对理解 GC 的工作原理以及性能调优有一定帮助,   在实现一些基础性设施比如缓存时也可能会用到, 希望本文能有所帮助.

 @Test

 public void referenceQueue() throws InterruptedException {

  Object referent = new Object(); 

  ReferenceQueue<Object> referenceQueue = new ReferenceQueue<Object>();

  WeakReference<Object> weakReference = new WeakReference<Object>(referent, referenceQueue);

 

  assertFalse(weakReference.isEnqueued());

  Reference<? extends Object> polled = referenceQueue.poll();

  assertNull(polled);

 

  referent = null;

  System.gc();

 

  assertTrue(weakReference.isEnqueued());

  Reference<? extends Object> removed = referenceQueue.remove();

  assertNotNull(removed);

}

 

分享到:
评论

相关推荐

    Java中对象与引用

    ### Java中对象与引用 在Java编程中,深入理解对象与引用的概念对于掌握面向对象编程至关重要。本文将从以下几个方面详细解析对象与引用的基本概念及其相互间的关系。 #### 一、对象与引用的基础概念 **对象**: ...

    java 常见的四种引用

    在Java中,为了更好地管理对象的生命周期,从JDK 1.2开始引入了四种不同级别的引用类型:强引用、软引用、弱引用和虚引用。每种引用类型都有其特定的应用场景,通过灵活运用这些引用类型,开发者可以在内存管理和...

    java中的引用问题

    Java中的引用问题主要涉及到对象作为参数传递时的行为。在Java中,有两类数据类型:基本类型(如int、char)和引用类型(如类实例、数组)。对于基本类型,Java采用值传递的方式,而对于引用类型,则是传递引用的...

    java中对象和对象引用的区别!

    ### Java中对象与对象引用的区别 #### 基础概念 在Java编程语言中,对象与对象引用是非常基础且重要的概念。理解它们之间的区别对于掌握Java面向对象编程至关重要。 #### 对象与引用定义 - **对象**:在Java中,...

    Java中弱引用软引用虚引用及强引用的区别Java开发Ja

    在Java编程语言中,引用类型是理解内存管理的关键概念之一。强引用、弱引用、软引用和虚引用是四种不同的引用强度,它们在垃圾回收机制中扮演着不同的角色。了解这些引用类型对于优化内存使用、防止内存泄漏以及合理...

    浅谈Java中的四种引用方式的区别

    在Java编程语言中,引用是连接对象和变量的桥梁,它们决定了对象的生命周期。Java提供了四种不同类型的引用,每种引用都有其特定的用途和行为。本文将深入探讨这四种引用——强引用、软引用、弱引用和虚引用,以及...

    Java中的软引用弱引用和虚引用.docx

    本文将深入探讨Java中三种特殊的引用类型——软引用(Soft Reference)、弱引用(Weak Reference)以及虚引用(Phantom Reference),并分析它们如何帮助我们更好地管理内存资源。 #### 二、基础知识回顾 在深入了解这三...

    Java:按值传递还是按引用传递详细解说

    在Java编程语言中,关于参数传递的方式一直存在两种观点:一种认为Java仅支持按值传递,另一种则指出Java同时支持按值传递和按引用传递。实际上,这两种观点并非完全对立,而是根据不同的角度来描述Java中的参数传递...

    JAVA中传值与引用问题

    Java作为一种广泛使用的高级编程语言,在设计之初就考虑到了如何避免C/C++等语言中的复杂性,特别是指针操作的复杂性和潜在风险。本文将深入探讨Java中的传值与传引用问题,并通过具体的例子来解析其中的原理。 ###...

    Java中四种引用类型详细介绍

    在Java编程语言中,引用类型对于管理对象的生命周期和内存使用至关重要。自JDK 1.2以来,Java引入了四种不同的引用级别,以提供更精细的控制权。以下是这四种引用类型的详细解释: 1. **强引用(StrongReference)*...

    Java 方法引用

    在Java编程语言中,方法引用是一种特殊的语法构造,它允许我们直接引用已有方法,而无需在lambda表达式中重新定义。方法引用的概念是随着Java 8的发布引入的,它是函数式编程特性的一部分,旨在简化代码并提高可读性...

    Java中调用Python代码

    本篇将详细探讨如何在Java中调用Python代码,以便充分利用两种语言的优点。 首先,我们需要了解Java与Python交互的几种常见方式: 1. **Jython**: Jython是一种Python的实现,它运行在Java平台上,可以直接执行...

    Java-Java面向对象中引用传递教程

    在Java编程语言中,面向对象特性是其核心概念之一,其中引用来传递对象是一个非常重要的知识点。本教程将深入探讨Java中的引用传递机制,并通过视频教程的形式帮助学习者更好地理解和应用这一概念。 首先,理解...

    java中引用json所用的jar包

    本篇将详细讲解如何在Java中引用用于处理JSON的jar包,以及其相关知识点。 首先,JSON(JavaScript Object Notation)是一种简洁且易于人阅读和编写的数据格式,同时也易于机器解析和生成。它能很好地替代XML作为...

    语音识别 sphinx4 JAVA 教程

    【语音识别技术与Sphinx-4简介】 ...总之,Sphinx-4为Java开发者提供了一种强大的语音识别解决方案,虽然中文模型的建立相对复杂,但通过不断学习和实践,开发者可以克服这一挑战,实现高效、准确的语音识别功能。

    JAVA基础——JAVA的五种引用类型及引用队列

    JAVA 是一种面向对象的语言,在 JAVA 程序运行时,对象是存储在堆内存(Heap)中的,C/C++ 中是通过指针来访问所谓对象(结构体)的,而 JAVA 则是通过引用来访问对象,也就是说,引用指向了对象在堆内存中的地址,...

    java中传值还是传引用的的认识

    Java 应用程序中的变量可以为以下两种类型之一:引用类型或基本类型。当作为参数传递给一个方法时,处理这两种类型的方式是相同的。两种类型都是按值传递的;没有一种按引用传递。 按值传递意味着当将一个参数传递...

    java调用Kettle引用jar包2.zip

    这个压缩包"java调用Kettle引用jar包2.zip"很可能包含了一些示例代码和必要的库文件,帮助开发者学习如何在Java项目中调用Kettle。 首先,我们需要理解Kettle的核心组件:Job和Transformation。Job是一系列步骤的...

    浅析Java引用类型和方法参数传递

    Java中,无论是值类型还是引用类型,在作为方法参数传递时,都遵循着一种被称为“按值传递”的机制。这意味着,当我们将一个变量作为参数传递给方法时,实际上传递的是该变量的一个副本。 ##### 1. 值传递 - **原理...

    java8中文文档API

    除了Lambda,Java 8还提供了方法引用和构造器引用,它们进一步简化了函数式编程。方法引用允许直接引用已有方法,如`List&lt;String&gt; list = Arrays.asList("a", "b", "c"); list.sort(Comparator.naturalOrder());`,...

Global site tag (gtag.js) - Google Analytics