深入Java(二):Java中的强引用、软引用、弱引用、幻像引用( 虚引用)

2023-11-10

在Java语言中,除了基本数据类型外,其他的都是指向各类对象的对象引用;Java中根据其生命周期的长短,将引用分为4类。


1 强引用

特点:我们平常典型编码Object obj = new Object()中的obj就是强引用。通过关键字new创建的对象所关联的引用就是强引用。 当JVM内存空间不足,JVM宁愿抛出OutOfMemoryError运行时错误(OOM),使程序异常终止,也不会靠随意回收具有强引用的“存活”对象来解决内存不足的问题。对于一个普通的对象,如果没有其他的引用关系,只要超过了引用的作用域或者显式地将相应(强)引用赋值为 null,就是可以被垃圾收集的了,具体回收时机还是要看垃圾收集策略。

2 软引用

特点:软引用通过SoftReference类实现。 软引用的生命周期比强引用短一些。只有当 JVM 认为内存不足时,才会去试图回收软引用指向的对象:即JVM 会确保在抛出 OutOfMemoryError 之前,清理软引用指向的对象。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。后续,我们可以调用ReferenceQueue的poll()方法来检查是否有它所关心的对象被回收。如果队列为空,将返回一个null,否则该方法返回队列中前面的一个Reference对象。


应用场景:软引用通常用来实现内存敏感的缓存。如果还有空闲内存,就可以暂时保留缓存,当内存不足时清理掉,这样就保证了使用缓存的同时,不会耗尽内存。

3 弱引用

弱引用通过WeakReference类实现。 弱引用的生命周期比软引用短。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。由于垃圾回收器是一个优先级很低的线程,因此不一定会很快回收弱引用的对象。弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。

应用场景:弱应用同样可用于内存敏感的缓存。

4 虚引用

特点:虚引用也叫幻象引用,通过PhantomReference类来实现。无法通过虚引用访问对象的任何属性或函数。幻象引用仅仅是提供了一种确保对象被 finalize 以后,做某些事情的机制。如果一个对象仅持有虚引用,那么它就和没有任何引用一样,在任何时候都可能被垃圾回收器回收。虚引用必须和引用队列 (ReferenceQueue)联合使用。当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就会在回收对象的内存之前,把这个虚引用加入到与之关联的引用队列中。

ReferenceQueue queue = new ReferenceQueue ();

PhantomReference pr = new PhantomReference (object, queue); 

程序可以通过判断引用队列中是否已经加入了虚引用,来了解被引用的对象是否将要被垃圾回收。如果程序发现某个虚引用已经被加入到引用队列,那么就可以在所引用的对象的内存被回收之前采取一些程序行动。


应用场景:可用来跟踪对象被垃圾回收器回收的活动,当一个虚引用关联的对象被垃圾收集器回收之前会收到一条系统通知。


诊断 JVM 引用情况

如果你怀疑应用存在引用(或 finalize)导致的回收问题,可以有很多工具或者选项可供选择,比如 HotSpot JVM 自身便提供了明确的选项(PrintReferenceGC)去获取相关信息,我指定了下面选项去使用 JDK 8 运行一个样例应用:


-XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintReferenceGC

这是 JDK 8 使用 ParrallelGC 收集的垃圾收集日志,各种引用数量非常清晰。


0.403: [GC (Allocation Failure) 0.871: [SoftReference, 0 refs, 0.0000393 secs]0.871: [WeakReference, 8 refs, 0.0000138 secs]0.871: [FinalReference, 4 refs, 0.0000094 secs]0.871: [PhantomReference, 0 refs, 0 refs, 0.0000085 secs]0.871: [JNI Weak Reference, 0.0000071 secs][PSYoungGen: 76272K->10720K(141824K)] 128286K->128422K(316928K), 0.4683919 secs] [Times: user=1.17 sys=0.03, real=0.47 secs]


注意:JDK 9 对 JVM 和垃圾收集日志进行了广泛的重构,类似 PrintGCTimeStamps 和 PrintReferenceGC 已经不再存在,我在专栏后面的垃圾收集主题里会更加系统的阐述。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入Java(二):Java中的强引用、软引用、弱引用、幻像引用( 虚引用) 的相关文章

  • java.library.path 中没有字体管理器

    以下代码在我的桌面上运行得很好 BufferedImage image new BufferedImage width height BufferedImage TYPE INT RGB Graphics g image getGraphi
  • 为什么不在下一个 JVM 中删除类型擦除呢?

    Java 在 Java 5 中引入了泛型类型擦除 因此它们可以在旧版本的 Java 上运行 这是兼容性的权衡 我们已经失去了这种兼容性 1 https stackoverflow com questions 22610400 a progr
  • 可以混合使用 JVM 语言吗?即:Groovy 和 Clojure

    我知道你可以轻松地混合groovy java clojure java 无论什么JvmLang java 这是否也意味着我也可以让 clojure 和 groovy 代码进行交互 如果我使用 Grails 或 jRoR 我也可以在该环境中使
  • jvm 如何以及何时何地更改 Linux 的最大打开文件值?

    在linux中 每个登录用户的每个进程的最大打开文件数有限制 如下所示 ulimit n 1024 当我学习java nio时 我想检查这个值 因为channel在Linux中也是一个文件 所以我编写了一个客户端代码来不断创建socketC
  • JVM内存段分配

    好吧 我有一个关于 JVM 内存段的问题 我知道每个 JVM 都会选择稍微不同地实现这一点 但这是一个总体概念 在所有 JVM 中应该保持相同 一个在运行时不使用虚拟机执行的标准C C 程序在运行时有四个内存段 代码 堆栈 堆 数据 所有这
  • Java 类:匿名类、嵌套类、私有类

    有人能解释一下Java中匿名类 嵌套类和私有类之间的区别吗 我想知道与每个相关的运行时成本以及每个编译器的方法 这样我就可以掌握哪个最适合用于例如性能 编译器优化的潜力 内存使用以及其他 Java 编码人员的普遍可接受性 我所说的匿名类是指
  • Bipush 在 JVM 中如何工作?

    我知道 iload 接受整数 1 到 5 但是如何使用 bipush 指令扩展到更高的数字 特定整数如何与字节码一起存储 有几种不同的指令可用于推送整数常量 最小的是iconst 指令 这些只是一个字节 因为该值是在操作码本身中编码的 ic
  • Java 语言中不可用的字节码功能

    当前 Java 6 是否有一些事情可以在 Java 字节码中完成而在 Java 语言中无法完成 我知道两者都是图灵完备的 所以将 可以做 理解为 可以做得更快 更好 或者只是以不同的方式 我正在考虑额外的字节码 例如invokedynami
  • Kotlin 未解决的参考:CLI 上 gradle 的 println

    放一个printlnkotlin 函数返回之前的语句会崩溃 堆栈跟踪 thufir dur NetBeansProjects kotlin thufir dur NetBeansProjects kotlin gradle clean bu
  • 如果使用的 JVM 是 x86 或 x64,则以不同的方式解决 Maven 依赖关系?

    我设置了一个 Maven 存储库来托管一些 dll 但我需要我的 Maven 项目根据使用的 JVM 是 x86 还是 x64 下载不同的 dll 例如 在运行 x86 版本 JVM 的计算机上 我需要从存储库下载 ABC dll 作为依赖
  • JVM:是否可以操作帧堆栈?

    假设我需要执行N同一线程中的任务 这些任务有时可能需要来自外部存储的一些值 我事先不知道哪个任务可能需要这样的值以及何时 获取速度要快得多M价值观是一次性的而不是相同的M值在M查询外部存储 注意我不能指望任务本身进行合作 它们只不过是 ja
  • Java的-XX:+UseMembar参数是什么

    我在各种地方 论坛等 看到这个参数 并且常见的答案是它有助于高并发服务器 尽管如此 我还是找不到 sun 的官方文档来解释它的作用 另外 它是Java 6中添加的还是Java 5中存在的 顺便说一句 许多热点虚拟机参数的好地方是这一页 ht
  • 使用适用于 API v2 的 Dropbox Java SDK 时出现 SSLHandshakeException

    In a XPages我想使用的应用程序适用于 API v2 的 Dropbox Java SDK 2 1 2 获取有关我的 Dropbox 帐户的信息 以下代码用于检索相应的帐户对象 String atoken DbxRequestCon
  • 将 Kotlin .kt 类打包到 JAR 中

    我如何构建HelloWorld kt as a JAR以便它运行 thufir dur kotlin thufir dur kotlin kotlinc HelloWorld kt include runtime d HelloWorld
  • Dart/Flutter 如何编译到 Android?

    我找不到任何具体的资源 Dart 是否被编译到 JVM 或者 Google 的团队是否编译了 Dart VM 以在 JVM 上运行 然后在 JVM 内的 Dart VM 中运行 Dart 前者更有意义 并且符合 无桥 的口号 但后者似乎更符
  • 为什么java(>=7版本)不支持运行没有main方法的程序? [关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 class WithoutMain static System out println Without main class Sy
  • Java 8:为什么元空间大小增加但加载的类数量保持不变?

    在 Jdk 8 上运行的应用程序中 我们使用 VisualVM 来跟踪加载的类的使用情况和元空间的使用情况 在我们的应用程序运行时的某个时间点 我们看到加载的类的数量不再增加 但元空间的大小在程序运行时仍然增加 那么除了类之外 还有什么东西
  • 如何使用 JAVA_OPTS 环境变量?

    我该如何使用JAVA OPTS变量来配置Web服务器 Linux服务器 我该如何设置 Djava awt headless true using JAVA OPTS JAVA OPTS是一些服务器和其他 Java 应用程序附加到执行调用的标
  • 哪个更快:instanceof 或 isInstance?

    抛开设计问题不谈 什么在现代 JVM 上执行得更快 foo instanceof Bar or Bar class isInstance foo Why Class isInstance是 JVM 固有的 它被编译为与instanceof完
  • 如果我使用最新的 JDK 编译 Java 文件,较旧的 JVM 是否能够运行 .class 文件?

    字节码是否取决于创建它所用的 Java 版本 如果我在最新的 JDK 中编译了 java 文件 较旧的 JVM 是否能够运行 class 文件 这取决于三件事 The actual Java versions you are talking

随机推荐

  • 将div的宽、高按比例设置有什么效果

    在添加div时 对它的大小 宽 高 有两种设置方法 固定值和百分比 1 若div的宽高为固定值 则该div的显示效果会随着其父div的缩放而变化 如下所示 fixed width 200px height 100px background
  • 【C语言】输入三个字符串,比较其大小,最终将它们由大到小输出。利用C指针。

    题目 输入三个字符串 比较其大小 最终将它们由大到小输出 利用C指针 解题思路 定义一个二维字符数组用于存放3组字符串 再定义一个一位指针数组使其分别指向这3个字符串 编写一个函数 利用传入的指针数组 对其指向的字符串的用 选择法 进行排序
  • 函数式接口习题

    基础题 练习一 函数式接口 定义一个函数式接口CurrentTimePrinter 其中抽象方法void printCurrentTime 使用注解 FunctionalInterface 在测试类中定义static void showLo
  • 云解析DNS能为你做什么?

    记录类型 云解析DNS支持A CNAME MX TXT SRV AAAA NS CAA记录类型 您可以参阅 添加解析记录 操作文档 记录类型功能描述AIPV4记录 支持将域名映射到IPv4地址使用AAAAIPV6记录 支持将域名映射到IPv
  • 非printf形式打印各种数据类型的十六进制和二进制

    转载请标明是引用于 http blog csdn net chenyujing1234 欢迎大家提出意见 一起讨论 一 源码实现 为了适配各种数据类型 且可以通过sizeof得到此类型的大小 所以这里采用模板形式开发 以下是实现此功能的源码
  • 在Ubuntu系统安装jdk1.7步骤

    在Ubuntu12 04系统安装sun jdk1 7 可以到 http www oracle com 下载jdk1 7版本 选择平台Linux x64 Accept the license agreement and download th
  • 《再也不怕elasticsearch》es核心概念

    ES核心概念 大家好我是迷途 一个在互联网行业 摸爬滚打的学子 热爱学习 热爱代码 热爱技术 热爱互联网的一切 再也不怕elasticsearch系列 帅途会慢慢由浅入深 为大家剖析一遍 各位大佬请放心 虽然这个系列帅途有时候更新的有点慢
  • 谷歌浏览器官方下载地址

    谷歌浏览器官方下载地址 在线安装版 https www google com chrome browser desktop index html 离线安装版 https www google com intl zh CN chrome br
  • python编写用户登录程序_python初学之用户登录的实现过程(实例讲解)

    要求编写登录接口 1 输入用户名和密码 2 认证成功后显示欢迎信息 3 用户名输错 提示用户不存在 重新输入 5次错误 提示尝试次数过多 退出程序 4 用户名正确 密码错误 提示密码错误 重新输入 密码错误3次 锁定用户名并提示 退出程序
  • python 字符串替换

    在Python中 字符串是一种非常重要的数据类型 它可以用来表示文本 数字 符号等信息 在实际开发中 我们经常需要对字符串进行替换操作 这时就需要用到字符串替换函数 Python中的字符串替换函数主要有replace translate r
  • 30岁后程序员的出路[转]

    那程序员到了30岁 怎样提高自己的不可替代性呢 我们打算做一辈子程序员吗 敢问路在何方 作为一个过来人 一个资深程序员 我觉得有几个方向可以选择 1 成为技术大拿 其实 做一辈子程序员并没有什么问题 重要的是 你必须成为一个不可替代的程序员
  • 在字节跳动做了6年软件测试,4月无情被辞,想给划水的兄弟提个醒

    先简单交代一下背景吧 某不知名 985 的本硕 17 年毕业加入字节 以 人员优化 的名义无情被裁员 之后跳槽到了有赞 一直从事软件测试的工作 之前没有实习经历 算是6年的工作经验吧 这6年之间完成了一次晋升 换了一家公司 有过开心满足的时
  • [JavaScript] async/await面试题 及其解析

    题目 async function async1 console log 1 await async2 console log 2 async function async2 console log 3 console log 4 setT
  • iframe简单使用 、获取iframe 、获取iframe 元素值 、iframe获取父页面的信息

    文章目录 1 iframe简单使用 2 获取iframe 3 获取iframe 元素值 4 iframe获取父页面的信息 1 iframe简单使用 标签规定一个内联框架 一个内联框架被用来在当前 HTML 文档中嵌入另一个文档 width插
  • 图像分类、目标检测、语义分割、实例分割和全景分割的区别

    1 Image Classification 图像分类 图像分类 下图左 就是对图像判断出所属的分类 比如在学习分类中数据集有人 person 羊 sheep 狗 dog 和猫 cat 四种 图像分类要求给定一个图片输出图片里含有哪些分类
  • ISTQB认证工程师学习笔记(4)——测试技术

    测试技术一般可分为黑盒测试 白盒测试 基于经验的测试技术 黑盒测试 黑盒测试技术 也称为行为的或基于行为的技术 基于对适当测试依据的分析 例如 正式需求文档 规格说明 用例 用户故事或业务流程 这些技术适用于功能和非功能测试 黑盒测试技术关
  • verilog 中的 log2

    对数的作用 log2是指2的对数 对于二进制的计算机系统来说非常有用 比如 10bits的地址线 可寻址的地址空间为2 10 那么反过来对于1024深的地址空间 需要多少bits的地址线 需要用log2 depth 来计算 如何求对数 sy
  • 爬取中国移动用户问答

    最近一个好朋友在搞爬虫 问了很多问题 所以干脆直接写了一个范例 这个程序整体要两次解析网页 第一层是分析网页中的json数据来获取qtid 第二层是用qtid来解析获得问答所在的网页 因为在问答网页里的数据存储是引用的数据库中的数据 所以不
  • Mac系统下algs4学习环境搭建

    InterliJ下的搭建 1 官网下载algs4 rar文件 拷贝到在新建项目的libs文件夹下 然后在File gt project Structure 需要用到啦gs4的模块中导入jar包 这样在程序中引用静态类就不会报错类 termi
  • 深入Java(二):Java中的强引用、软引用、弱引用、幻像引用( 虚引用)

    在Java语言中 除了基本数据类型外 其他的都是指向各类对象的对象引用 Java中根据其生命周期的长短 将引用分为4类 1 强引用 特点 我们平常典型编码Object obj new Object 中的obj就是强引用 通过关键字new创建