【Java虚拟机学习】-GC策略算法

Java8的GC垃圾回收(一) Java垃圾回收概况   Java GC(Garbage Collection,垃圾回收)机制,是Java与C++/C的主要区别之一,作为Java开发者,一般不需要专门编写内存回收和垃圾清理代码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢。这是因为在Java虚拟机中,存在自动内存管理和垃圾清扫机制。概括地说,该机制对JVM中的内存进行标记,并确定哪些内存需要回收,根据一定的回收策略,... 阅读详情


概述

思考GC需要完成的3件事情:

  • 哪些内存需要回收?
  • 什么时候回收?
  • 如何回收?

再回头看看第二章介绍的Java内存运行时区域的各个部分:

  • 程序计时器、虚拟机栈、本地方法栈:随线程而灭,栈帧随方法而进行出栈和入栈,每一个栈帧分配的内存在类结构确定就已知,因此这几个区域不需要考虑回收;
  • 对于Java堆和方法区,只有程序运行期间才知道会创建哪些对象,内存的分配和回收都是动态的,垃圾收集器所关注的是这部分内存;
对象已死吗?

在垃圾收集器进行回收前,第一件事就是确定这些对象哪些还存活,哪些已经死去。

引用计数算法

给对象添加引用计数器,当有地方引用它时就加1,引用失效就减1,为0时就认为对象不再被使用可回收。该算法失效简单,判断高效,但并不被主流虚拟机采用,主要原因是它很难解决对象之间相互循环引用的问题。

可达性分析算法

通过一系列的称为“GC Roots”的对象作为起点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),如果一个对象到GC Roots没有引用链相连,则该对象是不可用的。

可达性分析

在Java语言中,可作为GC Roots的对象包括:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象;
  • 方法区中类静态属性引用的对象;
  • 方法区中常量引用的对象;
  • 本地方法栈中JNI(即一般说的Native方法)引用的对象;
再谈引用

在JDK 1.2之后,Java对引用的概念进行了扩充,将引用分为强引用、软引用、弱引用和虚引用,这4种引用强度依次减弱。

生存还是死亡

要真正宣告一个对象死亡,至少要经历两次标记过程:如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那它将会被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行finalize方法(如没有重写finalize方法或者已经被调用过则认为没有必要执行);如果有必要执行则将该对象放置在F-Queue队列中,并在稍后由一个由虚拟机自己建立的、低优先级的Finalizer线程去执行它;稍后GC将对F-Queue中的对象进行第二次标记,如果对象还是没有被引用,则会被回收。

但是作者不建议通过finalize方法“拯救”对象,因为它运行代价高、不确定性大、无法保证各个对象的调用顺序。

回收方法区

永久代的垃圾收集主要回收两部分内容:废弃常量和无用的类。

一个无用的类需要满足以下三个条件:

  • 该类的所有实例都已经被回收;
  • 加载该类的ClassLoader已经被回收;
  • 该类对象的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法;

在大量使用反射、动态代理、CGLib等ByteCode框架、动态生成JSP以及OSGI这类频繁自定义ClassLoader的场景都需要虚拟机具备类卸载的功能(HotSpot提供-Xnoclassgc参数控制),以保证永久代不会溢出。

垃圾收集算法

  • 标记-清除算法:首先标记出所有需要回收的对象,然后统一回收所有被标记的对象;缺点是效率不高且容易产生大量不连续的内存碎片;
  • 复制算法:将可用内存分为大小相等的两块,每次只使用其中一块;当这一块用完了,就将还活着的对象复制到另一块上,然后把已使用过的内存清理掉。在HotSpot里,考虑到大部分对象存活时间很短将内存分为Eden和两块Survivor,默认比例为8:1:1。代价是存在部分内存空间浪费,适合在新生代使用;
  • 标记-整理算法:首先标记出所有需要回收的对象,然后让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。适用于老年代。
  • 分代收集算法:一般把Java堆分新生代和老年代,在新生代用复制算法,在老年代用标记-清理或标记-整理算法,是现代虚拟机通常采用的算法。

HotSpot的算法实现

枚举根节点
  • 由于要确保在一致性的快照中进行可达性分析,从而导致GC进行时必须要停顿所有Java执行线程;
  • 在HotSpot里通过一组OopMap数据结构来知道哪些地方存放着对象引用;
安全点
  • HotSpot只在特定的位置记录了OopMap,这些位置称为安全点(SafePoint);
  • 即程序执行时并非在所有地方都能停顿下来开始GC,只有到达安全点时才能暂停;
  • 对于安全点基本上是以程序“是否具有让程序长时间执行的特征”(比如方法调用、循环跳转、异常跳转等)为标准进行选定的;
  • 另外还需要考虑如果在GC时让所有线程都跑到最近的安全点上,有两种方案:抢先式中断和主动式中断(主流选择);
安全区域
  • 如果程序没有分配CPU时间(如线程处于Sleep或Blocked),此时就需要安全区域(Safe Region),其是指在一段代码片段之中,引用关系不会发生变化;
  • 线程执行到安全区域时,首先标识自己已经进入了安全区域,这样JVM在GC时就不管这些线程了;

垃圾收集器

  • 垃圾收集算法是内存回收的方法论,垃圾收集器就是内存回收的具体实现。
  • 这里讨论JDK 1.7 Update 14之后的HotSpot虚拟机(此时G1仍处于实验状态),包含的虚拟机如下图所示(存在连线的表示可以搭配使用):

HotSpot垃圾收集器

Serial收集器

Serial收集器

  • 最基本、发展历史最悠久,在JDK 1.3之前是新生代收集的唯一选择;
  • 是一个单线程(并非指一个收集线程,而是会暂停所有工作线程)的收集器,采用的是复制算法;
  • 现在依然是虚拟机运行在Client模式下的默认新生代收集器,主要就是因为它简单而高效(没有线程交互的开销);
ParNew收集器

ParNew收集器

  • 其实就是Serial收集器的多线程版本;
  • ParNew收集器在单CPU环境中绝对不会有比Serial收集器更好的效果;
  • 是许多运行在Server模式下虚拟机首选的新生代收集器,重要原因就是除了Serial收集器外,只有它能与CMS收集器配合工作;
  • 并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍处于等待状态;
  • 并发(Concurrent):指用户线程与垃圾收集线程同时执行,用户线程在继续执行而垃圾收集程序运行在另外一个CPU上;
Parallel Scavenge收集器
  • 新生代收集器,使用复制算法,并行的多线程收集器;
  • 与其他收集器关注于尽可能缩短垃圾收集时用户线程停顿时间不同,它的目标是达到一个可控制的吞吐量;
  • 高吞吐量可以高效率利用CPU时间,适合在后台运算而不需要太多交互的任务;
  • -XX:MaxGCPauseMillis参数可以设置最大停顿时间,而停顿时间缩短是以牺牲吞吐量和新生代空间来换取的;
  • 另外它还支持GC自适应的调节策略;
Serial Old收集器

Serial Old收集器

  • 是Serial收集器的老年代版本,同样是单线程,使用标记-整理算法;
  • 主要是给Client模式下的虚拟机使用的;
  • 在Server模式下主要是给JDK 1.5及之前配合Parallel Scavenge使用或作为CMS收集器的后备预案;
Parallel Old收集器

Parallel Old收集器

  • 是Parallel Scavenge的老年代版本,使用多线程和标记-整理算法;
  • 是JDK 1.6中才开始提供的;
CMS收集器

CMS收集器

  • 是一种以获取最短回收停顿时间为目标的收集器,特别适合互联网站或者B/S的服务端;
  • 它是基于标记-清除 算法实现的,主要包括4个步骤:初始标记(STW,只是初始标记一下GC Roots能直接关联到的对象,速度很快)、并发标记(非STW,执行GC RootsTracing,耗时比较长)、重新标记(STW,修正并发标记期间因用户程序继续导致变动的那一部分对象标记)和并发清除(非STW,耗时较长);
  • 还有3个明显的缺点:CMS收集器对CPU非常敏感(占用部分线程及CPU资源,影响总吞吐量)、无法处理浮动垃圾(默认达到92%就触发垃圾回收)、大量内存碎片产生(可以通过参数启动压缩);
G1收集器

G1收集器

  • 一款面向服务端应用的垃圾收集器,后续会替换掉CMS垃圾收集器;
  • 特点:并行与并发(充分利用多核多CPU缩短Stop-The-World时间)、分代收集(独立管理整个Java堆,但针对不同年龄的对象采取不同的策略)、空间整合(基于标记-整理)、可预测的停顿(将堆分为大小相等的独立区域,避免全区域的垃圾收集);
  • 关于Region:新生代和老年代不再物理隔离,只是部分Region的集合;G1跟踪各个Region垃圾堆积的价值大小,在后台维护一个优先列表,根据允许的收集时间优先回收价值最大的Region;Region之间的对象引用以及其他收集器中的新生代与老年代之间的对象引用,采用Remembered Set来避免全堆扫描;
  • 分为几个步骤:初始标记(标记一下GC Roots能直接关联的对象并修改TAMS值,需要STW但耗时很短)、并发标记(从GC Root从堆中对象进行可达性分析找存活的对象,耗时较长但可以与用户线程并发执行)、最终标记(为了修正并发标记期间产生变动的那一部分标记记录,这一期间的变化记录在Remembered Set Log里,然后合并到Remembered Set里,该阶段需要STW但是可并行执行)、筛选回收(对各个Region回收价值排序,根据用户期望的GC停顿时间制定回收计划来回收);
理解GC日志

GC日志

  • 最前面的数字代表GC发生的时间(虚拟机启动以后的秒杀);
  • “[GC”和“[Full GC”说明停顿类型,有Full代表的是Stop-The-World的;
  • “[DefNew”、“[Tenured”和“[Perm”表示GC发生的区域;
  • 方括号内部的“3324K -> 152K(3712K)” 含义是 “GC前该内存已使用容量 -> GC后该内存区域已使用容量(该区域总容量)”;
  • 方括号之外的“3324K -> 152K(11904)” 含义是 “GC前Java堆已使用容量 -> GC后Java堆已使用容量(Java堆总容量)”;
  • 再往后“0.0025925 secs”表示该内存区域GC所占用的时间;
垃圾收集器参数总结

垃圾收集器参数1
垃圾收集器参数2

内存分配与回收策略

  • 对象优先在新生代分配
  • 大对象直接进入老年代
  • 长期存活的对象将进入老年代
  • 动态对象年龄判断:如果在Survivor空间中相同年龄所有对象大小总和大于Survivor空间的一半,大于或等于该年龄的对象直接进入老年代;
  • 空间分配担保:发生Minor GC前,虚拟机会先检查老年代最大可用连续空间是否大于新生代所有对象总空间,如果不成立,虚拟机会查看HandlePromotionFailure设置值是否允许担保失败,如果允许继续检查老年代最大可用的连续空间是否大于历次晋升到老年代的平均大小,如果大于会尝试进行一次Minor GC;如果小于或者不允许冒险,会进行一次Full GC;

本章小结

本章介绍了垃圾回收算法、几款JDK 1.7中提供的垃圾收集器特点以及运作原理。内存回收与垃圾收集器在很多时候都是影响系统性能、并发能力的主要因素之一,然而没有固定收集器和参数组合,也没有最优的调优方法,需要根据实践了解各自的行为、优势和劣势。

Java领域JVM垃圾回收算法大揭秘 本文旨在全面解析JVM中的垃圾回收机制,涵盖从基础概念到高级算法的完整知识体系。我们将重点分析不同GC算法的设计思想、实现原理和适用场景,帮助开发者理解JVM内存管理的内部工作机制,并为实际应用中的性能调优提供理论依据。文章首先介绍GC的基本概念和JVM内存结构,然后深入分析各种GC算法,包括标记-清除、标记-整理、分代收集等传统算法,以及G1、ZGC等现代算法。随后通过实际案例展示GC调优方法,最后讨论未来发展趋势。GC Roots:垃圾回收的根对象集合,包括栈帧中的局部变量、静态变量、JNI引用等。 阅读详情

相关推荐

Java虚拟机之GC收集器对比解读

Java 虚拟机提供了多种垃圾收集器(Garbage Collector, GC),每种收集器都有其特定的设计目标和适用场景。JVM 的垃圾收集器主要分为两大类:分代收集器和分区收集器,分代收集器的代表是 CMS,分区收集器的代表是 G1 和 ZGC,下面我们来看看这两大类的垃圾收集器。

天天新知 880

【Java】图解 JVM 垃圾回收(一):GC 判断策略、引用类型、垃圾回收算法

垃圾回收(Garbage Collection,简称 GC)是内存管理的核心组成部分,它负责自动回收不再使用的内存空间。在 Java 中,程序员不需要手动释放对象占用的内存,一旦对象不再被引用,垃圾回收器就会在适当的时机回收它们所占用的内存。这样可以避免内存泄漏和野指针,从而大大减轻了程序员的负担,也使得 Java 成为一个相对安全、易于开发的编程语言。

Data · Model · Agent · Repeat 1828

JVM常用的GC策略介绍

描述了JVM的常用GC算法、GC策略和常用的垃圾回收器,适用于JDK1.7。

GC 回收机制与分代回收策略

那我们该怎么做才能做到年薪60万+呢,对于程序员来说,只有不断学习,不断提升自己的实力。我之前有篇文章提到过,感兴趣的可以看看,到底要学习哪些知识才能达到年薪60万+。通过职友集数据可以查看,以北京 Android 相关岗位为例,其中 【20k-30k】 薪酬的 Android 工程师,占到了整体从业者的 30.8%!北京 Android 工程师「工资收入水平 」今天重点内容是怎么去学,怎么提高自己的技术。1.合理安排时间2.找对好的系统的学习资料3.有老师带,可以随时解决问题。

2401_84132357的博客 984

DarkSword漏洞工具包分析:针对iOS的高级定向攻击

网络安全领域中,漏洞利用工具包是攻击者实施高级持续性威胁(APT)的核心武器。DarkSword作为新型iOS漏洞利用工具包,通过精心构造的漏洞链(包括CVE-2025-31277等)突破系统防护,采用内存驻留技术规避检测。这类攻击通常针对金融、能源等高价值目标,窃取钥匙串凭证、加密货币钱包等敏感数据。防御方面需结合终端检测与响应(EDR)解决方案和网络流量分析,同时关注漏洞修复时效性。本次事件揭示了移动设备在供应链安全和企业环境中的特殊风险,为行业敲响警钟。

weixin_32234493的博客 56

迈德威视相机调用( 基于 Linux系统+ OpenCV )

迈德威视相机调用( 基于 Linux系统+ OpenCV )前言一、登录迈德威视官网,下载官方SDK二、代码调用与视频帧处理( 基于 OpenCV )总结 前言     此博客记录了迈德威视工业相机在 Linux 系统下的代码调用及其环境配置,通过 OpenCV 对视频帧进行处理。   一、登录迈德威视官网,下载官方SDK      迈德威视官网 : http://www.mindvision.com.cn/     1. 进入官网后,在服务支持中选择软件下载。    2. 选择Linux系统S.

kkkkkk0729的博客 5680

Java虚拟机GC机制

Java虚拟机GC机制引言1 相关基础概念1.1 运行时数据分区1.2 可达性分析1.2 GC Roots2 常见GC算法2.1 标记-清除算法2.2 拷贝算法2.3 标记-整理算法3 GC过程概括 引言 程序中分配在堆上的内存,当不再需要的时候,需要及时回收以便后续能申请到内存可使用。像C、C++等语言,如果需要释放无内存空间需要由编程人员自己来处理。而Java语言的虚拟机支持管理内存生命周期、自动释放无用内存,即GC机制。 1 相关基础概念 1.1 运行时数据分区 java代码运行在虚拟机,分为两类:一

fs3296的博客 784

CAD制图

CAD制图可以提高设计效率和准确性,并方便文档的存档和交流,是现代工程设计中不可或缺的一部分。·CAD三维开发是指使用计算机程序和工具来创建、编辑和操作三维模型、图形和设计的过程。它在工程、建筑、制造和游戏等领域广泛应用。CAD三维开发可能涉及到复杂的图形算法、性能优化、并行计算等方面的内容,因此需要深入学习和实践,以提高开发的效率和质量。

RZer的博客 1655

Java虚拟机GC日志分析:从源码角度解读垃圾回收策略

GC日志不是*冷的时间数字,而是JVM垃圾回收器运行状态的生动写照。通过将日志中的关键事件与OpenJDK源码中的具体实现相对应,我们能够真正理解不同回收策略的优劣及其适用场景。这种从“知其然”到“知其所以然”的跨越,是每一位追求卓越的Java开发者必备的技能。下次当你面对GC日志时,不妨多问一句:“源码深处,此刻正在发生什么?” 这或许就是你解开性能谜题的关键钥匙。参考资料1.- 本文源码分析的基础。2.Oracle官方文档 - Java Garbage Collection Basics3.

ql191035的博客 1916

LLC混合滞回控制 vs 电压模/电流模:UCC25640x仿真对比与选型指南

在开关电源设计中,LLC谐振变换器的环路补偿是核心难点。传统电压模控制(VMC)和电流模控制(CMC)在LLC拓扑上存在环路增益漂移、动态响应慢等局限。混合滞回控制通过滞回比较器直接调制开关频率,并融合输出电压与谐振腔电流信息,实现了自适应环路增益和快速瞬态响应。该技术显著提升轻载效率与动态性能,适用于高密度适配器、快充及车载充电机等场景。本文基于UCC25640x系列,通过仿真对比三种控制策略,为工程选型与调试提供实践参考。

weixin_33925615的博客 336

YOLOv5入门实践(2)——手把手教你利用labelimg标注数据集

YOLOv5入门实践第2步,手把手教你使用labelimg标注数据集

路人贾的博客 1万+

一起学习GC算法(图文详解)

你好我是辰兮,很高兴你能来阅读,本篇整理了GC即垃圾回收算法相关的知识点,希望对你有帮助,分享获取新知,大家一起进步! 文章目录一、文章序言二、GC算法三、拓展小结 一、文章序言 GC(Garbage Collection):JAVA/.NET中的垃圾回收器。Java是由C++发展来的。它摈弃了C++中一些繁琐容易出错的东西。其中有一条就是这个GC。 Java语言的一个显著优点就是引入垃圾回收机制,在一定程度上解决了内存管理的问题。 垃圾回收可以有效的防止内存泄露,有效的使用空闲的内存; 垃圾回收.

末尾卡片和博主交流学习! 6026

【图像超分】论文复现:新手入门必备!Pytorch实现SRGAN!手把手详细教程!代码注释详尽!可用于训练自己的数据集!实时验证模型性能!绘制PSNR曲线图!附训练好的各放大倍数的模型权重文件!

【图像超分】论文精读:SRResNet/SRGAN【图像超分】论文复现:万字长文!Pytorch实现SRResNet代码修改无报错!踩坑全记录!适合各种深度学习新手!帮助你少走弯路!附修改后的代码和PSNR最优的模型权重文件!请配合上述论文精读文章使用,效果更佳!与原论文描述不一样的实现部分,也即可以修改的部分数据集使用:论文中是ImageNet随机选35000张图像,本文是VOC2012数据集16700张图像。数据集预处理:裁剪大小不同,论文是96×96,本文是88×88。

主要更新底层视觉(去噪、超分等)相关的科研内容,形式为【论文精读】+【论文复现】 6856

探索JVM垃圾回收算法:选择适合你应用的最佳GC策略

算法优点缺点使用示例推荐参数Serial GC实现简单,适合单核CPU停顿时间长,不适合多线程环境-Xms-Xmx高吞吐量,适合多核环境仍然存在“Stop-The-World”,调优难度大-Xms-XmxCMS GC低停顿时间,适合延迟敏感应用内存碎片问题严重,整体吞吐量低-Xms-XmxG1 GC停顿时间可控,适合大规模应用,减少内存碎片实现复杂,调优难度较大,在某些场景下性能不如Parallel GC-Xms-Xmx选择适合的GC算法需要根据具体应用的需求和环境进行权衡。

zcs_978176963的博客 1672

华为OD机试:查找接口成功率最优时间段 (C/C++/Py/Java/JS/GO)

华为OD机试双机位C卷 查找接口成功率最优时间段,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解。

qq_45776114的博客 4687

基于容积卡尔曼滤波的弹目相对姿态估计算法及其在导弹末端制导中的应用

本文针对导弹末端制导中的强非线性姿态估计问题,提出了一种基于容积卡尔曼滤波(CKF)的弹目相对姿态估计算法。通过建立包含视线角、角速率和相对距离的6维状态模型,利用三阶球面-相径容积准则精确逼近非线性状态分布,避免了传统EKF的线性化误差。在MATLAB/Simulink仿真中,CKF表现出比EKF更高的视线角速率估计精度和更快的收敛速度,最终显著减小了脱靶量,验证了其在提升导弹末端制导精度方面的有效性。该算法计算复杂度适中,适合工程实现,为高精度非线性姿态估计提供了新思路。

AI的内部世界的博客 105

JVM的GC回收算法、GC收集器以及内存分配策略

目录 •写在前面 •标记-清除算法 •复制算法 •标记-整理算法 •HotSpot上的算法实现保障 •GC收集器 •内存分配策略 •写在前面 JVM的垃圾回收算法、收集器以及内存分配策略放在一起了解和理解,我觉得有助于我们加深印象,这一篇文章我就不再讲述对象为什么要回收以及何时回收了,想要了解相关知识可以看我的另一篇文章JVM如何判断对象是否要回收。几个点放在一起内容会有些多,不...

BoCong-Deng的博客 1万+

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

上一篇: JVM启动参数推荐
下一篇: Java JVM 性能调优笔记
王树民
博客等级 码龄10年 912粉丝 560原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值