JVM垃圾回收机制

devtools/2024/10/18 5:39:17/

    为了解JVM的垃圾回收机制,我们要先了解为什么要进行垃圾回收,带我们编写代码的时候,会创建很多的对象,如果这些对象不及时的清除,那么可能会导致,后续我们在创建对象的时候已经没有空间留给我们进行操作,会导致对象创建失败,导致内存泄漏,如果我们不及时清除不需要的对象短时间内内存泄漏问题可能不会对程序产生什么影响甚至不会被发现,但是时间一长,内存空间泄露发生了,可能机会产生重大问题。

    在JVM中有许多内存区域,垃圾回收机制主要在堆中进行垃圾回收,java中垃圾回收的基本单位是对象,而堆中又是储存new 出来的对象,因此堆事垃圾回收机制的主要战场,并且在堆中我们只回收已经完全不被使用的对象,如果对象但凡有一丁点被使用的部分我们就不对其进行回收。

    垃圾挥回收分为两步 1)找到垃圾位置 2)进行垃圾回收。

    1垃圾的位置

    找到垃圾的位置有两种方案 引用计数和可达性分析

    引用计数:

    引用技术简单的来讲就是使用一个计数器,记录一个对象被引用的次数,如果被引用了数值就加一,如果有对一个对象的引用删除了,那么计数器就减一,如果计数器的数值为零了那么就说明这个对象么有被引用,也就说明这个对象没用了,就可以被当成垃圾进行处理了。

   这种方法看似比较好其实也有明显缺陷 1)耗费额外的内存空间 2)计数中容易造成“循环”引用这样的问题。

    消耗额外的空间这一点不难理解,计数器也是需要内存空间来计数否则如何知到该对象被引用了多少次。

    循环引用,这就比较的抽象了,下面我们观看一组代码来解释这个问题:

class Test{Test test = null;
}
public class csdn {public static void main(String[] args) {//第一步引用Test a = new Test();Test b = new Test();//对象内部的引用a.test = b;b.test = a;//将对象的指向为nulla = null;b = null;}
}

 

    在这个代码过程a的计数器在第一步加一,b的计数器也在第一步加一 在第二部中有余对象a和b都被彼此对象中的test再次引用,因此各自的技术器再加一,此时计数器中的数字都等于2,之后将a和b通知置为空,此时两个对象的引用分别减一,但此时两个计数器中的数都为1,这种情况就比较尴尬了,此时这两个对象不会被回收,因为计数其中的数并没有清零,这就造成了循环引用,导致计数器中的数没办法被清零。

    由于这种原因因此JVM中并没有使用这种方式来进行查找发记得位置而是使用了另一种方式。

     可达性分析:这种方式是用时间换空间,对时间的消耗比较多,但是对空间的要求比较小。

    这种方式查找垃圾所在位置类似于“图的遍历”,从root触发尽可能多的遍历到对象,如果该对象可以通过root到达摸个对象,则说明这个对象还在被引用就不必回收,如果没有遍历到那就说明这个对象已经不再被使用可以被回收了。

    这里的root 称为 GC root 可以理解为可达性分析的起点有三个部分可以作为GC root 

  1)栈上的局部变量(引用类型)。

  2)元数据区(方法区)上的静态成员变量(医用类型)。

  3)常量池引用指向的对象。

    其中 GC root可以有多个在查找垃圾的过程中会逐个的对GC root 进行遍历知到将所有的GC

 root 遍历(尽可能往下延伸)结束之后才可以确定那些是需要被回收的。

   进行垃圾回收也有几种方式:

    1)标记清除:直接针对内存中的对象进行释放。

    标记清除这种方式会引起‘内存碎片’问题:我们在释放内存的时候是随机的,虽然我们把不用的对象内存释放了,但是释放掉的空间并没有可空闲空间合并在一起,这就导致后续申请空间的时候可能会申请不到,因为我们申请的空间是必须连续的。

  2)复制算法:把一块内存分为两部分,同一时刻只使用其中的一部分,当使用的一部分进行可达性分析之后发现有不需要的对象,需要被释放掉,此时我们就把,不需要别释放的对象拷贝到另一半并且尽量保持连续,之后将原本的那一半进行释放,并且不断地循环这个过程。

    这个方法也有明显的缺点 1)空间利用率低 2)如果存活下来的对象比较多,那么进行复制拷贝的成本就比较大。

    3)标记整理:就类似于顺序表的删除,将部分元素向前移动,但是这样的方式如果数据量比较大的情况下,开销也是不小的。

    上述的三种方式都不是JVM垃圾回收的方式但是我们根据上述方式取长补短创建了一种新的方式分代回收:分代回收将内存分为两大类  一类是新生代 另一类是老年代  其中新生代中有分为两类一类是伊甸去另一类是幸存区,其中幸存区有两块,但是这两块都是非常小的。

    当我们创建新的类是这个类会出现在新生代中也就是新的类,这块内存是比较大的,根据我们的经验可知,大部分的类都活不过GC,因此保留下来的部分比较少,并且经过GC后会将这些幸存下来的列复制到幸存区中,前面提到幸存区有两部分,在这两部分中也会进行GC这两部分会进行上面讲述的复制算法这两部分会循环的进行这一操作,直到可达性分析达到一定次数之后,会认为这些剩余的类是会长期幸存的,之后会将这些类拷贝到老年区,在老年区中也会进行GC但是GC的频率会减低,因为在老年区中的类默认是会长期幸存的,这样还可以节省一些资源。

    上述的这些只是JVM垃圾回收机制的基本思想,真正实现这个过程是通过,“垃圾回收器”来实现的,JVM提供了许多的垃圾回收器。

     图中的几种“垃圾回收器”我们只需要知到两种即可 CMS 和 G1这两种是目前比较主流的垃圾回收器,其他的垃圾回收器已经渐渐地被历史淘汰了。

      

    


http://www.ppmy.cn/devtools/119816.html

相关文章

使用rsync+jenkins实现服务自动部署全流程

项目背景:城市政务云服务器没有上k8s,所有后端服务都是原始方式部署启动 (java -jar xxx.jar),那么有没有方式简化部署难度,实现自动部署?当然是有的,下面详细介绍(以Cen…

探索私有化聊天软件:即时通讯与音视频技术的结合

在数字化转型的浪潮中,企业对于高效、安全、定制化的通讯解决方案的需求日益迫切。鲸信,作为音视频通信技术的佼佼者,凭借其强大的即时通讯与音视频SDK(软件开发工具包)结合能力,为企业量身打造了私有化聊天…

超详细超实用!!!AI编程之cursor编写设计模式迪米特法则实例(八)

云风网 云风笔记 云风知识库 一、设计模式迪米特法则定义 只与你的直接朋友交谈,不跟“陌生人”说话 其含义是:如果两个软件实体无须直接通信,那么就不应当发生直接的相互调用,可以通过第三方转发该调用。其目的是降低类之间的耦…

高防IP能够运用在哪些场景当中?

随着互联网技术的快速发展,网络安全成为企业经常需要面对的问题,在日常生活中分布式拒绝服务攻击与CC攻击是常见的网络攻击类型,同时DDOS攻击对于企业和服务提供商造成了严重的损失,而高防IP作为一种有效的安全防护手段&#xff0…

flume系列之:flume jmx页面导出flume、java进程等全部指标

flume系列之:flume jmx页面导出flume、java进程等全部指标 一、需求背景二、完整的jmx指标信息三、修改jmx指标导出规则四、启动jmx导出程序一、需求背景 目前jmx页面指标只导出了flume相关的指标,现在需要导出java相关的指标二、完整的jmx指标信息 主要有flume指标java进程指…

GO Serial 学习与使用

文章目录 主要特性安装基本用法配置选项错误处理其他功能 github.com/goburrow/serial 是一个 Go 包,提供了一种简单的方式来与串口进行交互。以下是该包的主要特性和用法的简要概述: 主要特性 跨平台支持:支持 Windows、macOS 和 Linux。简…

基于php的在线租房管理系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏:Java精选实战项目…

《黑神话:悟空》在全球爆火的原因是什么?

以下将《黑神话:悟空》简称为《悟空》。 遥想当年,PC国产单机游戏蒸蒸日上之时,盗版光碟的猖獗,逼得正版游戏厂商要么倒闭,要么为了存活,转型开发网络游戏,要么索性转成其它行业,国产…