Java回收垃圾的基本过程与常用算法

article/2025/9/19 14:05:23

目录

一、基本概述

二、垃圾分类

基本背景

举例说明各种引用类型的作用

强引用(Strong Reference)

软引用(Soft Reference)

弱引用(Weak Reference)

虚引用(Phantom Reference)

三、垃圾查找

查找垃圾时机

查找垃圾操作

四、垃圾清理

常用算法介绍

标记-清除(Mark-Sweep)

标记-复制(Mark-Copy)

标记-整理(Mark-Compact)

分代收集算法

问题背景

分代区域描述

分代垃圾回收算法执行过程

参考文献、书籍及链接


一、基本概述

当 Java 程序运行时,对象会被动态地分配在堆内存中。随着程序的运行,有些对象可能不再被引用,成为垃圾。垃圾回收是指在程序运行时,对这些垃圾对象进行清理,以便腾出内存空间供新的对象使用。

Java 垃圾回收的基本过程可以分为以下三个步骤:

  1. 垃圾分类(Garbage Classification):垃圾回收器首先需要确定哪些对象是垃圾对象,哪些对象是存活对象。一般情况下,垃圾回收器会从堆的根节点(如程序计数器、虚拟机栈、本地方法栈和方法区中的类静态属性等)开始遍历对象图,标记所有可以到达的对象为存活对象,未被标记的对象则被认为是垃圾对象。
  2. 垃圾查找(Garbage Tracing):垃圾回收器需要查找出所有垃圾对象,以便进行清理。垃圾查找的方式不同,会导致不同的垃圾回收算法。常见的垃圾查找算法有标记-清除算法、复制算法、标记-整理算法、分代算法等。
  3. 垃圾清理(Garbage Collection):垃圾回收器需要将所有的垃圾对象进行清理。垃圾清理的方式也不同,常见的有标记-清除算法、复制算法、标记-整理算法、分代算法等。垃圾清理可能会引起应用程序的暂停,不同的垃圾回收器通过不同的方式来减少这种暂停时间,从而提高应用程序的性能和可靠性。

需要注意的是,不同的垃圾回收器在执行垃圾回收时,可能会采用不同的算法和策略,因此对于不同的应用场景,需要选择合适的垃圾回收器,并对其进行适当的参数调优,以达到最优的垃圾回收效果。

二、垃圾分类

基本背景

垃圾分类指的是将堆中的对象分为存活对象和垃圾对象两类的过程,与强引用、软引用、弱引用、虚引用等引用类型没有直接关系。

在垃圾分类阶段,JVM会从一组根对象开始,通过对象之间的引用关系,遍历所有的对象,并将所有存活的对象进行标记。在标记过程中,对象会被打上标记,以便在垃圾回收的后续阶段进行处理。被标记的对象就是存活对象,未被标记的对象则被视为垃圾对象,可以被垃圾回收器回收。

强引用、软引用、弱引用、虚引用等引用类型是用于控制垃圾回收的过程中对对象的生命周期的。它们的作用是告诉垃圾回收器哪些对象是可以被回收的,哪些对象是不可以被回收的。

举例说明各种引用类型的作用

强引用(Strong Reference)

强引用是最常见的引用类型,也是默认的引用类型。如果一个对象具有强引用,垃圾收集器就不会回收它。当内存空间不足时,JVM 宁愿抛出 OutOfMemoryError 错误也不会回收具有强引用的对象。强引用的示例代码:

Object obj = new Object(); //强引用

软引用(Soft Reference)

软引用是用来描述一些还有用但并非必须的对象。对于软引用关联着的对象,只有在内存不足时才会被回收。软引用可以用来实现内存敏感的高速缓存,比如网页缓存、图片缓存等。软引用的示例代码:

Object obj = new Object();SoftReference<Object> softRef = new SoftReference<>(obj); //软引用obj = null; //obj 不再具有强引用,但仍有软引用

弱引用(Weak Reference)

弱引用是用来描述非必须对象的,被弱引用关联的对象只能生存到下一次垃圾收集发生为止。在垃圾收集器工作时,无论当前内存是否充足,都会回收只被弱引用关联的对象。弱引用的示例代码:

Object obj = new Object();WeakReference<Object> weakRef = new WeakReference<>(obj); //弱引用obj = null; //obj 不再具有强引用,只有弱引用

虚引用(Phantom Reference)

虚引用也称为幽灵引用或者幻影引用,是最弱的一种引用类型。一个持有虚引用的对象,和没有任何引用一样,随时可能被垃圾回收器回收。虚引用主要用于跟踪对象被垃圾回收的状态,当一个对象即将被回收时,虚引用会被放入一个 ReferenceQueue 中,可以通过 ReferenceQueue 获取到通知。虚引用的示例代码:

Object obj = new Object();ReferenceQueue<Object> queue = new ReferenceQueue<>();PhantomReference<Object> phantomRef = new PhantomReference<>(obj, queue); //虚引用obj = null; //obj 不再具有强引用,只有虚引用

总之,通过不同的引用类型,我们可以更加灵活地控制对象的生命周期,避免过早或过晚地被垃圾回收器回收。 

三、垃圾查找

查找垃圾时机

不同的垃圾回收器,策略有所不同,以下只是列举:

  • 申请新对象空间、加载Class时申请空间不足
  • 老年代、永久代空间使用率到达了配置值(cms:CMSInitiatingOccupancyFraction=60,CMSInitiatingPermOccupancyFraction=60)
  • 调用System.gc()

查找垃圾操作

查找垃圾的方法可以分为两种:引用计数法和可达性分析法。

引用计数法:它是一种简单的垃圾收集算法,它的基本思想是给对象添加一个引用计数器,每当有一个地方引用它时,计数器就加1;当引用失效时,计数器就减1。当计数器为0时,就可以认为这个对象已经不再被引用,可以将其回收。然而,引用计数法无法解决循环引用的问题,即对象之间形成了环状结构,导致它们的计数器都不为0,即使它们已经不再被程序使用。

可达性分析法:它是现代垃圾收集算法的主要实现方式。它的基本思想是从一组被称为"根对象"(如:全局变量、栈、方法区)开始,通过一系列引用关系,能够到达的对象被认为是"存活"的,无法到达的对象则被认为是垃圾,需要被回收。在可达性分析中,对象之间形成的循环引用也会被正确处理,因为它们与根对象之间没有引用链相连。

四、垃圾清理

常用算法介绍

标记-清除(Mark-Sweep)

GC分为两个阶段,标记和清除

首先标记所有可回收的对象,在标记完成后统一回收所有被标记的对象。

缺点是清除后会产生不连续的内存碎片。碎片过多会导致以后程序运行时需要分配较大对象时,无法找到足够的连续内存,而不得已再次触发GC。

标记-复制(Mark-Copy)

将内存按容量划分为两块,每次只使用其中一块。当这一块内存用完了,就将存活的对象复制到另一块上,然后再把已使用的内存空间一次清理掉。这样使得每次都是对半个内存区回收,也不用考虑内存碎片问题,简单高效。

缺点需要两倍的内存空间。一种优化方式是使用eden和survivior区,具体步骤如下:

eden和survivior区默认内存空间占比为8:1:1,同一时间只使用eden区和其中一个survivior区。标记完成后,将存活对象复制到另一个未使用的survivior区(部分年龄过大的对象将升级到年老代)。

 这样,相比普通的两块空间的标记复制算法来说,只有10%的内存空间浪费,而这样做的原因是:大部分情况下,一次young gc后剩余的存活对象非常少

标记-整理(Mark-Compact)

标记-整理也分为两个阶段,首先标记可回收的对象,再将存活的对象都向一端移动,然后清理掉边界以外的内存。

 此方法避免标记-清除算法的碎片问题,同时也避免了复制算法的空间问题。

一般年轻代中执行GC后,会有少量的对象存活,就会选用复制算法,只要付出少量的存活对象复制成本就可以完成收集。

而年老代中因为对象存活率高,用标记复制算法时数据复制效率较低,且空间浪费较大。所以需要使用标记-清除或者标记-整理算法来进行回收。

所以通常可以先使用标记清除算法,当碎片率高时,再使用标记整理算法。

分代收集算法

问题背景

从上面对基础垃圾收集算法,都不是银弹,有各自不同的特点,不能应对所有的场景。在现代JVM中,通过大量实际场景的分析,可以发现,JVM内存中的对象,大致可以分为两大类:一类对象,他们的生命周期很短暂,比如局部变量、临时对象等。另一类对象则会存活很久,比如用户应用程序中DB长连接中的Connection对象。

上图中,纵轴为JVM内存使用情况,横轴为时间。图中可以发现,大多数对象的生命周期极短,很少有对象可以在GC后存活下来。基于此,诞生了分代思想。在JDK7中,Hotspot虚拟机主要将内存分为三大块,新生代(Young Genaration)、老年代(Old Generation)、永久代(Permanent Generation)

分代区域描述

主要基本区域归类分析如下:

新生代:新生代主要分为两个部分:Eden区和Survivor区,其中Survivor区又可以分为两个部分,S0和S1。该区域中,相对于老年代空间较小,对象的生存周期短,GC频繁。因此在该区域通常使用标记复制算法。

老年代:老年代整体空间较大,对象的生命周期长,存活率高,回收不频繁。因此更适合标记整理算法。

永久代:永久代又称为方法区,存储着类和接口的元信息以及interned的字符串信息。在JDK8中被元空间取代。

元空间:JDK8以后引入,方法区也存在于元空间。

分代垃圾回收算法执行过程

  • 初始态:对象分配在Eden区,S0、S1区几乎为空。

  • 随着程序的运行,越来越多的对象被分配在Eden区。

  • 当Eden放不下时,就会发生MinorGC(即YoungGC),此时,会先标识出不可达的垃圾对象,然后将可达的对象移动到S0区,并将不可达的对象清理掉。这时候,Eden区就是空的了。在这个过程中,使用了标记清理算法及标记复制算法。

  • 随着Eden放不下时,会再次触发minorGC,和上一步一样,先标记。这个时候,Eden和S0区可能都有垃圾对象了,而S1区是空的。这个时候,会直接将Eden和S0区的对象直接搬到S1区,然后将Eden与S0区的垃圾对象清理掉。经历这一轮的MinorGC后,Eden与S0区为空。

  • 随着程序的运行,Eden空间会被分配殆尽,这时会重复刚才MinorGC的过程,不过此时,S0区是空的,S0和S1区域会互换,此时存活的对象会从Eden和S1区,向S0区移动。然后Eden和S1区中的垃圾会被清除,这一轮完成之后,这两个区域为空。

  • 在程序运行过程中,虽然大多数对象都会很快消亡,但仍然存在一些存活时间较长的对象,对于这些对象,在S0和S1区中反复移动,会造成一定的性能开销,降低GC的效率。因此引入了对象晋升的行为。

  • 当对象在新生代的Eden、S0、S1区域之间,每次从一个区域移动到另一个区域时,年龄都会加一,在达到一定的阈值后,如果该对象仍然存活,该对象将会晋升到老年代。

  • 如果老年代也被分配完毕后,就会出现MajorGC(即Full GC),由于老年代通常对象比较多,因此标记-整理算法的耗时较长,因此会出现STW现象,因此大多数应用都会尽量减少或着避免出现Full GC的原因。

参考文献、书籍及链接

1.JVM经典垃圾回收器的运行机制和原理-康志兴的博客 | kangzhixing Blog

2.《深入理解Java虚拟机》

3.《垃圾回收的算法与实现》

 


http://chatgpt.dhexx.cn/article/ioEpX3wX.shtml

相关文章

java面试-GC垃圾回收机制

原理&#xff1a; GC是垃圾收集的意思&#xff08;Garbage Collection&#xff09;,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的。 简而言之&#xff0c;GC是将java的无用的堆对象进行清理&#xff0c;释放内存&#xff0c;以免发生内存泄露。…

JVM垃圾回收算法、GC和分代回收、三色标记并发漏标、垃圾回收器

一.标记清除 标记速度与存活对象线性关系 清除速度与内存大小线性关系 标记清除法分为标记阶段和清除阶段&#xff0c;标记阶段首先找到一些GC Root对象&#xff08;根对象&#xff09;&#xff0c;根对象是那些一定不能被回收的对象。清除阶段比较简单&#xff0c;加标记的对…

垃圾回收的主要区域是堆,那方法区会回收吗?

有些人认为方法区&#xff08;如HotSpot虚拟机中的元空间或者永久代&#xff09;是没有垃圾收集行为的&#xff0c;《Java虚拟机规范》中提到过可以不要求虚拟机在方法区中实现垃圾收集&#xff0c;事实上也确实有未实现或未能完整实现方法区类型卸载的收集器存在&#xff08;如…

GC(垃圾回收)详解

JVM 1.年轻代&#xff1a;年轻代主要存放新创建的对象&#xff0c;垃圾回收会比较频繁。(稍微讲细一点就是即可&#xff0c;年轻代分成Eden Space和Suvivor Space。当对象在堆创建时&#xff0c;将进入年轻代的Eden Space。垃圾回收器进行垃圾回收时&#xff0c;扫描Eden Spac…

java---垃圾回收算法(GC)

目录 一、如何判断一个对象是否存活 1.引用计数法 2.可达性分析法 二、垃圾回收算法 1.标记清除法 2.复制算法 3.标记整理法 4.分代算法 具体流程 注意事项 空间分配担保原则 总结 一、如何判断一个对象是否存活 Java 堆中存放着几乎所有的对象实例&#xff0c;垃圾…

Java - GC 垃圾回收

JVM中一个垃圾回收线程&#xff0c;它的优先级较低&#xff0c;正常情况下不会执行。JVM空闲或者当前内存不足时,才会触发垃圾回收线程执行,扫描内没有被引用的对象,将这些对象添加到要回收的集合中进行回收。 GC介绍 Garbage Collection 垃圾收集&#xff0c;监测对象是否可…

GC是如何判断一个对象为垃圾的?被GC判断为垃圾的对象一定会被回收吗?

一.GC如何判断一个对象为”垃圾”的 java堆内存中存放着几乎所有的对象实例&#xff0c;垃圾收集器在对堆进行回收前,第一件事情就是要确定这些对象之中哪些还“存活”着,哪些已经“死去”。那么GC具体通过什么手段来判断一个对象已经”死去”的&#xff1f; 1.引用计数算法(…

基于28181协议的视频与平台的对接

问题描述 将IPC摄像头接入平台进行观看&#xff0c;或使用28181/rtsp/rtmp/flv等协议将视频流分发到其他平台。 解决方案 WVP-PRO&#xff08;基于GB/T 28181-2016标准实现的流媒体平台&#xff09;&#xff0c;依托优秀的开源流媒体服务ZLMediaKit&#xff0c;提供完善丰富…

GB28181协议实现系列之----SDK Demo发布(7)

GB28181在终端的应用越来越广&#xff0c;但是一般很多做终端的厂家要加入到互联互通的GB28181网络协议栈中都必须招聘一些专业做GB28181的开发人员&#xff0c;并且需要对接各厂家的兼容性开发及对接调试工作&#xff0c;或是修改一些定制功能。安防市场一年有千亿以上的产值&…

GB28181协议之设备录像查询

目录 一、概述 二、GB28181录像文件查询 2.1 录像文件基本要求 2.2 命令流程 2.3 抓包文件抓图示例 三、国标平台介绍 一、概述 近年来&#xff0c;国内视频监控应用发展迅猛&#xff0c;系统接入规模不断扩大&#xff0c;涌现了大量平台提供商&#xff0c;平台提供商的接…

ZLMediaKit+wvp-GB28181-pro,搭建28181协议视频平台

ZLMediaKitwvp-GB28181-pro&#xff0c;搭建28181协议视频平台 一&#xff0c;简介 ZLMediaKit:实现RTSP/RTMP/HLS/HTTP协议的轻量级流媒体框架&#xff0c;支持大并发连接请求 一个基于C11的高性能运营级流媒体服务框架,项目地址&#xff1a;ZLMediaKit 特点&#xff1a; 基…

java gb28181网关_视频网关GB28181协议转换解决方案

原标题&#xff1a;视频网关GB28181协议转换解决方案 应用需求及问题&#xff1a; 四川某一所学校&#xff0c;校园内装置有上百个摄像头&#xff0c;学校监控系统是RTSP协议&#xff0c;现在需求要把校园的监控系统视频画面接入到公安系统里&#xff0c; 可公安系统只支持GB-T…

GB28181协议--校时

1、简介 根据《GB/T 28181 —2016》7.10、9.10的要求&#xff0c;GB28181设备网络校时功能描述如下&#xff1a; 联网系统内的IP 网络服务器设备宜支持 NTP(见IETF RFC2030) 协议的网络统一校时服务。 网络校时设备分为时钟源和客户端, 支持客户/服务器的工作模式; 时钟源应支…

GB28181协议常见几种信令流程(一)

在监控系统中&#xff0c;常见的摄像机设备互联协议有国际标准的ONVIF、国标的GB28181和各厂商的私有连接协议&#xff0c;本章从GB28181-2016中摘抄整理常见信令流程&#xff0c;如28181的会话/媒体通道、SIP基本注册/注销流程、客户端主动发起视频点播流程、设备控制流程等。…

国标GB28181协议客户端开发(一)整体流程和技术选型

国标GB28181协议客户端开发&#xff08;一&#xff09;整体流程和技术选型 本系列文章将介绍国标GB28181协议设备端的开发过程。本文旨在探讨整体设计和技术选型方面的考虑&#xff0c;为开发人员提供指导和参考。文章将从设备端开发的整体架构、信令交互流程以及关键技术选型等…

java gb28181网关_国标GB28181协议对接网关

国标GB28181网关概述 国标GB28181《安全防范视频监控联网系统信息传输、交换、控制技术要求》最新版为2016年版&#xff0c;较2011年版更加完善&#xff0c;其是基于SIP协议的视频联网框架标准。因其核心应用于公安视频联网&#xff0c;在平安城市、雪亮工程超大规模视频监控联…

GB28181协议之录像回放

目录 一、概述 二、录像文件播放 2.1 基本要求 2.2 命令流程 2.3 抓包示例 2.3.1 Invite请求[SIP服务器---->设备] 2.3.2 Invite应答[设备---->SIP服务器] 2.3.3 ACK[SIP服务器---->设备] 2.3.4 Bye结束回放 2.3.5 Bye应答 2.3.6 播放速度控制 2.3.6 控制…

GB28181协议之实时视频

目录 一、概述 二、实时视频 2.1基本要求 2.2命令流程 2.3抓包示例 2.3.1 Invite请求[SIP服务器----->设备] 2.3.2 Invite应答[设备---->SIP服务器] 2.3.3 ACK[SIP服务器----->设备] 2.3.4 Bye 2.3.5 Bye应答 三、国标平台介绍 一、概述 近年来&#xff0c;国…

GB28181协议--实时视音频点播(预览)

1、基本要求 根据《GB/T 28181 —2016》第9章关于实时视音频点播的描述&#xff0c;其内容如下&#xff1a; 实时视音频点播的SIP 消息应通过本域或其他域的SIP 服务器进行路由、 转发, 目标设备的实时视音频流宜通过本域内的媒体服务器进行转发。实时视音频点播采用SIP 协议…

GB28181协议--心跳

1、心跳介绍&#xff1a; 根据《GBT 28181-2016 公共安全视频监控联网系统信息传输、交换、控制技术要求》9.6.1状态信息报送章节描述。 当源设备(包括网关、SIP 设备、SIP 客户端或联网系统) 发现工作异常时, 应立即向本 SIP 监控域的SIP服务器发送状态信息; 无异常时, 应定…