当前位置: 首页 > news >正文

JVM原理(三):JVM对象回收判定机制与回收算法

如何判断一个对象是否存活(即是否还分配在堆中),那看他是否还在用。

1. 引用计数算法

这是一种判断方式,相应的方法就是:如果一个对象被引用,那将被引用的对象中的一个计数器加一,引用失效就减一。在任何时刻引用计数器为0那就是没有应用的话,那该对象就可被回收了。

存在着的缺陷:当两个对象相互引用的时候,就会造成一种循环,引用计数器无法判断他们是否还有用。

Java虚拟机不用这种。

2. 可达性分析算法

通过“GC Roots”的跟对象作为起始节点集,从这些结点开始,根据应用关系向下搜索,搜索过程中走过的路径叫做引用链,如果某个对象(或某个对象链)不在引用链上,会被标记为可回收对象(关于是否可以真正回收可以查看3.2.4)。

被固定可作为GCRoot对象有以下几种:

  • 虚拟机栈中引用的对象

  • 静态属性引用对象

  • 常量引用对象

  • 本地方发展中Native方法引用的对象

  • 一些常驻的异常对象

  • 被同步锁持有的对象

  • 反应Java虚拟机内部信息的对象(一些工具)

3. 再谈引用

无论是引用计数算法还是可达性分析算法判断对象是否可以被回收,我们都离不开引用的关系。

JDK1.2版本:强引用、软引用、弱引用、虚引用

强引用:是最传统的“引用”的定义,是指在程序代码之中普遍存在的引用赋值,即类似“Object obj=new Object()”这种引用关系。无论任何情况下,只要强引用关系还存在,垃圾收集器就永远不会回收掉被引用的对象

软引用:是用来描述一些还有用,但非必须的对象。只被软引用关联着的对象,在系统将要发生内存溢出异常前,会把这些对象列进回收范围之中进行第二次回收,如果这次回收还没有足够的内存,才会抛出内存溢出异常。在JDK 1.2版之后提供了SoftReference类来实现软引用。

弱引用:也是用来描述那些非必须对象,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾收集发生为止。当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。在JDK 1.2版之后提供了WeakReference类来实现弱引用。

虚引用:也称为“幽灵引用”或者“幻影引用”,它是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得--一个对象实例。为-一个对象设置虚引用关联的唯一目的只是为了能在这个对象被收集器凹收时收到一个系统通知。在JDK1.2版之后提供了PhantomReference类来实现虚引用。

4. 生存还是死亡?

可达性算法补充。

可达性算法判定为不可达对象后,这个对象还不是“非死不可”,这个对象要真正死亡,还需要至少经历两次标记过程。

第一次标记:可达性分析算法发现没有和GC Root相连,会被第一次标记。

中间流程:如果对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用了,那么虚拟机就会直接调用(finalize方法只能被执行一次)。

第二次标记:如果该对象finalize方法判定为有必要执行,那就会把该对象放到F-Queue队列中。finalize方法是对象逃脱死亡命运的最后一次机会,如果这时候该对象和GC Root上的引用链连接上了,那么就可以逃脱被回收的命运,不然就会被回收。

5. 回收方法区

方法区的垃圾收集主要回收两部分内容:废弃的常量和不再使用的类型。

判断常量是否可以被回收:

  1. 没有任何字符串对象引用该常量,且虚拟机中也没有其他地方引用这个字面量。

判定一个类型是否属于“不再被使用的类”:

  1. 该类所有的实例都已被回收,也就是Java堆中不存在该类及其任何派生子类的实例。

  2. 加载该类的类加载器已经被回收,这个条件除非是经过精心设计的可替换类加载器的场景,否则通常很难达成的。

  3. 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类方法。

相关文章:

  • vue3 cdn 的方式 ,通过 URLSearchParams 来获取参数的信息。
  • JAVA API营业执照识别、企业工商信息查询
  • flask项目部署总结
  • 《面向对象分析与设计》学习笔记1
  • 如何在 Odoo 16 中向新视图添加字段
  • coco dataset标签数据结构(json文件)
  • 解决 npm intasll 安装报错 Error: EPERM: operation not permitted
  • 【分布式系统五】监控平台Zabbix实际监控运用(命令+截图详细版)
  • sql业务场景分析思路参考
  • 免费的二级域名分发,您确定不要试试吗?
  • 嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
  • 量化交易对长期投资的影响
  • 【matlab】回归预测——智能优化算法支持向量机
  • Java中继承接口和实现接口的区别、接口和抽象类的区别、并理解关键字interface、implements
  • centos7.9 python3环境(virtualenv)搭建及所遇错误
  • [rust! #004] [译] Rust 的内置 Traits, 使用场景, 方式, 和原因
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • 【399天】跃迁之路——程序员高效学习方法论探索系列(实验阶段156-2018.03.11)...
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • Asm.js的简单介绍
  • Create React App 使用
  • ES10 特性的完整指南
  • Object.assign方法不能实现深复制
  • python docx文档转html页面
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • TypeScript迭代器
  • vagrant 添加本地 box 安装 laravel homestead
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • 案例分享〡三拾众筹持续交付开发流程支撑创新业务
  • -- 查询加强-- 使用如何where子句进行筛选,% _ like的使用
  • 从输入URL到页面加载发生了什么
  • 分享一份非常强势的Android面试题
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 前端路由实现-history
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 使用 @font-face
  • 写给高年级小学生看的《Bash 指南》
  • 一个项目push到多个远程Git仓库
  • ​​​【收录 Hello 算法】9.4 小结
  • ​一、什么是射频识别?二、射频识别系统组成及工作原理三、射频识别系统分类四、RFID与物联网​
  • #php的pecl工具#
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (3)llvm ir转换过程
  • (aiohttp-asyncio-FFmpeg-Docker-SRS)实现异步摄像头转码服务器
  • (C++17) optional的使用
  • (C语言)深入理解指针2之野指针与传值与传址与assert断言
  • (Java数据结构)ArrayList
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (附源码)spring boot火车票售卖系统 毕业设计 211004
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (蓝桥杯每日一题)平方末尾及补充(常用的字符串函数功能)
  • (三十五)大数据实战——Superset可视化平台搭建