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

图解 JVM 垃圾回收(一)

  • 1.前言
    • 1.1 什么是垃圾
    • 1.2 内存溢出和内存泄漏
  • 2.垃圾回收的定义与重要性
  • 3.GC 判断策略
    • 3.1 引用计数算法
    • 3.2 可达性分析算法
  • 4.引用类型
  • 5.垃圾回收算法
    • 5.1 标记-复制(Copying)
    • 5.2 标记-清除(Mark-Sweep)
    • 5.3 标记-整理(Mark-Compact)
    • 5.4 分代收集理论
    • 5.5 垃圾回收阶段算法小结

1.前言

1.1 什么是垃圾

垃圾 是指运行程序中 没有任何引用指向的对象,需要被回收。

1.2 内存溢出和内存泄漏

内存溢出:经过垃圾回收之后,内存仍旧无法存储新创建的对象,内存不够溢出。

内存泄漏:又叫 “存储泄漏”,对象不会再被程序使用了,但是 GC 又不能回收它们。例如:IO 流不适用了但是没有被 Close、数据库连接 JDBC 没有被 Close。这些对象不会被回收就会占据内存,大量的此类对象存在,也是导致内存溢出的原因。

2.垃圾回收的定义与重要性

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

  • 防止内存泄漏:手动管理内存容易导致内存泄漏,而 GC 可以自动回收不再使用的对象,防止内存泄漏的发生。
  • 提高开发效率:程序员不再需要关心内存释放的问题,可以更加集中精力在业务逻辑的实现上。
  • 系统性能和稳定性:通过有效的垃圾回收策略,可以保证系统的性能和稳定性。

垃圾回收的基本步骤分两步:

  • 1️⃣ 查找内存中不再使用的对象(GC 判断策略)
  • 2️⃣ 释放这些对象占用的内存(GC 收集算法)

在这里插入图片描述

3.GC 判断策略

3.1 引用计数算法

给对象添加一个引用计数器,当对象增加一个引用时计数器加 1,引用失效时计数器减 1。引用计数为 0 的对象可被回收。两个对象出现循环引用的情况下,此时引用计数器永远不为 0,导致无法对它们进行回收。正因为循环引用的存在,因此 Java 虚拟机不使用引用计数算法。

public class ReferenceCountingGC {public Object instance = null;public static void main(String[] args) {ReferenceCountingGC objectA = new ReferenceCountingGC();ReferenceCountingGC objectB = new ReferenceCountingGC();objectA.instance = objectB;objectB.instance = objectA;}
}

3.2 可达性分析算法

通过 GC Roots 作为起始点进行搜索,能够到达到的对象都是存活的,不可达的对象可被回收。

在这里插入图片描述
哪些对象可以作为 GC Roots 呢?

  • 虚拟机栈(栈帧中的局部变量表)中引用的对象
  • 本地方法栈(Native 方法)中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 所有被同步锁持有的对象
  • JNIJava Native Interface)引用的对象
public void method() { Object localVariable = new Object(); // localVariable 是 GC Roots 
}public class MyClass { private static Object staticObject = new Object(); // staticObject 是 GC Roots 
}public class MyClass { private static final String CONSTANT_STRING = "constant"; // CONSTANT_STRING 是 GC Roots 
}public synchronized void synchronizedMethod() { // 当前对象(this)在执行同步方法时是 GC Roots 
}

4.引用类型

无论是通过引用计算算法判断对象的引用数量,还是通过可达性分析算法判断对象是否可达,判定对象是否可被回收都与引用有关。

Java 中有四种类型的引用,它们对垃圾回收的影响不同:

  • 强引用Strong Reference):最常见的引用类型,只要对象有强引用指向,它就不会被垃圾回收。
  • 软引用Soft Reference):软引用可以帮助垃圾回收器回收内存,只有在内存不足时,软引用指向的对象才会被回收。
  • 弱引用Weak Reference):弱引用指向的对象在下一次垃圾回收时会被回收,不管内存是否足够。
  • 虚引用Phantom Reference):虚引用的主要用途是跟踪对象被垃圾回收的状态,虚引用指向的对象总是可以被垃圾回收。
import java.lang.ref.*;public class ReferenceTypes {public static void main(String[] args) {Object strongRef = new Object();  // 强引用SoftReference<Object> softRef = new SoftReference<>(new Object());  // 软引用WeakReference<Object> weakRef = new WeakReference<>(new Object());  // 弱引用PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), new ReferenceQueue<>());  // 虚引用System.gc();  // 触发垃圾回收System.out.println("Strong Reference: " + strongRef);System.out.println("Soft Reference: " + softRef.get());System.out.println("Weak Reference: " + weakRef.get());System.out.println("Phantom Reference: " + phantomRef.get());}
}

5.垃圾回收算法

在这里插入图片描述

5.1 标记-复制(Copying)

它可以将内存分为大小相同的两块,每次使用其中的一块。当这一块的内存使用完后,就将还存活的对象复制到另一块去,然后再把使用的空间一次清理掉。这样就使每次的内存回收都是对内存区间的一半进行回收。

在这里插入图片描述

  • ✅ 优点: 减少内存碎片,提高空间利用率。
  • ⭕ 缺点: 减半了可用的堆内存,可能增加垃圾回收的频率。

5.2 标记-清除(Mark-Sweep)

算法分为“标记”和“清除”阶段:

标记清除算法分为两个主要步骤:标记清除

  • 标记阶段: 在标记阶段,垃圾回收器会从 GC Roots 开始,遍历所有可达的对象,并标记它们为活动对象。
  • 清除阶段: 在清除阶段,垃圾回收器会遍历整个堆,回收所有未被标记的对象的内存。

有两个明显的问题:

  • 效率问题:如果需要标记的对象太多,效率不高。
  • 空间问题:标记清除后会产生大量不连续的内存碎片,空间碎片太多可能会导致在运行过程中需要分配较大对象时无法找到足够的连续内存而不得不提前触发另一次垃圾收集。

在这里插入图片描述

5.3 标记-整理(Mark-Compact)

标记整理算法是标记清除算法的改进版本。它在标记和清除的基础上增加了整理阶段,将所有活动对象向一端移动,从而消除内存碎片。

  • ✅ 优点: 解决了内存碎片化问题,提高了空间利用率。
  • ⭕ 缺点: 移动对象增加了额外的开销。

在这里插入图片描述

5.4 分代收集理论

当前虚拟机的垃圾收集都采用分代收集算法,根据对象存活周期的不同将内存分为几块。一般将 Java 堆分为新生代和老年代,这样我们就可以根据各个年代的特点选择合适的垃圾收集算法。

  • 新生代Young Generation):使用复制算法,因为新生代中的对象生命周期较短。
  • 老年代Tenured Generation):使用标记整理或标记清除算法,因为老年代中的对象生命周期较长,且数量较少。

在这里插入图片描述
1️⃣ 新生代的回收算法(以 复制 算法为主)

  • 所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。
  • 新生代内存按照 8 : 1 : 1 8:1:1 8:1:1 的比例分为一个 eden 区和两个 survivorsurvivor0survivor1)区(一般而言)。大部分对象在 eden 区中生成。回收时先将 eden 区存活对象复制到一个 survivor0 区,然后清空 eden 区,当这个 survivor0 区也存放满了时,则将 eden 区和 survivor0 区存活对象复制到另一个 survivor1 区,然后清空 eden 和这个 survivor0 区,此时 survivor0 区是空的,然后将 survivor0 区和 survivor1 区交换,即保持 survivor1 区为空, 如此往复。
  • survivor1 区不足以存放 edensurvivor0 的存活对象时,就将存活对象直接存放到老年代。若是老年代也满了就会触发一次 Full GCMajor GC),也就是新生代、老年代都进行回收。
  • 新生代发生的 GC 也叫做 Minor GCMinor GC 发生频率比较高(不一定等 eden 区满了才触发)。

2️⃣ 老年代的回收算法(以 标记-清除标记-整理 为主)

  • 在年轻代中经历了N次垃圾回收后仍然存活的对象,就会被放到老年代中。因此,可以认为老年代中存放的都是一些生命周期较长的对象。
  • 内存比新生代也大很多(大概比例是 1 : 2 1:2 1:2),当老年代内存满时触发 Major GCMajor GC 发生频率比较低,老年代对象存活时间比较长,存活率标记高。

3️⃣ 永久代(Permanet Generation)的回收算法

JDK 1.8 及以后方法区的实现变成了元空间。

用于存放静态文件,如Java类、方法等。永久代对垃圾回收没有显著影响,但是有些应用可能动态生成或者调用一些 class,例如 Hibernate 等,在这种时候需要设置一个比较大的永久代空间来存放这些运行过程中新增的类。永久代也称 方法区。方法区主要回收的内容有:废弃常量和无用的类。对于废弃常量也可通过根搜索算法来判断,但是对于无用的类则需要同时满足下面 3 个条件:

  • 该类所有的实例都已经被回收,也就是 Java 堆中不存在该类的任何实例。
  • 加载该类的 ClassLoader 已经被回收。
  • 该类对应的 java.lang.Class 对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。

5.5 垃圾回收阶段算法小结

标记复制标记清除标记压缩
速率最快最慢
空间开销两个大小相同的空间少(会堆积碎片)少(不会碎片堆积)
移动对象

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

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

相关文章

Android 基础技术——HashMap

笔者希望做一个系列&#xff0c;整理 Android 基础技术&#xff0c;本章是关于HashMap HaspMap的默认初始长度是16&#xff0c;并且每次扩展长度或者手动初始化时&#xff0c;长度必须是2的次幂。 为什么长度是2的x次幂和每次扩容都是2倍?? 1&#xff09;当一个key被放进到数…

Python实现时间序列分析使用LOESS(STL)模型进行季节性趋势分解(STL算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 时间序列分析中&#xff0c;LOESS&#xff08;局部加权回归平滑&#xff09;和STL&#xff08;Seasona…

轨道交通信号增强与覆盖解决方案——经济高效,灵活应用于各类轨道交通场景!

方案背景 我国是世界上轨道交通里程最长的国家&#xff0c;轨道交通也为我们的日常出行带来极大的便利。伴随着无线通信技术的快速发展将我们带入电子时代&#xff0c;出行的过程中对无线通信的依赖程度越来越高&#xff0c;无论是车站还是车内都需要强大、高质量的解决方案以…

全网最详细的从0到1的turbo pnpm monorepo的前端工程化项目[搭建篇]

全网最详细的从0到1的turbo pnpm monorepo的前端工程化项目[搭建篇] 引言相关环境技术栈初始化工程安装turbo配置pnpm-workspace安装husky安装lint-staged安装eslint安装prettier配置 .editorconfig配置 .gitignore初步项目结构结语 引言 最近各种原因&#xff0c;生活上的&am…

SSTI模板注入漏洞(vulhub 复现)

首先了解模板引擎&#xff1a; 模板引擎&#xff08;这里特指用于Web开发的模板引擎&#xff09;是为了使用户界面与业务数据&#xff08;内容&#xff09;分离而产生的&#xff0c;它可以生成特定格式的文档&#xff0c;利用模板引擎来生成前端的html代码&#xff0c;模板引擎…

网络原理 - HTTP/HTTPS(1)

HTTP HTTP是什么 HTTP("全程超文本协议")是一种应用非常广泛的应用层协议. 文本:字符串(能在utf8/gbk)码表上找到合法字符. 超文本:不仅是字符串,还能携带图片啥的(HTML). 富文本:类似于word文档这种. HTTP诞生于1991年.目前已经发展为最主流使用的一种应用层协议.…

如何使用python 挑战将ai生成的概念图制作成2d游戏

要使用Python将AI生成的概念图制作成2D游戏&#xff0c;你可以遵循以下步骤&#xff1a; 生成概念图&#xff1a; 使用AI图像生成工具&#xff08;如DALL-E、DeepArt等&#xff09;来创建你的游戏概念图。保存生成的图像文件&#xff0c;通常为PNG或JPEG格式。 选择游戏引擎&a…

防火墙 iptables(二)-------------SNAT与DNAT

一、SNAT ①SNAT 应用环境: 局域网主机共享单个公网IP地址接入Internet (私有IP不能在Internet中正常路由) ②SNAT原理: 源地址转换&#xff0c;根据指定条件修改数据包的源IP地址&#xff0c;通常被叫做源映射 数据包从内网发送到公网时&#xff0c;SNAT会把数据包的源IP由…

【Java EE初阶十九】网络原理(四)

4. 数据链路层 数据链路层也有很多种协议&#xff0c;其中一个比较常见常用的,就是“以太网协议”&#xff08;通过网线/光纤, 来通信所使用的协议叫做以太网协议&#xff0c;以太网是横跨数据链路层 物理层&#xff09;&#xff1b; 4.1 以太网数据帧格式 帧头 载荷(IP 数据…

从一到无穷大 #24 LogReducer:讨论日志中热点的影响,识别及在线解决方法

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作)&#xff0c;由 李兆龙 确认&#xff0c;转载请注明版权。 文章目录 引言LogReducer系统性分析日志影响&#xff0c;原因在线日志缩减框架 反省总结 引言 …

提升起重机效率与降低维修成本:PreMaint预测性维护系统的应用

随着科技的不断发展&#xff0c;人工智能技术在各行各业都展现出了强大的应用潜力。在港口起重机设备的维护管理中&#xff0c;预测性维护系统是一项革命性的技术&#xff0c;为提升设备效率、降低维修成本提供了全新的解决方案。本文将深入探讨起重机预测性维护系统的原理、应…

nvm的相关属性以及用法

一、安装nvm的原因 nvm是一个命令行工具&#xff0c;用于管理和切换到不同版本的 Node.js。 二、安装nvm&#xff08;node 版本管理工具&#xff09; 1、注意&#xff1a; Windows 不支持 NVM&#xff0c;因为 NVM 仅在 Linux 和 Mac 上受支持。你将在 Windows 机器上使用的…

中小品牌项目管理软件排行榜:发现行业新秀与潜力股

使用项目管理软件可以帮助企业提高工作效率&#xff0c;降低成本&#xff0c;提升竞争力。在项目管理软件中&#xff0c;不仅有大品牌如Zoho Projects、Microsoft Project、Jira等&#xff0c;还有一些小品牌的软件也备受关注。本文就为大家介绍在项目管理软件排行榜中小品牌榜…

09_Java集合

一、Java集合框架概述 一方面&#xff0c; 面向对象语言对事物的体现都是以对象的形式&#xff0c;为了方便对多个对象的操作&#xff0c;就要对对象进行存储。另一方面&#xff0c;使用Array存储对象方面具有一些弊端&#xff0c;而Java 集合就像一种容器&#xff0c;可以动态…

如何在Linux系统中配置并优化硬盘的RAID

在Linux系统中配置和优化硬盘的RAID技术可以帮助提高数据存储性能和安全性。RAID&#xff08;Redundant Array of Independent Disks&#xff09;技术通过将多个硬盘组合起来&#xff0c;以增加性能、容量或冗余度&#xff0c;提高数据的可靠性和可用性。本文将介绍如何在Linux…

6.s081 学习实验记录(十)file system

文章目录 一、Large files简介提示实验代码实验结果 二、Symbolic links简介提示实验代码实验结果 首先切换到 fs 分支 $ git fetch$ git checkout fs$ make clean 一、Large files 简介 该实验需要我们增大xv6文件的最大大小&#xff0c;目前xv6的最大文件大小为 268个块&…

WordPress主题YIA在广告位添加图片广告时下方有空白怎么办?

YIA主题设置中默认有4个广告位&#xff0c;而侧边栏的广告位由站长自行添加。boke112百科在这些广告位添加图片广告后发现图片下方有空白&#xff0c;导致下方的两个角没有变圆角&#xff0c;看起来也有点不好看。具体如下图所示&#xff1a; 其实&#xff0c;这个问题就是典型…

挑战杯 地铁大数据客流分析系统 设计与实现

文章目录 1 前言1.1 实现目的 2 数据集2.2 数据集概况2.3 数据字段 3 实现效果3.1 地铁数据整体概况3.2 平均指标3.3 地铁2018年9月开通运营的线路3.4 客流量相关统计3.4.1 线路客流量排行3.4.2 站点客流量排行3.4.3 入站客流排行3.4.4 整体客流随时间变化趋势3.4.5 不同线路客…

跟着pink老师前端入门教程(JavaScript)-day01

一、计算机编程基础 &#xff08;一&#xff09;编程语言 1、编程 编程&#xff1a;就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码&#xff0c;并最终得到结果的过程。 计算机程序&#xff1a;就是计算机所执行的一系列的指令集合&#xff0c;而程序全部…

嵌入式学习 C++ Day5、6

嵌入式学习 C Day5、6 一、思维导图 二、作业 1.以下是一个简单的比喻&#xff0c;将多态概念与生活中的实际情况相联系&#xff1a; 比喻&#xff1a;动物园的讲解员和动物表演 想象一下你去了一家动物园&#xff0c;看到了许多不同种类的动物&#xff0c;如狮子、大象、猴…