JVM java主流的追踪式垃圾收集器

目录

前言

分代垃圾收集理论

标记清除算法

标记复制算法 

标记整理法        


前言

        从对象消亡的角度出发, 垃圾回收器可以分为引用计数式垃圾收集和追踪式垃圾收集两大类, 但是java主流的一般是追踪式的垃圾收集器, 因此我们重点讲解. 

分代垃圾收集理论

        分代收集这种理论其实就是在说两件事: 

  1. 绝大多数的对象都是朝生夕灭
  2. 熬过多次GC的对象就越是难以消亡

        这两个理论将java的堆区划分为了不同的区域, 难以消亡的对象放在一起, 形成类似于老年代这种的内存区域, 这样的内存区域, 垃圾回收的频率小, 存活的对象数量占比整个老年代高.  然后把那些熬不过垃圾回收的放在一起, 然后标记其中少了不需要回收的对象, 然后将其余的回收即可. 通过这种分代的设计, 其实就可以给不同的内存区域以合适的GC频率. 来较低由垃圾回收器带来的性能消耗和空间的消耗.

        分了代之后, 垃圾回收器就可以根据不同的年龄代的内存区域进行独立的回收, 例如可以单独对年龄小的类对象进行回收, 老年代的可以稍后或者在需要的时候进行回收. 

        在商用的java里面, 设计者至少会将java堆区分为两个年代的区域: 新生代, 老年代: 

  1. 新生代: 对象朝生夕灭, 存活概率低, 这个区域每次GC都有大量的对象死去, 存活下来的才有机会进入老年代
  2. 老年代: 对象的存活几率大, 每次GC都有大量的对象存活. 

        但是分代收集也并非只是简单的对一个内存区域根据对象的存活概率来进行划分, 还需要考虑很多额外的事情, 例如老年代中可能会存在对象依赖新生代中的对象, 因此其实你无法直接清理掉新生代中某些已经被老年代中的对象引用的对象. 你必须查看老年代, 看有没有对象引用它. 

        遍历整个老年代无疑是给系统增加了非常多的负担, 但是其实实际上, 老年代中引用新生代中的对象的例子很少, 并且一般情况下, 如果新生代中的对象死亡, 那么依赖这个新生代对象的老年代中的对象, 也应该跟它一样倾向于死亡. 

        如果新生代中的对象 , 因为老年代中对象的引用导致这个对象一只没有被GC, 那么就会慢慢升级到老年代, 以至于和同尊级别相同, 都为老年代. 跨时代的引用就消失了. 

        在实际上跨代引用的对象其实很少,  因此我们只需要特别标记出一块特别的内存区域, 用来表示这个区域里面的年龄大的对象是具有新生代对象引用的对象, 然后在进行回收新生代的时候, 只需要在一小块的老年代内存中查找是否具有新生代引用的对象即可. 

        再细一点, 你可以将老年代划分为多个内存区域, 然后标记处那些具有新生代引用的内存区域, 扫描的时候, 也只需要扫描那些具有标记的内存区域即可, 但是在扫描的过程中, 可能会出现一种情况, 那就是扫描的时候需要维护数据的正确性, 也就是保证扫描的时候,, 其引用被修改了, 例如扫描之前一个老年代对象本来是引用了一个新生代的对象, 但是这个新生代对象在扫描其老年代的时候, 这个老年代的对象引用了另外一个对象, 而不是当前需要扫描其老年代引用的对象. 


标记清除算法

        最基础的垃圾收集算法, 简单来说就是先标记出所有的需要回收的对象, 然后在清理阶段, 清理掉被标记的对象, 反之亦可. 好处就是逻辑简单, 不需要修改修改其他地方对没有被回收对象的引用. 

        其算法的思路逻辑简单, 但是有一个缺点, 那就是不稳定, 你永远不能保证, 你所标记的对象只是少数, 在大量的对象被标记并需要被回收的时候, 会导致标记和执行的效率会非常慢, 第二个是如图所示, 因为对象是直接清除, 而不是将空闲的内存整理到一边, 被使用的内存整理到另外一边, 因此内存会出现很多碎片, 

        如果由于过多的碎片, 导致新建的对象无法找出一块足够大小的连续的内存, 就又不得不触发一次GC, 但是再一次GC之后会不会出现足够大的能容下新对象的内存, 还是个未知数 ... 



标记复制算法 

        简称复制算法, 核心思路就是 将一个内存划为两块大小相同的空间, 在一次GC之前, 只是用其中的一块, 用到差不多了的时候, 需要GC了, 就以此找出里面没有被标记需要回收的对象, 然后将其规整的复制到另外一边, 避免了其内存碎片的产生, 然后复制完之后, 直接就可以清理掉被复制的那块内存, 然后新建对象就可以在规整的内存的那一边进行创建. 

         只要是标记, 就要关注被标记为需要回收的对象的数量, 如果数量太多, 依然会因为标记和清理而影响性能, 同时如果大量对象都是存活的话, 还需要将大量的对象都复制到内存的另外一边, 这就额外造成了性能的消耗. 同时移动对象的内存地址之后, 还需要去修改引用其对象的局部变量或则好常量等.   而且可用的空间, 被缩小了一半. 

        但是这种方法避免的内存碎片的产生.

        但是实际情况确实, 每次回收其实只有少部分对象存活, 例如100个对象中, 一次GC后可能只剩下了10个对象左右, 保守一点, 我们可以将内存区域的划分为 8 : 2, 也就是每次新建的时候, 将新生代分为两部分, 新建的对象都在8这个占比的区域中, 然后等要到了GC的时候, 就将存活的对象规整的复制到2成内存占比的空间中, 修改引用地址之后, 直接将8成的内存空间直接释放掉即可.

        有的也可以将内存划为3块, 一块占比为80%, 另外两块分别占比10%, 我们分配内存, 只在80%和一块10%内存占比的区域中分配内存, 然后要GC的时候, 就将GC存活的对象一次性复制到另外一块10%内存占比的区域中

        无论是什么情况, 你都需要考虑一件事情, 那就是你无法保证, 每次存活的对象都占总对象的0~20%, 因此如果存活的对象, 大于小内存占比内存区域的可用空间的话, 就需要进行内存补偿,让其有足够的内存来分配, 例如老年代. 也就是说如果由于存货的对象过多, 存不下, 就可以将这些存活的对象一部分让其进入老年代进行存储.



标记整理法        

        标记复制算法在对象存活的数量过多的时候, 会存在复制效率过低的情况, 同时你会白白浪费一半左右的空间, 如果你不想浪费这一半的空间, 使用2 8 分的情况, 就需要为小内存进行内存补偿. 

        而标记整理法综合了标记清除算法和复制算法的优点: 

        首先, 对内存中需要回收的对象进行标记, 然后将存活对象移动到内存的一边, 然后直接清除掉存活的内存对象所占区域的区域

        缺点很明显, 需要移动对象, 如果移动对象数量过多, 那么就将会存为一种负担, 移动的存活对象还需要及时更新引用, 并且在移动和更新完成之前, 你不能使用它. 但是不考虑移动, 直接清理就会产生空间碎片化的情况. 但是如果完全不整理内存的碎片, 那么就需要引入类似于win10的内存分配器来解决碎片问题, 

        还有一种方式就是我没必要一上来就使用标记整理, 我可以在内存足够的时候, 先使用性能高, 代价小的标记清除算法, 然后后续再因为内存不够而分配失败 , 那么就进行整理, 将内存整理到一起,这样就完美的避开了他们的缺点.

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

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

相关文章

【vue3】vue3.3新特性真香

距离vue3.3发布已经过了一年多(2023.5.11),vue3.3提高开发体验的新特性你用了吗&#xff1f; 组件内部导入复杂类型 3.3之前想在组件内部导入复杂类型做props类型是不支持的。 <script setup lang"ts">import type { People } from /types;withDefaults(define…

python测试开发---js基础

JavaScript (JS) 是一种广泛用于前端开发的编程语言&#xff0c;其主要用于实现网页的动态交互功能。要掌握 JavaScript 的基础知识&#xff0c;主要需要理解以下几个核心概念&#xff1a; 1. 变量与数据类型 JavaScript 提供了不同的数据类型&#xff0c;并允许通过 var、le…

使用Refine构建项目(1)初始化项目

要初始化一个空的Refine项目&#xff0c;你可以使用Refine提供的CLI工具create-refine-app。以下是初始化步骤&#xff1a; 使用npx命令&#xff1a; 在命令行中运行以下命令来创建一个新的Refine项目&#xff1a; npx create-refine-applatest my-refine-project这将引导你通过…

Linux Vim编辑器常用命令

目录 一、命令模式快捷键 二、编辑/输入模式快捷键 三、编辑模式切换到命令模式 四、搜索命令 注&#xff1a;本章内容全部基于Centos7进行操作&#xff0c;查阅本章节内容前请确保您当前所在的Linux系统版本&#xff0c;且具有足够的权限执行操作。 一、命令模式快捷键 二…

企业专用智能云盘 | 帮助企业便捷管控企业文档 | 天锐绿盘云文档安全管理系统

由于当前多数企业内部的办公文件普遍散落于各员工电脑中&#xff0c;导致存在诸多潜在的文档使用风险。为优化团队协作效率&#xff0c;天 锐 绿盘是一款集文档统一管理、高效协同于一体的企业云盘&#xff0c;帮助企业解决文档管理中的诸多难题。 【地址&#xff1a;点击了解天…

STM32 MCU学习资源

STM32 MCU学习资源 文档下载需要注册登录账号 ST公司官方文档 STM32 MCU开发者资源 STM32F446 相关PDF文档 ST中文论坛 中文译文资料 ST MCU中文官网 其他学习资源 野火STM32库开发实战指南 零基础快速上手STM32开发&#xff08;手把手保姆级教程&#xff09; 直接使…

如何切换npm到淘宝的最新镜像源?

目录 前言一、查看当前npm镜像源二、切换到淘宝镜像源三、验证是否成功切换四、其他注意事项总结前言 要切换npm到淘宝的最新镜像源,您可以按照以下步骤操作: 一、查看当前npm镜像源 在更改npm镜像源之前,首先需要查看当前npm正在使用的镜像源地址。您可以通过在命令行(…

【2023工业异常检测文献】SimpleNet

SimpleNet:ASimpleNetworkforImageAnomalyDetectionandLocalization 1、Background 图像异常检测和定位主要任务是识别并定位图像中异常区域。 工业异常检测最大的难题在于异常样本少&#xff0c;一般采用无监督方法&#xff0c;在训练过程中只使用正常样本。 解决工业异常检…

TCP客户端编码和解码处理:发送和接收指定编码消息

文章目录 引言基于Netty实现TCP客户端Netty发送GBK编码指令Netty接收GBK编码基于Channel发送指令基于ChannelHandlerContext发送指令:建立连接时发送登陆指令开启日志,查看报文信息基于ChannelInboundHandlerAdapter进行业务逻辑处理原生API实现TCP客户端基于DataOutputStrea…

AI预测福彩3D采取888=3策略+和值012路或胆码测试9月19日新模型预测第92弹

经过90多期的测试&#xff0c;当然有很多彩友也一直在观察我每天发的预测结果&#xff0c;得到了一个非常有价值的信息&#xff0c;那就是9码定位的命中率非常高&#xff0c;90多期一共只错了10次&#xff0c;这给喜欢打私房菜的朋友提供了极高价值的预测结果~当然了&#xff0…

C语言中的assert断言

Assert断言 断言是程序中处理异常的一种高级形式。可以在任何时候启用和禁用断言验证&#xff0c;因此可以在测试时启用断言&#xff0c;而在部署时禁用断言。同样&#xff0c;程序投入运行后&#xff0c;最终用户在遇到问题时可以重新启用断言。 用法&#xff1a; #…

23.面试题02.07链表相交

public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {ListNode apheadA;ListNode bpheadB;int lenA0,lenB0;//求两个链表长度while(ap!null){apap.next;lenA;}while(bp!null){bpbp.next;lenB;}apheadA;bpheadB;int len0;//用来计算让…

Msf之Python分离免杀

Msf之Python分离免杀 ——XyLin. 成果展示&#xff1a; VT查杀率:8/73 (virustotal.com) 火绒和360可以过掉&#xff0c;但Windows Defender点开就寄掉了 提示&#xff1a;我用360测的时候&#xff0c;免杀过了&#xff0c;但360同时也申报了&#xff0c;估计要不了多久就寄…

CentOS5.2中安装并设置TFTP服务

在CentOS5.2中安装并设置TFTP服务,下面安装TFTP服务必须能联网,因为是使用yum安装,如果使用rpm从光盘安装则不需要。下面是步骤: 安装TFTP服务器: yum install tftp-server 安装TFTP客户端: yum install tftp 执行上面的命令后会自动搜索相应的最新版软件并自动下…

【C++ Primer Plus习题】6.9

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: #include <iostream> #include <string> #include <…

2-99 基于matlab多尺度形态学提取眼前节组织

基于matlab多尺度形态学提取眼前节组织&#xff0c;通过应用不同尺度的结构元素进行边缘检测&#xff0c;再通过加权融合的思想来整合检测到的边缘&#xff0c;降低图像噪声的影响&#xff0c;提高边缘检测的精度。程序已调通&#xff0c;可直接运行。 下载源程序请点链接&…

SalescustomerController

目录 1、 SalescustomerController 1.1、 /// 查询 1.1.1、 CustomerCode tbSales.CustomerCode,//客户编号 1.1.2、 //客户名称 1.2、 /// 修改 using QXQPS.Models; using QXQPS.Vo; using System; using System.Collections.Generic; using System.Linq; us…

OpenAI o1解决了「Quiet-STaR」的挑战吗?

随着OpenAI o1近期的发布&#xff0c;业界讨论o1关联论文最多之一可能是早前这篇斯坦福大学和Notbad AI Inc的研究人员开发的Quiet-STaR&#xff0c;即让AI学会先安静的“思考”再“说话” &#xff0c;回想自己一年前对于这一领域的思考和探索&#xff0c;当初也将这篇论文进行…

Electron 图标修改

目录 1. 图片基本要求 2. 在main.js中配置icon 位置 ​3. 在package.json 中配置icon 位置 4. 问题&#xff1a;左上角图片 开发环境下显示&#xff0c;生产环境下不显示 1. 图片基本要求 图片格式为ico&#xff0c;图片像素像素为256*256&#xff1b; 将ico文件放在pub…

dbt seed 命令及应用示例

DBT-core是一个命令行工具&#xff0c;它使数据分析师和工程师能够更有效地转换仓库中的数据。dbt的一个强大特性是seed命令&#xff0c;它可以将CSV文件(称为“seed”)加载到数据仓库中。本教程将带你完成使用dbt seed命令的过程。 在dbt中&#xff0c;seed是可以加载到数据仓…