当前位置: 首页 > news >正文

JVM 根可达算法

Java中的垃圾

Java中"垃圾"通常指的是不再被程序使用和引用的对象,具体表现在没有被栈、JNI指针和永久代对象所引用的对象。Java作为一种面向对象的编程语言,它使用自动内存管理机制,其中垃圾收集器负责检测和回收不再被程序引用的对象,以释放它们占用的内存空间。以下是一些导致对象成为垃圾的常见情况:

  1. 无引用对象: 当一个对象没有任何引用指向它时,它就变得不可达,成为垃圾,Java的垃圾收集器会识别这样的对象,并将它们回收。

  2. 引用循环: 如果一组对象彼此引用形成一个循环,而这个循环与程序的其他部分没有引用相连,那么这个循环中的对象就会成为垃圾。Java的垃圾收集器通过识别引用循环并处理它们来防止内存泄漏。

  3. 显式置空引用: 如果程序员显式地将一个引用置空(null),而没有其他引用指向相同的对象,那么该对象就变成了垃圾。

垃圾收集器周期性地运行,并识别和回收这些垃圾对象,释放其内存中对应的区域以确保内存能够得到有效利用,这种自动的内存管理机制就叫做垃圾回收。

如何寻找垃圾?

引用计数(Reference Count)
引用计数算法是一种垃圾标记,其核心思想是通过维护对象的引用计数来判断对象是否可以被回收。每个对象都有一个关联的引用计数,表示当前有多少个指针引用它。当引用计数为零时,意味着没有指针再引用该对象,因此可以安全地回收该对象的内存。

其实引用计数算法的核心思想就是,只要有对象引用我,那么就说明我是有用的,我还不需要被回收,反正,我就是没有用的对象,那么我和我的子对象都应该被回收掉。这里我们说的对象都是堆上的对象,一般是堆上的内存空间需要程序员手动回收,而栈上的内存空间则由操作系统自行回收。由于栈上的对象是操作系统自行管理和回收的,因此栈上的对象以及一些静态对象始终都是出于存活的状态,因此,堆中存活的对象至少会有一个引用(指针)指向它。

但是这样会存在着一个问题,就是对象中的引用关系形成了环状——循环引用,这种情况下环内所有对象的引用都是>1的,这样一来环内的所有都无法被回收从而造成“内存泄漏”。这是引用算法最主要的局限性,也是为什么JVM不采用循环计数的方法来标记垃圾的原因。

根可达算法(Root Search)

由于引用计数算法无法解决“循环引用”的问题,无可避免的会造成内存泄露,因此,Java没有采用引用计数算法来寻找垃圾。而是采用了一种从GC Roots开始搜索存活对象的垃圾标记算法——根可达算法。
在这里插入图片描述

哪些是GC Root?

  1. 线程栈 (Thread Stacks) :活动线程的栈帧中的本地变量引用的对象。每个线程都有一个栈,栈中的引用对象是潜在的存活对象。
  2. 静态变量 (Static Variables) :类的静态成员变量引用的对象。静态变量随着类的加载而初始化,它们的引用可能使对象保持存活。
  3. 常量池 (Constant Pool) :常量池中的引用,包括字符串常量等。这些常量在类加载时被创建,它们的引用也可能使对象保持存活。
  4. JNI 引用 (JNI References) :通过 JNI 在本地代码中创建的对象引用。如果 Java 代码通过 JNI 调用了本地方法,并在本地方法中创建了对象,这些对象的引用也是 GC Roots。
  5. 监控与管理 MBeans (JMX) :活动的监控、管理 MBeans 等通过 JMX 等管理工具注册的对象。这些对象的引用也被视为 GC Roots。

线程栈 (Thread Stacks)
在Java中,当程序运行的时候线程会将一个个方法放到栈上来执行,并且对于方法局部的一些小的对象和变量也会被分配在栈空间上,而栈空间是由操作系统本身来控制什么时候进行释放和分配的。因此,基于这个逻辑我们可以认为对于当前线程来说,存在于栈空间上的变量都是存活的,而且栈空间一般比较小只有几MB的大小,里面存活的变量和对象都是有限的作为GC Roots来说搜索起来也是非常高效的。

静态变量 (Static Variables)
在Java中静态变量一般是随着类加载的时候被创建和初始化的,和Java字节码一样,静态变量也会被加载到元空间(Meta Space,Java 8之前叫做方法区(Method Area)或叫做永久代(Permanent Generation),Java 8之后叫做元空间)。

元空间的对象是不会轻易被释放的,而静态变量会随着整个类被释放的时候才会被释放,因此静态变量可以作为GC Root来寻找垃圾。

常量池 (Constant Pool)
常量池(Constant Pool)是Java中一种存放常量的数据结构,用于存储编译期生成的字面量和符号引用。常量池属于元空间(Meta Space,Java 8之前叫做方法区(Method Area)或叫做永久代(Permanent Generation),Java 8之后叫做元空间),具体说是类加载后存放在元空间的一部分内存。

在Java程序的编译阶段,常量池会保存各种字面量和符号引用,包括字符串、类和接口的全限定名、字段和方法的名称和描述符等,这些信息在编译后会被存放在class文件的常量池中,在运行期间这些常量池依旧会存在并且Java根据常量池来映射参数。

所以,处于常量池中的变量也可以作为GC Roots来寻找垃圾

JNI 引用 (JNI References)
JNI(Java Native Interface)引用是指在Java程序中通过JNI创建的与本地代码(C++代码,调用平台相关函数)相互调用的引用。JNI引用包括本地引用(Local Reference)、全局引用(Global Reference)和弱全局引用(Weak Global Reference)。

本地引用(Local Reference): 本地引用是一种短期的引用,用于限定其生命周期。当Java方法调用本地方法时,本地引用会被创建,但在本地方法返回后,这些引用将被自动释放。本地引用不能作为GC Roots。

全局引用(Global Reference): 全局引用是一种长期有效的引用,可以在整个程序的生命周期内使用。全局引用可以防止被引用对象被垃圾回收,因此它可以作为GC Roots。

弱全局引用(Weak Global Reference): 弱全局引用也是一种全局引用,但它对被引用对象的生命周期没有强制影响。如果一个对象只被弱全局引用引用,那么它在垃圾回收时可能被回收。弱全局引用不能作为GC Roots。

JNI引用之所以能作为GC Roots,是因为它们可以在本地方法(C++方法,调用平台相关函数)中持有Java对象的引用,防止这些对象在本地方法执行期间被垃圾回收。全局引用在整个程序的生命周期内有效,因此它们有可能成为根引用,即GC Roots。

根可达算法原理

知道了什么是GC Roots那么根可达算法理解起来就相对来说会简单一些。GC Roots我们可以简单理解为和Java程序的生命周期强关联、和JVM生命周期强关联或者和当前线程强关联的一些对象。这些对象至少说在发生GC这一时刻是不应该被当成垃圾回收掉的,否则会影响程序的正常使用,因此,我们标记存活对象的时候从GC Roots开始,认为被GC Roots 引用或者间接引用的对象就是存活对象。因此,根可达算法的基本原理和流程如下:

  1. 初始根集合(Initial Roots): 根可达算法从程序的初始根集合开始,这些根是一组特殊的引用,如线程栈中的引用、静态变量、JNI(Java Native Interface)引用等。

  2. 标记阶段(Mark Phase): 算法通过追踪根引用,递归遍历对象图,标记所有可以从根引用访问到的对象。在这个过程中,被标记的对象被认为是可达的,而未被标记的对象被认为是不可达的。

  3. 标记-清除阶段(Mark-Sweep Phase): 在标记完成后,算法执行清除操作,即移除未被标记的对象。这些未被标记的对象被认为是不可达的,可以被垃圾回收器回收。这个阶段的目标是回收不再被程序使用的内存空间。

  4. 压缩(Compaction)或整理(Compaction): 在某些情况下,为了优化内存布局,可能会执行进一步的操作,如将存活对象整理到一起,以减少内存碎片。这个步骤通常与标记-清除阶段结合使用。

  5. 可选的再标记阶段(Optional Re-Mark Phase): 有些算法可能会在标记-清除后执行可选的再标记阶段,以处理在清除阶段可能发生的并发引用更新。这一步确保在垃圾回收过程中引用关系的一致性。

  6. 结束(Finish): 垃圾回收算法完成后,内存中只留下了可达对象,而不可达的对象已被清理。程序可以继续执行。

实际上来说,如CMS和G1之类比较流行的垃圾回收器都是采用的“三色标记”算法,而非直接采用的根可达算法来对垃圾进行标记的.

相关文章:

JVM 根可达算法

Java中的垃圾 Java中"垃圾"通常指的是不再被程序使用和引用的对象,具体表现在没有被栈、JNI指针和永久代对象所引用的对象。Java作为一种面向对象的编程语言,它使用自动内存管理机制,其中垃圾收集器负责检测和回收不再被程序引用的…...

Kafka基础架构与核心概念?有哪些应用场景?

Kafka简介 Kafka是由Apache软件基金会开发的一个开源流处理平台,由Scala和Java编写。Kafka是一种高吞吐量的分布式发布订阅消息系统,它可以处理消费者在网站中的所有动作流数据。架构特点是分区、多副本、多生产者、多订阅者,性能特点主要是高吞吐,低时延。 Kafka主要设计…...

内网不能访问网站怎么办?

内网不能访问网站是在网络使用过程中常见的问题之一。当我们使用局域网连接时,有时候会遇到无法访问特定网站的情况。这可能是因为网络环境复杂,或者受到了某些限制。本篇文章将介绍一种解决内网不能访问网站问题的产品——天联组网。 天联组网是一款由…...

python-求f(x,n)

[题目描述] 输入: 输入 𝑥和 𝑛。输出: 函数值,保留两位小数。样例输入1 4.2 10 样例输出1 3.68 来源/分类(难度系数:一星) 完整代码如下: x,nmap(eval,input().split(…...

java值jsp语法笔记

1 JSP注释 1.1 显示注释 显示注释会出现在生成的HTML文档中&#xff0c;对用户可见。 <!-- 这是一个HTML显示注释 --> 1.2 隐式注释 隐式注释不会出现在生成的HTML文档中&#xff0c;对用户不可见。 <%-- 这是一个JSP隐式注释 --%> 2 JSP脚本元素 2.1 局部…...

057、PyCharm 运行代码报错:Error Please select a valid Python interpreter

当我们在PyCharm运行代码时&#xff0c;提示如下图错误&#xff1a; 那么问题通常是由于PyCharm未正确配置Python解释器引起的。 我们只需按以下步骤重新配置Python解释器即可&#xff1a; 打开PyCharm设置&#xff1a; 在菜单栏中的点击 “File” -> “Settings”&#xf…...

Java实现图书管理系统

一、引言 本篇介绍了一个简易的图书管理系统&#xff0c;面向管理员和普通用户分别给出了不同的菜单&#xff0c;实现了一些基本的图书操作功能&#xff0c;包括图书的增删查改、借阅、归还等 二、图书管理系统框架 图书管理系统&#xff0c;顾名思义&#xff0c;管理的是图…...

使用静态方法接受对象参数

我们先来看一个例子 public class MyInteger { private int value; // 构造函数 public MyInteger(int value) { this.value value; } // 实例方法 public boolean isEven() { return value % 2 0; } // 静态方法接受int参数 public static boolean isEvenStatic…...

cocos creator如何使用cryptojs加解密(及引入方法)

cocos creator如何使用cryptojs加解密&#xff08;及引入方法&#xff09; 如果想转请评论留个言并注明原博 Sclifftop 13805064305 阿浚 cocos creator如何使用cryptojs加解密&#xff08;及引入方法&#xff09; 步骤 获取库 1. npm install crypto-js -g&#xff0c;加不加…...

安装台式电脑网卡驱动

安装电脑网卡驱动 1. 概述2. 具体方法2.1 先确定主板型号2.2 详细操作步骤如下2.2.1 方法一2.2.2 方法二2.2 主流主板官网地址 结束语 1. 概述 遇到重装系统后、或者遇到网卡驱动出现问题没有网络时&#xff0c;当不知道怎么办时&#xff0c;以下的方法&#xff0c;可以作为一…...

JavaEE-多线程(1)

这篇文章&#xff0c;我们将介绍进程、线程的相关概念以及进程和线程的区别&#xff0c;下篇文章我们将使用Java来编写多线程的代码 进程&#xff1a; 进程&#xff08;Process&#xff09;是操作系统中资源分配的基本单位&#xff0c;它是一个正在运行的程序的实例。进程包括…...

【计算机视觉】人脸算法之图像处理基础知识(五)

图像的几何变换 3.图像的旋转 图像的旋转就是让图像按照某一点旋转到指定的角度。需要确定3个参数&#xff1a;图像的旋转中心、旋转角度和缩放因子。在openv中通过getRotationMatrix2D()函数来实现图像的旋转。 import cv2 import numpy as npimgpath "images/img1.j…...

工业 web4.0 的 UI 风格,独树一帜

工业 web4.0 的 UI 风格&#xff0c;独树一帜...

BSP驱动教程-CAN/CANFD/CANopen知识点总结分享

学习知识点整理&#xff1a; CAN 总线的前世今生&#xff1a; https://www.armbbs.cn/forum.php?modviewthread&tid104480 wikibai百科CAN总线&#xff1a; https://en.wikipedia.org/wiki/CAN_bus 瑞萨CAN入门教程&#xff1a; https://www.armbbs.cn/forum.php?m…...

微服务之远程调用

常见的远程调用方式 RPC&#xff1a;Remote Produce Call远程过程调用&#xff0c;类似的还有 。自定义数据格式&#xff0c;基于原生TCP通信&#xff0c;速度快&#xff0c;效率高。早期的webservice&#xff0c;现在热门的dubbo &#xff08;12不再维护、17年维护权交给apac…...

Opencv数一数有多少个水晶贴纸?

1.目标-数出有多少个贴纸 好久没更新博客了&#xff0c;最近家里小朋友在一张A3纸上贴了很多水晶贴纸&#xff0c;要让我帮他数有多少个&#xff0c;看上去有点多&#xff0c;贴的也比较随意&#xff0c;于是想着使用Opencv来识别一下有多少个。 原图如下&#xff1a; 代码…...

AI Agent智能应用从0到1定制开发(完结)

在数字化时代的浪潮中&#xff0c;人工智能&#xff08;AI&#xff09;代理智能应用如同星辰般璀璨&#xff0c;引领着技术革新的潮流。从零开始定制开发一款AI Agent智能应用&#xff0c;就像是在无垠的宇宙中绘制一颗新星的轨迹&#xff0c;每一步都充满了挑战与创新的火花。…...

事件驱动架构:新时代的软件设计范式

引言 在现代软件开发中&#xff0c;随着系统复杂度的增加和实时响应需求的提升&#xff0c;传统的单体架构和同步调用模型逐渐显露出其局限性。事件驱动架构&#xff08;Event-Driven Architecture, EDA&#xff09;作为一种高度解耦、灵活性强的架构设计模式&#xff0c;越来…...

【机器学习】机器学习与物流科技在智能配送中的融合应用与性能优化新探索

文章目录 引言机器学习与物流科技的基本概念机器学习概述监督学习无监督学习强化学习 物流科技概述路径优化车辆调度需求预测 机器学习与物流科技的融合应用实时物流数据分析数据预处理特征工程 路径优化与优化模型训练模型评估 车辆调度与优化深度学习应用 需求预测与优化强化…...

web前端何去何从:探索未来之路

web前端何去何从&#xff1a;探索未来之路 在数字化浪潮的推动下&#xff0c;web前端技术正经历着前所未有的变革。随着新技术的不断涌现和用户体验的持续提升&#xff0c;web前端开发者们面临着前所未有的挑战与机遇。那么&#xff0c;web前端究竟何去何从&#xff1f;本文将…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...

【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error

在前端开发中&#xff0c;JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作&#xff08;如 Promise、async/await 等&#xff09;&#xff0c;开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝&#xff08;r…...

一些实用的chrome扩展0x01

简介 浏览器扩展程序有助于自动化任务、查找隐藏的漏洞、隐藏自身痕迹。以下列出了一些必备扩展程序&#xff0c;无论是测试应用程序、搜寻漏洞还是收集情报&#xff0c;它们都能提升工作流程。 FoxyProxy 代理管理工具&#xff0c;此扩展简化了使用代理&#xff08;如 Burp…...