当前位置: 首页 > 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;本文将…...

yolov8通过训练完成的模型生成图片热力图--论文需要

源代码来自于网络 使用pytorch_grad_cam&#xff0c;对特定图片生成热力图结果。 安装热力图工具 pip install pytorch_grad_cam pip install grad-cam# get_params中的参数&#xff1a; # weight&#xff1a; # 模型权重文件&#xff0c;代码默认是yolov8m.pt # c…...

Java数据结构之ArrayList(如果想知道Java中有关ArrayList的知识点,那么只看这一篇就足够了!)

前言&#xff1a;ArrayList是Java中最常用的动态数组实现之一&#xff0c;它提供了便捷的操作接口和灵活的扩展能力&#xff0c;使得在处理动态数据集合时非常方便。本文将深入探讨Java中ArrayList的实现原理、常用操作以及一些使用场景。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨…...

Zadig vs. Jenkins 详细比较

01、Zadig vs. Jenkins&#xff1a;关于时代的选择 最近官方公众号发布了一篇名为 《是时候和 Jenkins 说再见了》的文章&#xff0c;引起了社区的广泛关注和讨论。作为曾经最被广泛使用的持续构建交付工具&#xff0c;Jenkins 的江湖地位似乎被挑战了。评论中有一条被高度点赞…...

航拍无人机像素坐标转世界坐标

一、背景 已知相机参数&#xff08;传感器宽度和高度、图像宽度和高度、焦距、相对航高、像主点坐标 &#xff09;&#xff0c;在给定像素坐标的前提下&#xff0c;求世界坐标&#xff0c;大部分通过AI来实现&#xff0c;不知道哪个步骤有问题&#xff0c;望大家指正 二、代码…...

Linux系统学习——指令二

Linux系统学习——指令二 sed 指令perl 指令rpm 指令rz 和 sz 指令查看文件大小及压缩文件指令使用tar命令&#xff1a;使用zip命令&#xff1a;注意事项&#xff1a; 解压文件指令 sed 指令 使用sed命令&#xff1a;sed -i s/旧内容/新内容/g 文件名&#xff0c;这将会在文件…...

【逻辑回归】和【线性回归】的区别和联系-九五小庞

逻辑回归&#xff08;Logistic Regression&#xff09;和线性回归&#xff08;Linear Regression&#xff09;是两种常用的统计学习和机器学习技术&#xff0c;它们各自具有特定的应用场景和优势。以下是它们之间的主要区别和联系&#xff1a; 定义与目的 线性回归&#xff1a…...

富格林:正视欺诈阻挠交易被骗

富格林指出&#xff0c;在交易的过程中&#xff0c;投资者们就算做了十分的把握&#xff0c;也难免会出现亏损。因此建议新手投资者&#xff0c;在准备投资时一定要做好充分的准备工作&#xff0c;明辨欺诈陷阱&#xff0c;同时学习正规的做单盈利技巧&#xff0c;这才能帮助我…...

如何在WPS中加载EndNote X9插件

如何在WPS中加载EndNote X9插件 步骤1&#xff1a;关闭WPS 确保所有WPS文档和窗口都已关闭。 步骤2&#xff1a;修改文件后缀 打开文件资源管理器&#xff0c;导航到路径&#xff1a;C:\Program Files (x86)\EndNote X9\Product-Support\CWYW。找到文件 Cwyw_X86.dat&#…...

vb.net小demo(计算器、文件处理等/C#也可看)

Demo1&#xff1a;使用窗体控件实现一个简易版计算器 Public Class Form1Private Sub Button_1_Click(sender As Object, e As EventArgs) Handles Button_1.ClickCalSubBox.Text Button_1.TextEnd SubPrivate Sub Button_2_Click(sender As Object, e As EventArgs) Handles …...

【vue3|第8期】深入理解Vue 3 computed计算属性

日期&#xff1a;2024年6月10日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对的地方&#xf…...