iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >全面解析Java中的GC与幽灵引用
  • 435
分享到

全面解析Java中的GC与幽灵引用

JavaGC 2022-11-15 22:11:25 435人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

Java 中一共有 4 种类型的引用 : StrongReference、 SoftReference、 WeakReference 以及 PhantomReference (传说中

Java 中一共有 4 种类型的引用 : StrongReference、 SoftReference、 WeakReference 以及 PhantomReference (传说中的幽灵引用 呵呵),
这 4 种类型的引用与 GC 有着密切的关系,  让我们逐一来看它们的定义和使用场景 :

1、 Strong Reference
StrongReference 是 Java 的默认引用实现,  它会尽可能长时间的存活于 JVM 内, 当没有任何对象指向它时 GC 执行后将会被回收

Java代码


@Test 
public void strongReference() { 
    Object referent = new Object(); 

     
    Object strongReference = referent; 

    assertSame(referent, strongReference); 

    referent = null; 
    System.gc(); 

     
    assertNotNull(strongReference); 


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

@Test 
public void weakReference() { 
    Object referent = new Object(); 
    WeakReference<Object> weakRerference = new WeakReference<Object>(referent); 

    assertSame(referent, weakRerference.get()); 

    referent = null; 
    System.gc(); 

     
    assertNull(weakRerference.get()); 


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

@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(); 

     
    Thread.sleep(1000); 

     
    assertFalse(weakHashMap.containsValue(value)); 


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

@Test 
public void softReference() { 
    Object referent = new Object(); 
    SoftReference<Object> softRerference = new SoftReference<Object>(referent); 

    assertNotNull(softRerference.get()); 

    referent = null; 
    System.gc(); 

     
    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>()); 

     
    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代码


@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); 


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 的工作原理以及性能调优有一定帮助,在实现一些基础性设施比如缓存时也可能会用到, 希望本文能有所帮助。

--结束END--

本文标题: 全面解析Java中的GC与幽灵引用

本文链接: https://www.lsjlt.com/news/172479.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 全面解析Java中的GC与幽灵引用
    Java 中一共有 4 种类型的引用 : StrongReference、 SoftReference、 WeakReference 以及 PhantomReference (传说中...
    99+
    2022-11-15
    Java GC
  • PageHelper引发的幽灵数据问题解析
    目录前言大胆猜测PageHelper工作原理Tomcat请求流程总结前言 最近测试反馈一个问题,某个查询全量信息的接口,有时候返回全量数据,符合预期,但是偶尔又只返回1条数据,简直就...
    99+
    2023-05-16
    PageHelper幽灵数据 PageHelper 数据
  • Java泛型与注解全面分析讲解
    目录1.什么是泛型2.为何使用泛型2.1.如何定义泛型2.2.通配符2.3.受限泛型2.4.泛型接口2.5.泛型方法3.java高级--注解3.1.预定义注解3.2.自定义注解(初级...
    99+
    2024-04-02
  • MySQL 驱动中虚引用 GC 耗时优化与源码分析
    目录本文要点:背景优化——由暴力破解到优雅配置什么是虚引用关联对象真的被回收了吗虚引用的使用场景——mysql-connector-Java 虚引用源码分析总结本文要点: ...
    99+
    2023-05-16
    MySQL 驱动虚引用GC 耗时 MySQL 驱动虚引用
  • 全面理解Java中的引用传递和值传递
    目录1.基本类型和引用类型在内存中的保存2.变量的基本类型和引用类型的区别3.引用传递和值传递4.结论关于Java传参时是引用传递还是值传递,是一个讨论比较多的话题, 有说Java中...
    99+
    2024-04-02
  • java注解的全面分析
    全面解析java注解Java中的常见注解 a.JDK中的注解    @Override 覆盖父类或者父接口的方法    @Deprecated 表示方法已经过时 &nbs...
    99+
    2023-05-31
    java 注解 ava
  • 全面分析Java方法的使用与递归
    目录java中方法的使用什么是方法方法的定义与使用方法如何进行调用及其方法调用过程方法的形参和实参方法重载方法签名递归java中方法的使用 什么是方法 举一个日常生活中的例子,比如我...
    99+
    2024-04-02
  • 全面解析C++中的new,operator new与placement new
    new operator/delete operator就是new和delete操作符,而operator new/operator delete是函数。 new operator(...
    99+
    2022-11-15
    placement_new new operator_new
  • 深入浅析Java中的对象与引用
    今天就跟大家聊聊有关深入浅析Java中的对象与引用,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Java中的对象和引用详解 在Java中,有一组名词经常一起出现,它们就是“对象和对象...
    99+
    2023-05-31
    java 对象 引用
  • C++ 函数指针使用指南:全面理解与灵活调用
    答案: 函数指针允许 c++++ 以更灵活的方式处理函数。语法及使用:声明函数指针:type (*function_name)(args);指向函数:function_pointer =...
    99+
    2024-04-30
    c++ 函数指针 typedef
  • Java中类加载过程全面解析
    类文件加载的顺序先加载执行父类的静态变量及静态初始化块(执行先后顺序按排列的先后顺序)再加载执行本类的静态变量及静态初始化块只要类没有被销毁,静态变量及静态初始化块只会执行1次,后续再对该类进行其他操作也不会再执行这两个步骤。类实例创建过程...
    99+
    2023-05-30
    java 类加载过程 中类
  • Java多态的全面系统解析
    目录Java基础知识(多态)多态多态的定义和存在的必要条件多态的定义:多态存在的三个必要条件多态的案例多态的好处多态的弊端引用类型转换1. 引用类型转换是什么,为什么需要它?2. 向...
    99+
    2024-04-02
  • 全面解析JavaScript中offsetLeft、offsetTop的用法
    目录一、第一个小例子二、第二个小例子(给box1添加相对定位)三、第三个小例子(给box1,box2添加相对定位)四、解析五、扩展(在第三个例子中,假如我想获取到box3到浏览器窗口...
    99+
    2023-05-17
    JavaScript offsetLeft offsetTop
  • AndroidApplication的使用全面解析
    目录一、Application是什么?二、Application类的方法1、onCreate()方法2、onConfigurationChanged(Configuration ne...
    99+
    2022-12-09
    Android Application使用解析 Android Application
  • Java全面讲解顺序表与链表的使用
    目录线性表顺序表链表小结线性表 线性表 ( linear list ) 是 n 个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见 的线性表:顺序表、...
    99+
    2024-04-02
  • Java 面向对象的特征解析与应用
    ## 类和对象 * 面向对象与面向过程 面向过程:是指类似在C语言学习中,所写的代码都在主程序(main())中运行,非常的繁琐。 面向对象:首先创建一个类,类中包括对一个事物描述的...
    99+
    2024-04-02
  • vue$attrs的使用全面解析
    目录$attrs的使用vue以下是$attrs的使用示例1.父组件(Father.vue)2.儿子组件(Child.vue)3.孙子组件(GrandChild.vue)$attrs到...
    99+
    2024-04-02
  • Java 开发人员必备:接口与抽象类的全面解析
    简介 接口和抽象类是 Java 中面向对象编程中至关重要的概念,它们提供了多态性和代码重用,使开发人员能够编写更加灵活和可扩展的代码。 接口 接口是定义方法签名的抽象类型,它不需要实现这些方法。接口本质上是契约,声明了类必须实现的行为。...
    99+
    2024-03-03
    Java 接口 抽象类 多态 代码重用 面向对象
  • 从入门到精通:PHP Shell 学习笔记与索引全面解析!
    PHP Shell 是一款基于PHP语言的命令行界面工具,它可以让PHP开发者更加方便地进行命令行操作,提高开发效率。本文将从入门到精通逐步介绍PHP Shell的使用方法和技巧,并提供相关的学习笔记和索引。 一、PHP Shell 入门 ...
    99+
    2023-10-13
    shell 学习笔记 索引
  • JAVA与SQL 中的null与NULL解析
    目录一、前言看下面我做的一个简单的测试:二、Java中的null引发这个异常的情况有:2.1 大小写2.2 默认的初值2.3 类型2.4 对null的检查== 与 !=instanc...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作