JVM垃圾回收算法

该博客聚焦JVM垃圾回收。垃圾收集器主要关注Java堆和方法区,判断对象存活有引用计数和可达性分析算法。Java堆对象分新生代和老年代,分别采用复制、标记—清理或标记—整理算法回收。还介绍了如 -Xms、-Xmx等内存设置参数。

前言

程序计数器,虚拟机栈,本地方法3个区域随线程而生,随线程而灭,栈中的栈帧随着方法的进入和退出有条不紊地执行着出栈和入栈操作,每一个栈帧中分配多少内存,基本上是在类结构确定下来就已知。因此这几个区域的内存分配和回收都具备确定性。在这几个区域就不需要考虑太多回收问题。垃圾收集器主要关注于Java堆和方法区。

一、如何判断对象是否存活?

首先说为什么要判断是否存活,当垃圾收集器在对堆进行回收前,第一就是要确定对象哪些是还在被引用的或者后面还需要被引用的,即存活,哪些是已经“死去”(即不可能再被任何途径使用)

1、引用计数算法

在对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1,引用失效时就减1.任何时刻计数器为0的对象就是不可能再被使用的。这个方法效率挺高,大部分情况下也是很不错的算法。

但是在JVM中会很难解决对象之间相互循环引用的问题,就如果两个对象之间相互调用,这时候就会发生类似死锁的情况,即这个地方相互调用会使得引用计数法始终认为有对象在引用当前对象,就一直计数值大于或等于1,也就无法通知GC收集器回收它们。但是实际的情况是这两个对象后面已经不再调用,所以这个方法虽然简单高效,但不是我们的首选。虚拟机也不是通过这个算法来判断对象是否存活的

2、可达性分析算法

使用一系列的GC Roots的对象(包括:虚拟机栈中引用的对象,方法区中类静态属性引用的对象,方法区中常量引用的对象,本地方法栈中JNI引用的对象)作为起点,从节点开始向下搜索,当没有被GCRoots链接到的对象就可以回收,如下图的对象4和5就判断为可回收对象。

在JDK1.2之后,Java对引用这个概念进行了扩充,也就是对象不仅仅只有引用和没有引用两个概念,而是扩展到了4个:

强引用:类似于“Object obj=new Object()”只要强引用在,垃圾收集器永远不会回收掉被引用的对象。

软引用:是用来描述一些还有用但是并非必需的对象,对于软引用对象,在内存溢出异常之前,会把这些对象列进回收范围之中进行第二次回收。

弱引用,比软引用更弱一点,被弱引用关联的对象只能生存到下一次垃圾收集发生之前。当垃圾收集发生时无论内存是否足够,都会只回收弱引用的对象。

虚引用,最弱的引用关系,对象是否有虚引用对其生存时间是没有影响的。唯一目的就是能在这个对象被收集器回收时收到一个系统通知

对象要想真正宣告“死亡”需要至少两次的标记过程,当对象在可达性分析时候发现没有被GC Roots链到那么对象就会进行第一次标记并且进行第一次筛选,筛选的条件就是判断该对象有没有必要执行finalize()方法,需要执行的话就会把对象放入F-Queue的对列中去执行该对象中的finalize()方法。如果finalize()方法让对象重新被GC Roots链到那么对象就重新活下来,否则就会进行第二次标记,等待垃圾回收的到来

二、垃圾收集算法

目前来说Java堆中的对象是分为新生代和老年代,对于新生代中的对象采用的是复制算法清理

1、复制算法

它将可用内存空间划分为一块较大的Eden空间和两块较小的From Survivor(S0)和To Survivor(S1)空间。每次使用时只使用Eden和其中一块S区。比如这次使用的是S0区。回收时将Eden和S0区中的中还存活的对象一次性复制到S1中最后再清理Eden和S0中的对象,HotSpot虚拟机默认Eden:S0:S1之间大小比例是8:1:1,这是因为新生代中对象大多数甚至98%的都是“朝生夕死”。如果S区的大小不够那么就会依赖老年代的内存进行分配担保。

2、标记—清理与标记—整理算法

在老年代中因为对象存活率高,没有额外的空间对它进行分配担保,所以会采用标记—清理或标记—整理算法来进行回收对象

标记—清理算法:首先标记出所有需要回收的对象,在标记完成之后统一回收所有标记的对象

标记—整理算法:先标记所有可回收对象,让存活的对象向一端移动,然后直接清理掉端边界以外的内存

上面的标记过程都是根据可达性分析算法中对象标记判定来实现的。

三、内存设置参数

上面介绍了这么多,那我们到底怎么操作里面的一些参数呢?

-Xms:初始堆大小,JVM 启动的时候,给定堆空间大小。

-Xmx:最大堆大小,JVM 运行过程中,如果初始堆空间不足的时候,最大可以扩展到多 少。

-Xmn:设置年轻代大小。整个堆大小=年轻代大小+年老代大小+持久代大小。持久代一 般固定大小为 64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大, Sun 官方推荐配置为整个堆的 3/8。

-Xss:设置每个线程的 Java 栈大小。JDK5.0 以后每个线程 Java 栈大小为 1M,以前每 个线程堆栈大小为 256K。根据应用的线程所需内存大小进行调整。在相同物理内存下,减 小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成。

-XX:NewSize=n:设置年轻代大小

-XX:NewRatio=n:设置年轻代和年老代的比值。如:为 3,表示年轻代与年老代比值为 1: 3,年轻代占整个年轻代+年老代和的 1/4

-XX:SurvivorRatio=n:年轻代中 Eden 区与两个 Survivor 区的比值。注意 Survivor 区有两个。 如:3,表示 Eden:Survivor=3:2,一个 Survivor 区占整个年轻代的 1/5

-XX:MaxPermSize=n:设置持久代大小

-XX:MaxTenuringThreshold:设置垃圾最大年龄。如果设置为 0 的话,则年轻代对象不经 过 Survivor 区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在 Survivor 区进行多次复制,这样可以增加对象再年轻代 的存活时间,增加在年轻代即被回收的概率。

原文链接 JVM垃圾回收算法

内容概要:本文介绍了一个基于多传感器融合的定位系统设计方案,采用GPS、里程计和电子罗盘作为定位传感器,利用扩展卡尔曼滤波(EKF)算法对多源传感器数据进行融合处理,最终输出目标的滤波后位置信息,并提供了完整的Matlab代码实现。该方法有效提升了定位精度与稳定性,尤其适用于存在单一传感器误差或信号丢失的复杂环境,如自动驾驶、移动采用GPS、里程计和电子罗盘作为定位传感器,EKF作为多传感器的融合算法,最终输出目标的滤波位置(Matlab代码实现)机器人导航等领域。文中详细阐述了各传感器的数据建模方式、状态转移与观测方程构建,以及EKF算法的具体实现步骤,具有较强的工程实践价值。; 适合人群:具备一定Matlab编程基础,熟悉传感器原理和滤波算法的高校研究生、科研人员及从事自动驾驶、机器人导航等相关领域的工程技术人员。; 使用场景及目标:①学习和掌握多传感器融合的基本理论与实现方法;②应用于移动机器人、无人车、无人机等系统的高精度定位与导航开发;③作为EKF算法在实际工程中应用的教学案例或项目参考; 阅读建议:建议读者结合Matlab代码逐行理解算法实现过程,重点关注状态预测与观测更新模块的设计逻辑,可尝试引入真实传感器数据或仿真噪声环境以验证算法鲁棒性,并进一步拓展至UKF、PF等更高级滤波算法的研究与对比。
内容概要:文章围绕智能汽车新一代传感器的发展趋势,重点阐述了BEV(鸟瞰图视角)端到端感知融合架构如何成为智能驾驶感知系统的新范式。传统后融合与前融合方案因信息丢失或算力需求过高难以满足高阶智驾需求,而基于Transformer的BEV融合方案通过统一坐标系下的多源传感器特征融合,在保证感知精度的同时兼顾算力可行性,显著提升复杂场景下的鲁棒性与系统可靠性。此外,文章指出BEV模型落地面临大算力依赖与高数据成本的挑战,提出“数据采集-模型训练-算法迭代-数据反哺”的高效数据闭环体系,通过自动化标注与长尾数据反馈实现算法持续进化,降低对人工标注的依赖,提升数据利用效率。典型企业案例进一步验证了该路径的技术可行性与经济价值。; 适合人群:从事汽车电子、智能驾驶感知算法研发的工程师,以及关注自动驾驶技术趋势的产品经理和技术管理者;具备一定自动驾驶基础知识,希望深入了解BEV架构与数据闭环机制的专业人士。; 使用场景及目标:①理解BEV+Transformer为何成为当前感知融合的主流技术路线;②掌握数据闭环在BEV模型迭代中的关键作用及其工程实现逻辑;③为智能驾驶系统架构设计、传感器选型与算法优化提供决策参考; 阅读建议:本文侧重技术趋势分析与系统级思考,建议结合实际项目背景阅读,重点关注BEV融合逻辑与数据闭环构建方法,并可延伸研究相关企业在舱泊一体等场景的应用实践。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值