前言

// 呵呵 03.12加班, 是一件无聊的事情

接前面几篇

25 关于 Signal Dispatcher

26 关于 Attach Listener

27 关于 Reference Handler

呵呵 关于常见的几个线程AttchListener,Signal Dispatcher, Reference Handler, Finalizer, 虽然 平时使用的不是很多吧, 但是 还是可以了解一下的

这里 我们便来看一下Finalizer这个线程吧

这个是 对象被 gc回收 处理之后, 需要回调的相关方法, 用类似于 c++ 里面的析构函数, 不过这里面可以有一些骚操作

一下的相关代码, 截图如果没有特殊说明基于 jdk9

测试代码

package com.hx.test06;import static com.hx.test05.Test20DefNewGc.touchMinorGc;/*** Test03Finalizer** @author Jerry.X.He <970655147@qq.com>* @version 1.0* @date 2020-05-17 09:31*/
public class Test03Finalizer {// identStrprivate String identStr = "identStr";int f01;int f02;int f03;int f04;int f05;// Test03Finalizer// vmOpts : -Xint -server -Xmx600m -Xms600m -XX:PermSize=128M -XX:MaxPermSize=128M -XX:NewSize=128m -XX:MaxNewSize=128m -XX:SurvivorRatio=8 -XX:+UseSerialGC -XX:+PrintGCDetailspublic static void main(String[] args) {Test03Finalizer obj = new Test03Finalizer();obj = null;touchMinorGc();int x = 0;}@Overrideprotected void finalize() throws Throwable {System.out.println(" finialize ");}}

class文件信息如下

master:classes jerry$ javap -c com/hx/test06/Test03Finalizer.class
Compiled from "Test03Finalizer.java"
public class com.hx.test06.Test03Finalizer {int f01;int f02;int f03;int f04;int f05;public com.hx.test06.Test03Finalizer();Code:0: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: aload_05: ldc           #2                  // String identStr7: putfield      #3                  // Field identStr:Ljava/lang/String;10: returnpublic static void main(java.lang.String[]);Code:0: new           #4                  // class com/hx/test06/Test03Finalizer3: dup4: invokespecial #5                  // Method "<init>":()V7: astore_18: aconst_null9: astore_110: invokestatic  #6                  // Method com/hx/test05/Test20DefNewGc.touchMinorGc:()V13: iconst_014: istore_215: returnprotected void finalize() throws java.lang.Throwable;Code:0: getstatic     #7                  // Field java/lang/System.out:Ljava/io/PrintStream;3: ldc           #8                  // String  finialize5: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V8: return
}

测试结果如下

Finalizer

类似于 Reference Handler 线程的初始化, Finalizer 的初始化是在 java 代码层面上进行初始化的

处理事情是, 不断从 Finalizer 的引用队列里面获取 FinalReference, 然后进行 runFinalizer 处理

runFinalizer 的处理也很简单, 如果该对象 没有执行过 finalize, 执行 finalize 方法

总结一下 Finalizer 做的事情就是 不断从 引用队列 里面获取 FinalReference 然后再 调用 referent 的 finalize 方法

引用队列 的数据是由 gc 处理之后, 放到 pendingList, 之后由 Reference Handler 转发到各个 引用 注册的 引用队列

为对象注册 Finalizer

注册的时机 取决于RegisterFinalizersAtInit 这个参数, 默认是 true, 表示在 构造函数 末尾注册 Finalizer

如果是 false 的话, 表示在 为对象分配了空间之后 注册

RegisterFinalizersAtInit 为 false

增加 vmOpt : -XX:-RegisterFinalizersAtInit

为对象分配了空间之后, 就向 Finalizer 注册了当前对象

定位一下当前的位置

warning: (x86_64) /Users/jerry/ClionProjects/HelloOpenJdk/jdk9/build/macosx-x86_64-normal-serverANDclient-slowdebug/jdk/bin/java empty dSYM file detected, dSYM was created with an executable with no debug info.
(lldb) re r
General Purpose Registers:rbx = 0x00000000000000bbrbp = 0x000070000b29f710rsp = 0x000070000b29f698r12 = 0x0000000000000000r13 = 0x0000000111ff7fe0r14 = 0x000070000b29f6a8r15 = 0x00007fcab7808000rip = 0x000000011b3f59f1
13 registers were unavailable.(lldb) x 0x0000000111ff7fe0
0x111ff7fe0: bb 00 04 59 b7 02 00 4c 01 4c b8 03 00 03 3d b1  ...Y...L.L....=.
0x111ff7ff0: ff 00 34 41 12 1a 12 00 00 00 00 00 10 00 1c 00  ..4A............

在 main 方法里面 第一个 指令, new

注册的方式是 调用 Finalizer.register 注册

Finalizer.register 所做的事情, 就是创建了一个 Finalizer(继承自 FinalReference), 注册的队列为 一个全局的 queue

unfinalized 的链表用于关联所有的 注册了 Finalizer, 但是还没有 finalize 的 Finalizer

引用队列 的数据是由 gc 处理之后, 放到 pendingList, 之后由 Reference Handler 转发到各个 引用 注册的 引用队列, 然后 Finalizer 线程再来 消费 Finalizer.queue 队列, 执行 Finalizer.referent 的 finalize

RegisterFinalizersAtInit 为 true

去掉RegisterFinalizersAtInit 的手动设置, 默认为 true

这里的注册 就是在 构造方法 的末尾来进行注册了

定位一下当前的位置, 当前指令为 0xe8

warning: (x86_64) /Users/jerry/ClionProjects/HelloOpenJdk/jdk9/build/macosx-x86_64-normal-serverANDclient-slowdebug/jdk/bin/java empty dSYM file detected, dSYM was created with an executable with no debug info.
(lldb) re r
General Purpose Registers:rbx = 0x00000000000000e8rbp = 0x000070000c937710rsp = 0x000070000c937698r12 = 0x0000000000000000r13 = 0x000000011212c5a8r14 = 0x000070000c9375d0r15 = 0x00007fbb7b000800rip = 0x000000011650a9f1
13 registers were unavailable.(lldb) x 0x000000011212c5a8
0x11212c5a8: e8 ff 00 64 00 00 00 00 00 00 00 00 01 00 18 00  ...d............
0x11212c5b8: 19 00 00 00 00 00 01 00 20 c6 12 12 01 00 00 00  ........ .......

但是你去查找规范, 你会发现根本没有 0xe8 对应的指令, 因为 这是一条 vm 自己使用的指令, 用于支持某些特性

到这里, 你可以先跳到07 运行时常量池索引的 rewrite的末尾的片尾彩蛋, 看一下

RegisterFinalizersAtInit 为 true 的时候, Object. 的最后一条Bytecodes::_return 更新成了Bytecodes::_return_register_finalizer

_return_register_finalizer 的业务处理

跳转之前 会调用InterpreterRuntime::register_finalizer, 把当前对象传递进去

也就是RegisterFinalizersAtInit 为 true 上面的截图是 执行_return_register_finalizer 的时候调用的InterpreterRuntime::register_finalizer

0xe8 指令为 _return_register_finalizer

finalize 骚操作之 起死回生

package com.hx.test06;import static com.hx.test05.Test20DefNewGc.touchMinorGc;/*** Test04FinalizerBackToAlive** @author Jerry.X.He* @version 1.0* @date 2020-05-17 10:58*/
public class Test04FinalizerBackToAlive {// identStrprivate String identStr = "identStr";private static Test04FinalizerBackToAlive obj = null;int f01;int f02;int f03;int f04;// Test04FinalizerBackToAlive// vmOpts : -Xint -server -Xmx600m -Xms600m -XX:PermSize=128M -XX:MaxPermSize=128M -XX:NewSize=128m -XX:MaxNewSize=128m -XX:SurvivorRatio=8 -XX:+UseSerialGC -XX:+PrintGCDetailspublic static void main(String[] args) {Test04FinalizerBackToAlive obj = new Test04FinalizerBackToAlive();obj = null;touchMinorGc();Test04FinalizerBackToAlive.obj = null;touchMinorGc();}@Overrideprotected void finalize() throws Throwable {Test04FinalizerBackToAlive.obj = this;System.out.println(" finialize ");}}

这里之所以 显式的 使用了Test04FinalizerBackToAlive.obj 是为了效果更加明显, 其实 第一次 minorgc 之后 obj 对应的对象是存活的

第二点就是 finalize 方法只执行了一次, 这一点可以参见上面runFinalizer 的代码, 可以自己调试一下 跟踪一下流程

finalize 骚操作之 致命异常

package com.hx.test06;import static com.hx.test05.Test20DefNewGc.touchMinorGc;/*** Test05FinalizerThrowEx** @author Jerry.X.He* @version 1.0* @date 2020-05-17 10:58*/
public class Test05FinalizerThrowEx {// identStrprivate String identStr = "identStr";int f01;int f02;int f03;int f04;int f05;// Test04FinalizerBackToAlive// vmOpts : -Xint -server -Xmx600m -Xms600m -XX:PermSize=128M -XX:MaxPermSize=128M -XX:NewSize=128m -XX:MaxNewSize=128m -XX:SurvivorRatio=8 -XX:+UseSerialGC -XX:+PrintGCDetailspublic static void main(String[] args) {Test05FinalizerThrowEx obj = new Test05FinalizerThrowEx();obj = null;touchMinorGc();}@Overrideprotected void finalize() throws Throwable {if(f01 == 1) {throw new RuntimeException(" this is ex ");
//     finalize();}System.out.println(" finialize ");}}

finalize 方法里面 尽量不要 做什么奇奇怪怪的事情, 就算你抛了异常, 结果什么什么反馈都看不到

finalize 骚操作之 阻塞

package com.hx.test06;import static com.hx.test05.Test20DefNewGc.touchMinorGc;/*** Test06FinalizerBlocked** @author Jerry.X.He* @version 1.0* @date 2020-05-17 10:58*/
public class Test06FinalizerBlocked {// identStrprivate String identStr = "identStr";int f01;int f02;int f03;int f04;int f05;// Test06FinalizerBlocked// vmOpts : -Xint -server -Xmx600m -Xms600m -XX:PermSize=128M -XX:MaxPermSize=128M -XX:NewSize=128m -XX:MaxNewSize=128m -XX:SurvivorRatio=8 -XX:+UseSerialGC -XX:+PrintGCDetailspublic static void main(String[] args) throws Exception {Test06FinalizerBlocked obj = new Test06FinalizerBlocked();obj = null;touchMinorGc();System.in.read();}@Overrideprotected void finalize() throws Throwable {System.out.println(" finialize ");System.in.read();}}

Finalizer 只是一个线程, 里面执行的是用户可以 自定义的方法, 如果 某对象的 finalize 阻塞, 或者 耗时过长, 则会对其他的 对象的 finalize 造成影响

参考

25 关于 Signal Dispatcher

26 关于 Attach Listener

27 关于 Reference Handler

07 运行时常量池索引的 rewrite

02 FinalReference.referent的回收时机

28 关于 Finalizer相关推荐

  1. iOS底层原理:weak的实现原理

    作者丨夜幕降临耶 链接: https://juejin.im/post/5e7a322f6fb9a07ca24f79bb 来源:掘金 在iOS开发过程中,会经常使用到一个修饰词weak,使用场景大家都 ...

  2. 如何成为一个区块链开发人员_成为开发人员是社会工作

    如何成为一个区块链开发人员 Times have changed since the old days when an IT professional was this typical shy per ...

  3. Could not install packages due to an EnvironmentError: [Errno 28] No space left on device

    Could not install packages due to an EnvironmentError: [Errno 28] No space left on device 1. 问题现象 安装 ...

  4. 前端面经笔记 2021.8.28

    前端面经笔记 2021.8.28 下面哪些执行结果为true() A.'foo' == new function(){ return String('foo'); }; B.'foo' == new ...

  5. 团队作业4——第一次项目冲刺(Alpha版本)4.28

    ·本次会议为第三次Scrum Meeting会议~ ·本次会议项目经理召开时间为9::30,在教学楼教室召开,召开时长约30分钟,探讨了昨日任务的进展.遇到的困难以及后续所要开展的工作. 1.站立式会 ...

  6. rpm安装的mysql如何数据迁移_【鲲鹏翱翔】数据库04-MySQL5.7.28移植安装指南-RPM包方式...

    1.   简介 MySQL是一种快速易用的关系型数据库管理系统(RDBMS),它通过插件形式提供了多种存储引擎,目前最通用的是InnoDB.作为一款开放源码的数据库软件,MySQL社区及用户活跃度很高 ...

  7. Linux那些事儿 之 戏说USB(28)设备的生命线(十一)

    现在已经使用GET_DESCRIPTOR请求取到了包含一个配置里所有相关描述符内容的一堆数据,这些数据是raw的,即原始的,所有数据不管是配置描述符.接口描述符还是端点描述符都彼此的挤在一起,所以得想 ...

  8. 选项选择Windows XP系统安装MySQL5.5.28图解

    本文纯属个人见解,是对前面学习的总结,如有描述不正确的地方还请高手指正~ Windows XP系统安装MySQL5.5.28图解 MySQL数据库的安装一共分为两个部分:数据库的安装和数据库的配置. ...

  9. 办公室28个经典赞美句子【转】

    1.you look great today.(你今天看上去很棒.)[每天都可以用!] 2. you did a good job. (你干得非常好.)[国际最通用的表扬!] 3. we're so ...

最新文章

  1. 【干货51页PPT】深度学习理论理解探索
  2. SparkSQL介绍
  3. devc 能优化吗_SEO关键词推广要多少钱?关键词优化选择外包靠谱吗?
  4. [android] 百度地图开发 (一).申请AK显示地图及解决显示空白网格问题
  5. anaconda安装PIL库报错:PIL库不存在的解决方法
  6. phpMyAdmin链接MySQL拒接_phpmyadmin连接MySQL服务器被拒绝
  7. C++的多态原理和实现
  8. 典型的php系统由什么组成,完整的计算机系统由什么组成
  9. 六款练手的javaweb项目源码!
  10. php自定义表单程序,自定义流程gooflow2.0+自定义表单
  11. 官方标配,吊炸天的 Linux 可视化管理工具,必须推荐给你
  12. a标签实现下载文件功能
  13. LPDDR4协议规范之 (一)地址映射和容量计算
  14. 人工智能应用-手把手教你用Python硬件编程实现打开或关闭电灯泡
  15. 计算机通信网络(二)路由基本概念及静态路由配置
  16. 工作进度跟踪表excel_在Excel中跟踪时间
  17. 导图解文 从梦想到财富(28)如何成为顶尖高手
  18. ubantu查看设备序列号
  19. android 开源 高斯模糊_Android高斯模糊、高斯平滑(Gaussian Blur)【1】
  20. 打造爆款产品只需四步,学会你也能爆单

热门文章

  1. 如何用pycharm将.ui文件转换为.py文件(内含出错解决方法)
  2. com.monotype.android.font.ktoppo,Zawgyi Myanmar Fonts Free
  3. 统计学的那些冷门思考(各种检验+中心极限)
  4. php get 号,php-GET请求不带问号
  5. Mac--技巧:修复“闪烁的问号”错误提示
  6. Android常用存储类型与简介
  7. 5款良心电脑软件,有一款虽已停更,却依然免费使用
  8. 阿里实人认证android,Android集成
  9. PYTHON 编写程序实现以下功能:计算beg到end之间的所有水仙花数并输出。如果beg到end之间不存在水仙花数,则输出“not found”。
  10. openwrt开启网络共享Samba