分代收集 + 垃圾回收算法

分代假说

1. 弱分代假说(Weak Generational Hypothesis):绝大多数对象都是朝生夕灭的

2. 强分代假说(Strong Generational Hypothesis):熬过越多次垃圾收集过程的对象就越难以消亡

3. 跨代引用假说(Intergenerational Reference Hypothesis):跨代引用相对于同代引用来说仅占极少数

💛 收集器应该将Java堆划分出不同的区域,然后将回收对象依据其年龄(年龄即对象熬过垃圾收集过程的次数)分配到不同的区域之中存储。

显而易见,如果一个区域中大多数对象都是朝生夕灭,难以熬过垃圾收集过程的话,那么把它们集中放在一起,每次回收时只关注如何保留少量存活而不是去标记那些大量将要被回收的对象(解释1),就能以较低代价回收到大量的空间;如果剩下的都是难以消亡的对象,那把它们集中放在一块,虚拟机便可以使用较低的频率来回收这个区域,这就同时兼顾了垃圾收集的时间开销和内存的空间有效利用(解释2)。

 解释1:

 解释2:

        时间开销 ——> 支取扫描1%,比扫描99%快得多;
        内存空间有效利用 ——> 1%移动时不会直接移动,而是复制一份,将复制移动过去,成功后,删除原有的。


新生代 —— 存放朝生夕死的对象

老年代 —— 存放新生代回收后还存活的对象,不容易死的对象

💛 在新生代中,每次垃圾收集时都发现有大批对象死去,而每次回收后存活的少量对象,将会逐步晋升(解释3)到老年代中存放。

 解释3:

 当年龄达到13时,就进入老年代


跨代引用

分代收集有一个问题:跨代引用

比如说新生代中有一个对象A引用老年代的一个对象 B,只要老年代的对象不回收,新生代的这个对象也不会被回收。每次新生代回收时还是要去扫(判断A是否需要回收,此时也需要去判断A引用的B是否被回收),也不能直接将A放入老年代,因为可能在A的年龄为12时,对象B就被回收了。

解决跨代引用的问题

💛 存在互相引用关系的两个对象,是应该倾向于同时生存或者同时消亡的。

举个例子,如果某个新生代对象存在跨代引用,由于老年代对象难以消亡,该引用会使得新生代对象在收集时同样得以存活,进而在年龄增长之后晋升到老年代中,这时跨代引用也随即被消除了。

跨代引用只占极少数,就不应再为了少量的跨代引用去扫描整个老年代,也不必浪费空间专门记录每一个对象是否存在及存在哪些跨代引用,只需在新生代上建立一个全局的数据结构(该结构被称为“记忆集”,Remembered Set)。这个结构把老年代划分成若干小块,标识出老年代的哪一块内存会存在跨代引用。
一旦出现跨代引用,就会出现在老年代的跨代引用区域。当发生新生代收集时,只有包含了跨代引用的小块内存里的对象会进行扫描。

虽然这种方法需要在对象改变引用关系(如将自己或者某个属性赋值)时维护记录数据的正确性,会增加一些运行时的开销,但比起收集时扫描整个老年代来说仍然是划算的。

垃圾回收算法

一、标记-清除算法

标记:哪些对象可以存活或者哪些对象可以回收

它的主要缺点有两个:

  • 第一个是执行效率不稳定。
    如果Java堆中包含大量对象,而且其中大部分是需要被回收的,这时必须进行大量标记和清除的动作,导致标记和清除两个过程的执行效率都随对象数量增长而降低;

  • 第二个是内存空间的碎片化问题。
    标记、清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致当以后在程序运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。

基本不使用

二、标记-复制算法

根据IBM研究,新生代中的对象有98%熬不过第一轮收集(普通场景下,无法保证每次都是这样),因此不需要按照1:1的比例来划分新生代的内存空间,而是使用了8:1:1分配内存空间。

 每次进行收集时,将前8:1空间的存活对象一次性复制到另外的1比例,然后清理掉前8:1空间的朝生夕死的对象。

💛 内存的分配担保好比我们去银行借款,如果我们信誉很好,在98%的情况下都能按时偿还,于是银行可能会默认我们下一次也能按时按量地偿还贷款,只需要有一个担保人能保证如果我不能还款时,可以从他的账户扣钱,那银行就认为没有什么风险了。

标记-复制算法虽然弥补了标记-清除算法的缺点,但标记-复制算法还是有自己的缺点:

首先就是在对象存活率较高时要进行较多的复制操作,效率将会降低

还有一种情况,就是在十分之九的的对象里超过十分之一存活,那么复制到右边区域时空间大小就不够了。

为了解决这些,出现了标记-整理算法。

三、标记-整理算法

标记过程仍与标记-清除算法相同,但后续让所有存活的对象都向内存空间一端移动,然后直接清理掉边界以外的内存。

弊端

  • 像在老年代这种每次回收都有大量对象存活区域,移动存活对象并更新所有引用这些对象的地方将会是一种极为负重的操作,而且这种对象移动操作必须全程暂停用户应用程序(解释4)才能进行 ——> 宕机 stop the world 

但不移动的话,碎片化问题严重,得不到解决也会导致性能、存储量降低。

解释4:

如果不暂停的话,刚标记的时候只占据一块,标记完以后整理时可能就变成了占据了两块。

💛 通常标记-清除算法也是需要停顿用户线程来标记、清理可回收对象的,只是停顿时间相对而言要来的短而已。

于是混合式出现了,让虚拟机平时多数时间都采用标记-清除算法,暂时容忍内存碎片的存在,直到内存空间的碎片化程度已经大到影响对象分配时,再采用标记-整理算法收集一次,以获得规整的内存空间。

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

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

相关文章

leetcode 125.验证回文串

⭐️ 题目描述 🌟 leetcode链接:https://leetcode.cn/problems/valid-palindrome/ 思路: 这道题只判断字符串中的字母与数字是否是回文。虽然小写大写字母可以互相转换,但是里面是含有数字字符的,所以先统一&#xff…

爬虫逆向实战(十八)--某得科技登录

一、数据接口分析 主页地址:某得科技 1、抓包 通过抓包可以发现数据接口是AjaxLogin 2、判断是否有加密参数 请求参数是否加密? 查看“载荷”模块可以发现有一个password加密参数和一个__RequestVerificationToken 请求头是否加密? 无…

JavaScript 快速入门手册

本篇文章学习: 菜鸟教程、尚硅谷。 JavaScript 快速入门手册 💯 前言: 本人目前算是一个Java程序员,但是目前环境… ε(ο`*))) 一言难尽啊,blog也好久好久没有更新了,一部分工作原因吧(外包真…

window安裝python2.7.0

官网下载安装 https://www.python.org/downloads/release/python-270/ 选中所有用户,然后点击next 切换安装位置,最好不要选择c盘 点击next 等待安装 安装完成 配置环境变量 将python安装路径添加到系统环境变量 cmd窗口输入python,会打开应用商…

Idea中隐藏指定文件或指定类型文件

Setting ->Editor ->Code Style->File Types → Ignored Files and Folders输入要隐藏的文件名,支持*号通配符回车确认添加

基于51单片机直流电机转速数码管显示控制系统

一、系统方案 本文主要研究了利用MCS-51系列单片机控制PWM信号从而实现对直流电机转速进行控制的方法。本文中采用了三极管组成了PWM信号的驱动系统,并且对PWM信号的原理、产生方法以及如何通过软件编程对PWM信号占空比进行调节,从而控制其输入信号波形等…

LNMP及论坛搭建

目录 安装Nginx服务 1.安装依赖包 2.创建运行用户、组(Nginx 服务程序默认以 nobody 身份运行,建议为其创建专门的用户账号,以便更准确地控制其访问权限) 3.编译安装Nginx 4.优化路径 5.添加 Nginx 系统服务 安装 MySQL 服…

正则表达式在PHP8中的应用案例-PHP8知识详解

正则表达式在php8中有许多应用案例。以下是一些常见的应用场景:如数据验证、数据提取、数据替换、url路由、文本搜索和过滤等。 1、数据验证 使用正则表达式可以对用户输入的数据进行验证,例如验证邮箱地址、手机号码、密码强度等。 下面是一个用正则表…

BDA初级分析——SQL多表连接应用

一、用SQL拼接数据 三个初始数据 问题1:在所有的数据里,销售额最高的产品品类名是什么? 问题2:是否有什么产品是在所观测的时间里没有被购买过的? 拼接数据:JOIN join,加入 作用&#xff1…

uniapp 上传比较大的视频文件就超时

uni.uploadFile,上传超过10兆左右的文件就报错err:uploadFile:fail timeout,超时 解决: 在manifest.json文件中做超时配置 uni.uploadFile({url: this.action,method: "POST",header: {Authorization: uni.getStorage…

【es6】中的Generator

Generator 一、Generator 是什么?1.1 与普通函数写法不一样,有两个不同 二、Generator 使用2.1 书写方法 三、yield语句3.1 yield和return3.2 注意事项3.3 yield*语句3.4 yield*应用 四、next方法4.1参数 总结 一、Generator 是什么? Genera…

[JavaWeb]【一】入门JavaWeb开发总概及HTML、CSS、JavaScript

目录 一 特色 二 收获​编辑 三 什么是web? 四 网站的工作流程 五 web网站的开发模式​编辑 六 web开发课程学习安排 七、初始web前端 八 HTML、CSS 8.1 什么是HTNL\CSS(w3cschool) 8.2 HTML快速入门 8.3 VS Code开发工具 8.3.1 插件 8.3.2 主题(改变颜色&…

【C++】做一个飞机空战小游戏(八)——生成敌方炮弹(rand()和srand()函数应用)

[导读]本系列博文内容链接如下: 【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动【C】做一个飞机空战小游戏(三)——getch()函数控制任意造型飞机图标移动 【C】做一个飞…

solidwords(5)

我们打算从上面画出总体,再从上面、侧面切除 最后成品

blender 发射体粒子

发射体粒子的基础设置 选择需要添加粒子的物体,点击右侧粒子属性,在属性面板中,点击加号,物体表面会出现很多小点点,点击空格键,粒子会自动运动,像下雨一样; bender 粒子系统分为两…

抖音火山引擎推出免费域名DNS和公共DNS服务

抖音旗下的云计算服务火山引擎最近推出了"TrafficRoute DNS 套件"服务,其中包括两款产品,对软希网来说非常有用。 1.域名DNS: 这是一个用于网站域名的DNS服务,可以加速域名解析速度,从而提升网站的速度。如…

【3Ds Max】挤出命令的简单使用(实现二维变三维)

简介 在3ds Max中,"挤出"(Extrude)是一种常用的建模操作,用于在平面或曲面上创建立体几何形状。以下是使用3ds Max中的挤出命令的基本步骤: 创建基本几何形状: 在3ds Max中创建一个基本的几何形…

自动驾驶——车辆动力学模型

/*lat_controller.cpp*/ namespace apollo { namespace control {using apollo::common::ErrorCode;//故障码 using apollo::common::Status;//状态码 using apollo::common::TrajectoryPoint;//轨迹点 using apollo::common::VehicleStateProvider;//车辆状态信息 using Matri…

Kotlin实战之获取本地配置文件、远程Apollo配置失败问题排查

背景 Kotlin作为一门JVM脚本语言,收到很多Java开发者的青睐。 项目采用JavaKotlin混合编程。Spring Boot应用开发,不会发生变动的配置放在本地配置文件,可能会变化的配置放在远程Apollo Server。 问题 因为业务需要,需要增加一…

MybatisPlus整合p6spy组件SQL分析

目录 p6spy java为什么需要 如何使用 其他配置 p6spy p6spy是一个开源项目,通常使用它来跟踪数据库操作,查看程序运行过程中执行的sql语句。 p6spy将应用的数据源给劫持了,应用操作数据库其实在调用p6spy的数据源,p6spy劫持到…