JVM 垃圾回收机制(可达性分析、引用计数)

目录

    • 1 什么是垃圾
    • 2 为什么需要回收
    • 3 哪些对象被判定为垃圾呢
      • 3.1 引用计数法
      • 3.2 可达性分析算法:GC Roots根

1 什么是垃圾

垃圾是指在运行程序中没有任何指针指向的对象,就是需要被回收的。

2 为什么需要回收

  • 执行程序会不断地分配内存空间,如果不进行回收,内存迟早都会被消耗完。

  • 除了释放没用的对象,垃圾回收也可以清除内存里的记录碎片。碎片整理将所占用的堆内存移到堆的一端,以便JVM将整理出来的内存分配给新的对象

3 哪些对象被判定为垃圾呢

在堆空间和元空间中,GC这条守护线程会对这些空间开展垃圾回收⼯作,那么GC如何判断这些空间的对象是否是垃圾,有两种算法引用计数法可达性分析算法

3.1 引用计数法

​ 每个对象有个引用计数器属性,记录被引用的情况。对象被引⽤,则计数器+1,如果计数器是0,那么对象将被判定为是垃圾,于是被回收。

这种算法,实现简单,判定效率高。但缺点是需要需要单独的字段存储计数器,每次赋值都需要更新计数器,增加了空间和时间的开销。缺最严重的是无法解决循环依赖问题。因此JVM⽬前的主流⼚商Hotspot没有使⽤这种算法。

注:什么是循环依赖问题?

如下图所示,p引用了A,对象A间接引用了C,C又引用了A。方法执行完p不再需要引用A,但A和C的引用没有消失,引用计数器还都是1,不会被回收。
在这里插入图片描述

3.2 可达性分析算法:GC Roots根

该算法的基本思想就是:

通过一系列被称为「GC Roots」的根对象作为起始节点集,从这些节点开始,通过引用关系向下搜寻,搜寻走过的路径称为「引用链」,如果某个对象到GC
Roots没有任何引用链相连,就说明该对象不可达,即可以被回收。

哪些会被认定为GC Roots根呢?

  • 方法区静态属性引用的对象
    全局对象的一种,Class对象本身很难被回收,回收的条件非常苛刻,只要Class对象不被回收,静态成员就不能被回收。
  • 方法区常量池引用的对象
    也属于全局对象,例如字符串常量池,常量本身初始化后不会再改变,因此作为GC Roots也是合理的。
  • 方法栈中栈帧局部变量表引用的对象
    属于执行上下文中的对象,线程在执行方法时,会将方法打包成一个栈帧入栈执行,方法里用到的局部变量会存放到栈帧的局部变量表中。只要方法还在运行,还没出栈,就意味这局部变量表的对象还会被访问,GC就不应该回收,所以这一类对象也可作为GC Roots。
  • 本地方法栈中引用的对象
    和上一条本质相同,无非是一个是Java方法栈中的变量引用,一个是native方法(C、C++)方法栈中的变量引用。
  • 被同步锁持有的对象
    synchronized锁住的对象也是绝对不能回收的,当前有线程持有对象锁呢,GC如果回收了对象,锁不就失效了。

五种变量的位置如下:

静态变量会在方法区中存一个引用,市级指向堆内存,局部变量表也是如此。

在这里插入图片描述

总结

可达性分析就是JVM首先枚举根节点,找到一些为了保证程序能正常运行所必须要存活的对象,然后以这些对象为根,根据引用关系开始向下搜寻,存在直接或间接引用链的对象就存活,不存在引用链的对象就回收。

GC再扫描堆空间的某个节点时,会向上遍历,看看能不能遍历到gc roots根节点,如果不能,那么意味着这个对象是垃圾。

例如下图,对象4、5、6都没有和GC Root根节点相连,会被判定为垃圾回收。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

百度测试开发工程师面试心得

百度测试开发实习生面试心得: 电话面试: 面试官:首先做一下自我介绍吧 我:我是***,来自什么大学,现在大三,在学校期间担任过部长,副主席等职务, 组织举办了很多比赛&…

Xcode 14.3.1build 报错整理

1、Command PhaseScriptExecution failed with a nonzero exit code 2、In /Users/XX/XX/XX/fayuan-mediator-app-rn/ios/Pods/CocoaLibEvent/lib/libevent.a(buffer.o), building for iOS Simulator, but linking in object file built for iOS, file /Users/XX/XX/XX/fayuan…

【探索Linux】—— 强大的命令行工具 P.11(基础IO,文件操作)

阅读导航 前言一、C语言的文件操作二、C的文件操作三、Linux系统文件操作(I/O接口)1. open()⭕传入多个打开方式(按位或操作将不同的标志位组合在一起) 2. write()3. read()4. close()5. lseek() 温馨提示 前言 前面我们讲了C语言…

Windows:VS Code IDE安装ESP-IDF【保姆级】

物联网开发学习笔记——目录索引 参考: VS Code官网:Visual Studio Code - Code Editing. Redefined 乐鑫官网:ESP-IDF 编程指南 - ESP32 VSCode ESP-ID Extension Install 一、前提条件 Visual Studio Code IDE安装ESP-IDF扩展&#xf…

机器学习的原理是什么?

训过小狗没? 没训过的话总见过吧? 你要能理解怎么训狗,就能非常轻易的理解机器学习的原理. 比如你想教小狗学习动作“坐下”一开始小狗根本不知道你在说什么。但是如果你每次都说坐下”然后帮助它坐下,并给它一块小零食作为奖励,经过多次…

Android---Android 是如何通过 Activity 进行交互的

相信对于 Android 工程师来说,startActivity 就像初恋一般。要求低,见效快,是每一个菜鸟 Android 工程师迈向高级 Android 工程师的必经阶段。经过这么多年的发展,startActivity 在 google 的调教下已经变得愈发成熟,对…

Ubuntu:Arduino IDE 开发环境配置【保姆级】

物联网开发学习笔记——目录索引 本章主要介绍在Ubuntu系统搭建Arduino IDE 开发环境,windows系统请移步:Windows:Arduino IDE 开发环境配置【保姆级】 参考官网:Arduino - Home 有关更多详细信息,请参阅 Arduino I…

深度学习问答题(更新中)

1. 各个激活函数的优缺点? 2. 为什么ReLU常用于神经网络的激活函数? 在前向传播和反向传播过程中,ReLU相比于Sigmoid等激活函数计算量小;缓解梯度消失问题。对于深层网络,Sigmoid函数反向传播时,很容易就…

分布式事务协调中间件---seata快速入门

分布式事务 Seata,之前叫做Fescar,是一个开源的分布式事务解决方案,它主要致力于提供高效和简单的分布式事务服务。Seata主要用于解决微服务架构下的数据一致性问题。 Seata 的基本原理是基于两阶段提交 (2PC) 以及三阶段提交 (3PC)&#xff…

【LeetCode热题100】--215.数组中的第K个最大元素

215.数组中的第K个最大元素 本题主要是返回数组排序之后的倒数第k个位置 方法一:基于快速排序 思路和算法 我们可以用快速排序来解决这个问题,先对原数组排序,再返回倒数第 k 个位置,这样平均时间复杂度是 O(nlog⁡n)&#xff0…

npm install报--4048错误和ERR_SOCKET_TIMEOUT问题解决方法之一

一、问题描述 学习vue数字大屏加载动漫效果时,在项目终端页面输入全局下载指令 npm install -g json-server 问题1、报--4048错误 会报如下错误 operation not permitted......errno: -4048code:EPERMsyscall: mkdir......The operation was reiected by your op…

Qt应用开发(基础篇)——列表视图 QListView

一、前言 QListView类继承于QAbstractItemView类,提供了一个列表或者图标视图的模型。 视图基类 QAbstractItemView QListView效果相当于Windows文件夹右键->查看->图标和列表,使用setViewMode()设置视图模式,并且提供setIconSize()函数…