JVM虚拟机垃圾回收机制
JVM虚拟机垃圾回收机制
- 垃圾回收机制
- 判断是否存活算法
- 引用计数法
- 可达性分析法
- 最终判定
- 垃圾回收算法
- 分代收集机制
- 空间分配担保
垃圾回收机制
判断是否存活算法
java语言和我们之前学的c/c++不同,c/c++可以手动进行内存释放,那样随时随地就可以释放不必要的内存,减少内存溢出,但我们java的内存是有jvm虚拟机自行释放的,当一个对象不再被使用的时候,jvm会自行释放并回收内存,那么它是怎么样来判断一个对象是否存活的呢?想必这里一定有着一套耐人寻味的算法
引用计数法
1·每个对象都包含一个引用计数器,用于存放引用计数(其实就是存放被引用的次数)
2.每当有一个地方引用此对象时,引用计数+1
3·当引用失效(比如离开了局部变量的作用域或是引用被设定为null)时,引用计数-1
局部变量的作用域:从定义开始,到其所在的大括号结束为止。
4·当引用计数为0时,表示此对象不可能再被使用,因为这时我们已经没有任何方法可以得到此对象的引用了
但这种方法却存在一个问题,如果两个对象相互引用呢?
public class jvm {public static void main(String[] args) {Test a = new Test();Test b = new Test();a.another = b;b.another = a;a = b = null;}private static class Test{Test another;}
}
按照引用计数算法,那么当出现以上情况时,虽然我们无法在得到此对象的引用了,并且此对象我们也无需再使用,但是由于这两个对象直接存在相互引用的情况,那么引用计数器的值将会永远是1,但是实际上此对象已经没有任何用途了。所以引用计数法并不是最好的解决方案。
可达性分析法
首先每个对象的引用都有机会成为树的根节点(GC Roots),可以被选定作为根节点条件如下:
1.位于虚拟机栈的栈帧中的本地变量表中所引用到的对象(其实就是我们方法中的局部变量)同样也包括本地方法栈中JNI引用的对象。
2.类的静态成员变量引用的对象。
3.方法区中,常量池里面引用的对象,比如我们之前提到的String类型对象。
4.被添加了锁的对象(比如synchronized关键字)
5.虚拟机内部需要用到的对象。

一旦已经存在的根节点不满足存在的条件时,那么根节点与对象之间的连接将被断开。此时虽然对象1仍存在对其他对象的引用,但是由于其没有任何根节点引用,所以此对象即可被判定为不再使用。比如某个方法中的局部变量引用,在方法执行完成返回之后:


可以解释成当一个对象为null就是没有指向任何GC Roots则证明这个对象是不可以再使用的了
最终判定
我们在上面讲到的可达性分析法,他只能告诉我们jvm可以去回收,但真正的想回收还必须经过我们的最终判定,并不是说算法判定可以回收之后,这个对象一定会被回收
Object类里面有一个方法名为finalize(),这个方法就是最终判定方法,如果子类里面重写了此方法,放该子类对象被判定为可回收的时候,会进行二次确认,如果确认之后对象依然不满足被回收的条件的时候,那么该对象依然逃脱不了被回收的命运
示例代码:
public class jvm {private static Test a;public static void main(String[] args) throws InterruptedException {a = new Test();a = null;System.gc();Thread.sleep(1000);System.out.println(a);}private static class Test{@Overrideprotected void finalize() throws Throwable {System.out.println(this+"开启了他的");a = this;}}
}
运行结果:

但切记,该方法只会起到一次效果,如果之后再出现这种情况就不会奏效了
示例代码:
public class jvm {private static Test a;public static void main(String[] args) throws InterruptedException {a = new Test();a = null;System.gc();Thread.sleep(1000);System.out.println(a);a = null;System.gc();Thread.sleep(1000);System.out.println(a);}private static class Test{@Overrideprotected void finalize() throws Throwable {System.out.println(this+"开启了他的");a = this;}}
}
运行结果:

之所有代码中要加上Thread.sleep()是因为finalize()方法是新开了一个线程执行的,并且该线程的优先级比较低,以免主线程已经执行完了,该线程还在执行着
当然,除了堆中的对象以外,方法区中的数据也是可以被垃圾回收的,但是回收条件比较严格,这里就暂时不谈了
垃圾回收算法
前面我们介绍了对象存活判定算法,现在我们已经可以准确地知道堆中的哪些对象可以被回收了,那么,接下来就该考虑如何对对象进行回收了,垃圾收集器会不定期地检查堆中的对象,查看它们是否满足被回收的条件。我们该如何对这些对象进行回收,是一个一个判断是否需要回收吗?
分代收集机制
实际上,如冤我们对堆中的每一个对象都依次判断是否需要回收,这样的效率其实是很低的,那么有没有更好地回收机制呢?
第一步,我们可以对堆中的对象进行分代管理。
比如某些对象,在多次垃圾回收时,都未被判定为可回收对象,我们完全可以将这一部分对象放在一起,并让垃圾收集器减少回收此区域对象的频率,这样就能很好地提高垃圾回收的效率了。
因此,Java虚拟机将堆内存划分为新生代、老年代和永久代(其中永久代是HotSpot虚拟机特有的概念,在JDK8之前方法区实际上就是采用的永久代作为实现,而在JDK8之后,方法区由元空间实现,并且使用的是本地内存,容量大小取决于物理机实际大小
这里我们主要讨论的是新生代和老年代。
不同的分代内存回收机制也存在一些不同之处,在HotSpot虚拟机中,新生代被划分为三块,一块较大的Eden空间和两块较小的Survivor空间,默认比例为8:∶ 1∶1,老年代的GC评率相对较低,永久代一般存放类信息等〈其实就是方法区的实现)如图所示:

Minor GC - 次要垃圾回收,主要进行新生代区域的垃圾回收
-触发条件:新生代Eden区容量已满的时候
Major GC -主要垃圾回收,主要进行老年代的垃圾收集
Full DC -完全垃圾回收,对整个java堆内存和方法区进行垃圾回收
·触发条件1:每次晋升到老年代的对象平均大小大于老年代剩余空间
·触发条件2: Minor GC后存活的对象超过了老年代剩余空间
·触发条件3:永久代内存不足(JDK8之前)
·触发条件4∶手动调用System.gc(方法
空间分配担保
考虑一种极端情况(正常情况下新生代的回收率是很高的,所以不用太担心会经常出现这种情况)就是当新生代的Eden区经历过一次回收之后,仍然存在大量的对象。
这时就需要用到空间分配担保机制了,可以把Survivor区无法容纳的对象直接送到老年代,让老年代进行分配担保(当然老年代也得装得下才行)在现实生活中,贷款会指定担保人,就是当借款人还不起钱的时候由担保人来还钱。
好,那既然新生代装不下就丢给老年代,那么要是老年代也装不下新生代的数据呢?这时,老年代肯定担保人是当不成了,那么这样的话,首先会判断一下之前的每次垃圾回收进入老年代的平均大小是否小于当前老年代的剩余空间,如果小于,那么说明也许可以放得下(不过也仅仅是也许,依然有可能放不下,因为判断的实际上只是平均值,万一这一次突然非常大呢),否则,会先来一次FullGC,进行一次大规模垃圾回收,来尝试腾出空间,再次判断老年代是否有空间存放,要是还是装不下,直接抛出0OM错误,摆烂。
相关文章:
JVM虚拟机垃圾回收机制
JVM虚拟机垃圾回收机制垃圾回收机制判断是否存活算法引用计数法可达性分析法最终判定垃圾回收算法分代收集机制空间分配担保垃圾回收机制 判断是否存活算法 java语言和我们之前学的c/c不同,c/c可以手动进行内存释放,那样随时随地就可以释放不必要的内存…...
菜鸟刷题Day3
⭐作者:别动我的饭 ⭐专栏:菜鸟刷题 ⭐标语:悟已往之不谏,知来者之可追 一.字符串压缩:面试题 01.06. 字符串压缩 - 力扣(LeetCode) 描述 字符串压缩。利用字符重复出现的次数,编…...
南京邮电大学数据库第三次课后作业
1.单选(2分) 下列关于模式的术语中,(C)不是指数据库三级模式结构中的外模式 (A)子模式 (B)用户模式 (C)存储模式 (D)用户视图 2单选题(2分) 数据库的三级模式结构中,描述数据全局逻辑…...
【vue2】使用vue常见的业务流程与实现思路
🥳博 主:初映CY的前说(前端领域) 🌞个人信条:想要变成得到,中间还有做到! 🤘本文核心:vue的业务处理思路。前台数据渲染与后台的增删改查操作 【前言】当大家会点开这一篇文章…...
Linux操作系统ARM体系结构处理器机制原理与实现
ARM 的概念ARM(Advanced RISC Machine),既可以认为是一个公司的名字,也可以认为是对一类微处理器的通称,还可以认为是一种技术的名字。ARM 公司并不生产芯片也不销售芯片,它只出售芯片技术授权。其合作公司针对不同需求搭配各类硬…...
Mongodb 常用基本语法与操作
常用操作 1、 Help查看命令提示 db.help(); 2、 切换/创建数据库 use test 如果数据库不存在,则创建数据库,否则切换到指定数据库 3、 查询所有数据库 show dbs; 4、 删除当前使用数据库 db.dropDatabase(); 5、 查看当前使用的数据库 db.getName(); 6、…...
MySQL注入秘籍【绕过篇】
MySQL注入秘籍【绕过篇】1.通用方法2.绕过空格3.绕过引号4.绕过逗号,5.绕过等号6.绕过and/or7.绕过注释符8.绕过函数检测1.通用方法 编码 编码无非就是hex、url等等编码,让传到数据库的数据能够解析的即可,比如URL编码一般在传给业务的时候就会自动解码…...
TCP三次握手/四次挥手
TCP三次握手 任何基于TCP的应用,在发送数据之前,都需要由TCP进行“三次握手”建立连接示意图 第一次握手:客户端PC发送一个SYN位置1(SYN1代表请求服务端建立连接)的TCP报文发送给要建立TCP连接的Server,此…...
Python程序员看见一个好看的手机壁纸网站,开撸!
人生苦短,我用python 最近好像没什么大事, .那就采集一下小——姐——姐————看下吧~ python 安装包资料:点击此处跳转文末名片获取 最近有同学的爬虫代码出了bug,给问我怎么改 于是就发现了这个好看的手机壁纸网站。 这个图片应该是违规…...
浏览器工作原理
一、JavaScript 的历史 JavaScript(简称JS)Web前端开发的脚本语言。 它诞生1995年,由网景公司的 Brendan Eich 开发。最初,JavaScript 被设计用于在网页上嵌入动态内容和交互式功能。 1996年,JavaScript 1.1 成为国…...
对在使用容器HashSet存放自定义对象时重写其类的hashcode和equals方法的几点认识
判断是否是相同对象时,hashcode和equals方法的调用顺序 先调用hashcode()方法,再调用equals()方法如果hashcode()方法得到的哈希值不同,那么两个对象一定不相同,不作后续判断如果hashcode()方法得到的哈希值相同,那么…...
Java集群:单体架构升级到集群架构(二)实现session共享
默认情况下,session是保存在TOMCAT服务器内存中的,如果我们有两个TOMCAT,它们的session是没有共享的。我们这回要做的就是把session保存在redis中,这样两个TOMCAT就可以共享session了。其实这货的详细原理还是很复杂的,…...
MySQL索引及索引失效的分析(MySQL8.0.19)
目录索引数据结构主键索引非主键索引索引在什么时候是有效的?字符串比较大小btween and索引数据结构 主键索引 我们先来看看索引的数据结构,以及我们是如何利用索引来搜索数据的。MySQL的数据存储结构是B树,在叶子节点存储了数据行ÿ…...
第一个 Django 应用
1. 创建项目 1.1 新建项目 首先新建一个项目,名为 mysite,命令如下: django-admin startproject mysite # 或用 django-admin.py运行成功,生成一些目录: mysite/manage.py # 管理 Django 项目的命令行工具mysit…...
001-ksum 求符合条件的 k 个数 1. Two Sum/15. 3Sum/18. 4Sum/
推荐阅读 000-从零开始的数据结构与算法 001-01-ksum 求符合条件的 k 个数 1. Two Sum/15. 3Sum/18. 4Sum/ 002-两数相加 add two numbers 003-无重复字符的最长子串 Longest Substring Without Repeating Characters 004-寻找两个正序数组的中位数 005-最长回文子串 Lon…...
Nginx学习笔记(三)Linux环境下Nginx的安装和部署
目录一、官网下载二、配置基本信息1.上传 Linux2.解压3.安装编译环境4.配置基本信息4.1 配置失败原因(1):没有安装C编译环境4.2 配置失败原因(2):没有安装 PCRE 依赖4.3 配置失败原因(3):没有安装 zlib 依赖5.查看文件列表三、编译安装四、配…...
【十二天学java】day05--数组和循环高级
**# 1.数组 概念: 指的是一种容器,可以同来存储同种数据类型的多个值。 但是数组容器在存储数据的时候,需要结合隐式转换考虑。 比如: 定义了一个int类型的数组。那么boolean。double类型的数据是不能存到这个数组中的&#…...
用队列实现栈和用栈实现队列(C 语言)
目录 一、用队列实现栈 二、 用栈实现队列 一、用队列实现栈 请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。 实现 MyStack 类: void push(int…...
albedo开源框架配置多数据源
前言:公司框架项目一直都没认真阅读过,最近项目需要连接oracle数据,所以尝试使用框架连接多数据库。添加多数据源插件:我们在项目的插件模块内添加多数据源插件:albedo-dynamic-datasource<?xml version"1.0&…...
22张图带你了解IP地址有什么作用
了解IP地址 1、IP地址的格式 在IP协议的报文中,可以得知IP地址是有32个比特,IP地址在计算机中是以二进制的方式处理的,如果全部以二进制的形式来表示,使用跟表达都非常的困难,所以为了人类方便记忆,采用了…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
