Java Finalization‘s Memory-Retention Issues 及Reference类解析

引言

《Effective Java Programming Language Guide》 一书中强烈建议不要使用java的finalize()方法去做对象消亡前的清理。因为jvm调用finalize()方法的时机并不确定,容易导致Memory-Retention Issues。通俗点讲就是内存没办法及时回收。
详细的见oracle的官方说明https://www.oracle.com/technical-resources/articles/javase/finalization.html。

Memory-Retention Issues问题简述

如果类有重写finalize()方法,JVM会将该类的对象标记为finalizable,区别于普通对象被垃圾收集器判定为不可达时,会立即回收内存,finalizable的对象会经过更多的GC周期。
下图来自oracle官方。
在这里插入图片描述
finalizable对象回收通常经历以下过程

  1. 垃圾回收器检查到该对象不可达
  2. 垃圾回收器将该对象加入到finalization队列,对象变成可达
  3. 专门的Finalizer线程从finalization队列中将对象移除,并执行对象的finalize()方法,并将对象标记为finalized
  4. 垃圾回收器再次发现该对象不可达,而且为finalized状态的(finalize方法已执行过),因此直接回收该对象内存。

以上过程的一些个人分析:

jvm为什么不直接在回收对象前调用finalize()方法,而是使用专门的线程去执行

java每次GC需要通过可达性分析标记大量对象,回收内存后,还涉及内存整理,如果把finalize()方法的调用也放到这个过程中,GC耗时会更长,影响系统的响应时间,所以只能由另外的过程去处理。

Memory-Retention问题

从上述过程可以看到,finalizable对象至少要2个GC周期才能将对象回收掉。更有甚者,如果系统中有大量的对象是finalizable,或者有些对象finalize()方法本身就比较耗时,加上只有一个Finalizer线程,这个线程优先级并不比别的高,还会和其他线程竞争执行资源,对象在finalization队列中呆的时间更长。在这期间如果有发生GC,垃圾收集器也是无法清理这些对象的,因此这些对象还在被finalization队列强引用。所以容易产生Memory-Retention问题。

Memory-Retention问题解决方案

《Effective Java Programming Language Guide》建议使用JDK的Cleaner来做对象消亡前的清理,其基于PhantomReference,下面系统的介绍JDK的Reference。

Reference解析

java的Reference的相关子类,用于应用层与垃圾收集器有更多的交互,通俗点讲就是垃圾收集器给应用层暴露一些API,让应用对对象的回收时机有了一定的控制能力。

SoftReference

垃圾回收器会根据内存使用情况对软引用对象进行回收,当然jvm会尽可能的不回收软引用对象,至于什么情况下回收,JDK并没有明确说明。根据其特点可以看出SoftReference可以用于缓存设计缓存,这样不用自己去设计LRU等算法对缓存进行清理。
一旦垃圾收集器认为软引用对象需要被清理时,JVM会解除软引用对对象的引用(即将referent字段置为null),同时或者稍后将软引用自己放到ReferenceQueue(如果创建软引用时有传入)
JDK保证在jvm抛出OutOfMemoryError前,清掉所有的软引用对象。除此之外,并不保证软引用对象被清理的时间点,而且也不保证软引用对象清理的顺序。

WeakReference

一旦垃圾回收器检测到对象只有弱引用,会立即解除弱引用(将弱引用的referent字段置为null),同时或者稍后将弱引用放入ReferenceQueue(如果创建软引用时有传入)。
弱引用不能阻止垃圾回收器对对象的回收,因此弱引用一般用于“规范化映射(canonicalizing mappings)”,例如WeakHashMap。
对canonicalizing mappings详细说明可以阅读
https://objectcomputing.com/resources/publications/sett/june-2000-collaborating-with-the-java-memory-manager
https://wiki.c2.com/?CanonicalizedMapping

PhantomReference

虚引用在垃圾回收器确定其引用对象可以被回收后放到ReferenceQueue,这一点与SoftReference及WeakReference有所区别。对于finalizable对象,后两者在垃圾回收器将对象放入finalization队列时,就会解除引用并将引用放入到ReferenceQueue。而PhantomReference必须在finalizable对象从finalization队列移除后,并且被垃圾回收器再次检测到不可达能够真正的回收其内存时,放入到ReferenceQueue中,而且引用不会自动解除。
在这里插入图片描述

未完待续

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/174010.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[超详细]基于YOLO&OpenCV的人流量统计监测系统(源码&部署教程)

1.图片识别 2.视频识别 [YOLOv7]基于YOLO&Deepsort的人流量统计系统(源码&部署教程)_哔哩哔哩_bilibili 3.Deepsort目标追踪 (1)获取原始视频帧 (2)利用目标检测器对视频帧中的目标进行检测 &#xff08…

京东数据分析(京东数据采集):2023年10月京东平板电视行业品牌销售排行榜

鲸参谋监测的京东平台10月份平板电视市场销售数据已出炉! 根据鲸参谋电商数据分析平台的相关数据显示,10月份,京东平台上平板电视的销量将近77万,环比增长约23%,同比则下降约30%;销售额为21亿,环…

汽车智能座舱/智能驾驶SOC -1

看到华为&小康的 AITO问界M6、M7各种广告营销、宣传、测评、好评如潮水般席卷网络各APP平台。翻看了中信和海通对特斯拉M3和比亚迪元的拆解报告,也好奇华为的汽车芯片平台又能做出哪些新花样,下面是Mark开头,也学习下智能座舱和智能驾驶芯…

Vue项目 配置项设置

一、项目运行时浏览器自动打开 找到package.json文件 找到"sctipts"配置项 在"serve"配置项最后加上--open "scripts": {"serve": "vue-cli-service serve --open","build": "vue-cli-service build&quo…

2023 最新 PDF.js 在 Vue3 中的使用(长期更新)

因为自己写业务要定制各种 pdf 预览情况(可能),所以采用了 pdf.js 而不是各种第三方封装库,主要还是为了更好的自由度。 一、PDF.js 介绍 官方地址 中文文档 PDF.js 是一个使用 HTML5 构建的便携式文档格式查看器。 pdf.js 是社区…

SPASS-指数平滑法

基本概念及统计原理 基本概念 指数平滑法的思想来源于对移动平均预测法的改进。指数平滑法的思想是以无穷大为宽度,各历史值的权重随时间的推移呈指数衰减,这样就解决了移动平均的两个难题。 统计原理 简单模型 Holt线性趋势模型 案例 为了研究上海市…

HarmonyOS ArkTSTabs组件的使用(六)

Tabs组件的使用 ArkUI开发框架提供了一种页签容器组件Tabs,开发者通过Tabs组件可以很容易的实现内容视图的切换。页签容器Tabs的形式多种多样,不同的页面设计页签不一样,可以把页签设置在底部、顶部或者侧边。 Tabs组件的简单使用 Tabs组件…

flutter iOS 视频mov格式转MP4格式

flutter iOS 视频mov格式转MP4格式 前言一、使用video_compress压缩视频总结 前言 今天在写项目的时候,突然发现iOS 里面的有些视频格式是mov的格式,这就导致在视频播放组件无法播放的问题,期间试过替换视频格式,但是又不想存储文…

1-verilog的串行滤波器FIR实现

verilog的串行滤波器FIR实现 1,RTL代码2,RTL原理框图3,测试代码4,输出FIR滤波器的波形 参考文献: 1,基于FPGA的串行FIR滤波器设计与实现 2,FPGA实现FIR滤波器 1,RTL代码 timescale 1ns / 1ps /…

某60区块链安全之Call函数簇滥用实战一学习记录

区块链安全 文章目录 区块链安全Call函数簇滥用实战一实验目的实验环境实验原理实验内容实验过程 Call函数簇滥用实战一 实验目的 学会使用python3的web3模块 学会以太坊Delegatecall漏洞分析及利用 实验环境 Ubuntu18.04操作机 实验工具 python3 实验原理 call 外部调用…

重生之我是一名程序员 37

哈喽啊大家晚上好! 今天呢给大家带来一个烧脑的知识——C语言中的栈溢出问题。那什么是栈溢出呢?栈溢出指的是当程序在执行函数调用时,为了保护函数的局部变量和返回地址,将这些数据存储在栈中。如果函数在函数调用时使用了过多的…

Tensorrt 实现 yolov5-cls 遇到的问题

yolov5-6.2增加了分类训练、验证、预测和导出(所有 11 种格式),还提供了 ImageNet 预训练的 YOLOv5m-cls、ResNet(18、34、50、101) 和 EfficientNet (b0-b3) 模型. 官方Git : https://github.com/ultralytics/yolov5 分类模型与…

解决VSCode运行时自动保存问题【图文解析】

用VSCode写前端时老是自动保存,代码还没写完就开始 刷新页面 调用接口 出现报错之类的,很烦人,所以就写一篇修改VSCode自动保存文件的文章,以免自己忘记在哪设置。 同事总是用不自动保存,每次写完都要ctrls一下&#x…

2023 年爆肝将近 20 万字讲解最新 JavaEE 全栈工程师基础教程(更新中)

1. Java 语言基本概述 Java 是一种广泛使用的编程语言,由 James Gosling 在 Sun Microsystems(现在是 Oracle Corporation 的一部分)于 1995 年发表。Java 是一种静态类型的、类基础的、并发性的、面向对象的编程语言。Java 广泛应用于企业级…

C语言scanf_s函数的使用

因为scanf函数存在缓冲区溢出的可能性;提供了scanf_s函数;增加一个参数; scanf_s最后一个参数是缓冲区的大小,表示最多读取n-1个字符; 下图代码; 读取整型数可以不指定长度;读取char&#xf…

第十二章 pytorch中使用tensorboard进行可视化(工具)

PyTorch 从 1.2.0 版本开始,正式自带内置的 Tensorboard 支持了,我们可以不再依赖第三方工具来进行可视化。 tensorboard官方教程地址:https://github.com/tensorflow/tensorboard/blob/master/README.md 1、tensorboard 下载 step 1 此次…

『 Linux 』使用fork函数创建进程与进程状态的查看

文章目录 🖥️ 前言 🖥️🖥️ 通过系统调用获取进程标识符 🖥️💻 进程标识符PID💻 父进程标识符PPID 🖥️ 通过系统调用创建子进程 fork() 🖥️💻 那么为什么在fork()函…

华为ac+fit漫游配置案例

Ap漫游配置: 其它配置上面一样,ap管理dhcp和业务dhcp全在汇聚交换机 R1: interface GigabitEthernet0/0/0 ip address 11.1.1.1 255.255.255.0 ip route-static 12.2.2.0 255.255.255.0 11.1.1.2 ip route-static 192.168.0.0 255.255.0.0 11.1.1.2 lsw1: vlan batch 100 200…

dvwa 代码注入impossible代码审计

dvwa 代码注入impossible代码审计 <?phpif( isset( $_POST[ Submit ] ) ) {// Check Anti-CSRF tokencheckToken( $_REQUEST[ user_token ], $_SESSION[ session_token ], index.php ); // 检查token值是否正确// Get input$target $_REQUEST[ ip ]; $target stripslas…

Servlet执行流程Servlet 生命周期

Servlet 生命周期 对象的生命周期指一个对象从被创建到被销毁的整个过程 import javax.servlet.*; import javax.servlet.annotation.WebServlet; import java.io.IOException; WebServlet(urlPatterns "/demo",loadOnStartup 10) public class ServletDemo imple…