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

JVM学习.02 内存分配和回收策略

1、前言

《JVM学习.01 内存模型》篇讲述了JVM的内存布局,其中每个区域是作用,以及创建实例对象的时候内存区域的工作流程。上文还讲到了关于对象存货后,会被回收清理的过程。今天这里就着重讲一下对象实例是如何被清理回收的,以及清理回收的几种算法。

2、再谈引用

JDK1.2版本之后,对引用的概念进行了扩充,分为强引用,软引用,弱引用,虚引用。这4种引用关系强度依次减弱。

2.1、Strongly Reference 强引用

强应用是最传统的”引用“定义。这种引用关系,无论任何情况(包括OOM异常),只要强引用关系还存在,GC就不会回收掉被引用对象

声明方式:

Object object = new Object();

2.2、Soft Reference 软引用

一种相对强引用弱化了一些的引用。比如高速缓存就可以用到软引用。当内存足够时就保留,不够时就回收。其中:

  • 当系统内存充足的时候,不会被回收;

  • 当系统内存不足的时,会将这些对象列进回收范围之中进行第二次回收,如果还是内存不足,才会抛出内存溢出异常。

声明方式:

 SoftReference softReference = new SoftReference<>(obj);

2.3、Weak Reference 弱引用

弱引用的强度比软引用更弱一些。被弱引用关联的对象,生命周期只能到下一次GC。当GC开始工作,无论当前的内存是否够用,都会会受到被弱引用关联的对象。

声明方式:

WeakReference weakReference = new  WeakReference<>(obj);

2.4、Phantom Reference 虚引用

虚引用是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对该对象的生存时间构成影响,也无法通过虚引用来取得一个对象实例。虚引用的作用主要是用来跟踪对象被垃圾回收的状态。

设值虚引用关联的唯一目的,就是在这个对象被回收的时候收到一个系统通知,或是后续添加进一步的操作处理。

声明方式:

PhantomReference phantomReference = new PhantomReference<>(obj, rq);

2.5、各引用小结

  • 强引用:对象不会被回收,出现OOM

  • 软引用:内存不够时才回收(二次清理)

  • 弱引用:只要GC就回收

  • 虚引用:用于检测对象的GC状态

3、如何判断对象“存活”

3.1、引用计数算法

在JVM中专门开辟一块额外的内存空间,专门用来对实例引用进行技数。一个对象如果在JVM中有被别人引用(关联或持有),则计数器+1;反之,则-1。任何时刻只要计数器为0的对象(没有任何指针对其引用),那么他就是不是存活,需要被清理。

这种的技数方式虽然原理简单,效率也很高,且有不错的案例使用。但是依然存在弊端。

看一段代码:

public class GcReferenceCount {public void testGC(){GcObject gcObj1 = new GcObject(); GcObject gcObj2 = new GcObject(); gcObj1.gcObj = gcObj2;gcObj2.gcObj = gcObj1;gcObj1 = null;gcObj2 = null;// 假设这里发生了gcSystem.gc();}
}class GcObject {GcObject gcObj;
}

上述代码,gcObj1和gcObj2互为引用。就算当gcObj1 = null;gcObj = null;那么计数器永远不可能为0,意味着永远不可能被回收。

3.2、可达性分析算法

通过一系列被称为“GC Roots”的根对象作为起始节点集,从这些节点开始根据引用关系向下搜索,搜索过程所走的路径称为“引用链”。如果某个对象到GC Roots间都没有任何的引用链关联,或者说到GC Roots对象不可达的,则证明此对象是内存垃圾。

通过这种方式可以规避引用计数算法存在的相互指向的问题。也是目前GC中默认的分析标记算法。

网上借来的图:

3.3、并发的可达性分析

这里的并发指的是用户线程和GC线程同时工作。

3.2中提到的可达性分析算法用来断定对象是否存活。理论上要求标记的全过程都基于一个保障一致性的快照中才能进行(假设一边在进行链路搜索,一边用户线程又在更改对象引用指向,那么起初搜索过的路径就会存在歧义)。且往往需要标记的对象又是大多数,这时候随着堆变大而等比例的增加STW(停顿)时间,那么也将直接影响整个系统。

为了解决或降低用户线程的停顿,即要搞为什么必须要在一个能保证一致性的快照中才能进行。引入了”三色标记“算法作为工具来辅助推导。这里将对象按照”是否访问过“分成三种颜色:

  • 白色:该对象没有被GC访问过。

  • 黑色:该对象被GC访问过,他是安全存活的,且这个对象所有引用都被扫描过。

  • 灰色:该对象被GC访问过,但这个对象至少存在一个引用还没被扫描过。

关于并发可达性分析算法,可能存在两个问题:

1、原本消亡的对象被错误标记为存活,这个是可以容忍的。只不过产生了一点浮动垃圾而已,等待下次回收就可以了。

2、原本存活的对象被错误标记为消亡,这个可能会导致系统的致命错误。

关于并发出现”对象消失“问题示意图:

同时满足两个条件时,就会出现”对象消失“的问题:

1、赋值器插入一条或多条从黑色对象到白色对象的新引用;

2、赋值器删除了全部从灰色对象到该白色对象的直接或间接引用;

解决方式:

1、增量更新。破坏第一个条件。当黑色对象插入新的指向白色对象的引用时,把这个新的引用记录下来,等并发标记结束之后,再扫描一次这个记录。比如用一个队列记录下来。可以理解为,黑色对象一旦新插入白色对象的引用之后,它就变回灰色对象了。

2、原始快照。破坏第二个条件。当灰色对象要删除指向白色对象的引用时,就把这个要删除的引用记录下来,等并发标记结束之后,再以这个记录里的灰色对象为根,重新扫描一次。

4、内存回收策略

4.1、标记 - 清除算法

标记:标记处所有需要回收的对象(也可以反过来,标记存活的对象)。

清除:在标记完成后,统一回收所有被标记的对象(如果标记的是需要被回收的对象的话,否则反之)。

网上借的图:

主要缺点:

1、执行效率不稳定。如果Java堆中包含大量对象,且其中大部分是需要被回收的。必须进行大量的标记动作,导致执行效率会随着对象数量增加而降低;

2、空间碎片化。标记,清除后会产生大量不连续的内存碎片。空间碎片太多会导致后面大对象分配时无法找到足够的连续空间。

4.2、标记 - 复制算法

将内存分为大小相等的两块空间,每次只使用其中一块。

标记:标记处所有需要回收的对象(也可以反过来,标记存活的对象)。

复制:当其中一块的内存不足时,将存活的对象复制到另一块内存中。然后把这块的对象清理。

网上借的图:

主要缺点:

1、空间利用率低。以空间换时间的做法,造成空间浪费;其间始终有一块内存没有被使用。

2、效率问题。如果对象有大量都是存活的,那么复制的对象很多,效率自然也会低下。

主要优点:

适合大量对象都是短生命周期的。一次性收集后存活对象很少的情况。同时也避免了空间碎片的问题。

4.3、标记 - 整理算法

结合了标记清除和标记复制的优缺点。

标记:标记处所有需要回收的对象(也可以反过来,标记存活的对象)。

整理:当被标记对象需要被清理时,对存活的对象不进行复制,而是统一向一端移动,然后清理掉端边界外部的内存空间。

网上借的图:

主要缺点:

1、效率问题。每次存活对象的移动,都带来大量的内存重新寻址的计算量, 执行效率较低。甚至低于复制算法。

主要优点:

不会造成空间碎片和空间浪费问题。

4.4、分代收集原则

到目前为止,大多数的回收器都遵循分代垃圾收集原则。

新生代:以标记复制算法居多。大部分对象生命周期较短,采用复制算法可以避免一定的空间碎片问题,且效率比较高

老年代:标记清除或标记整理算法。因为对象的存活时间比较长。

5、小结

到这里,讲述了JVM中的内存回收,以及引用如何被垃圾收集器回收的一些算法。对JVM的内存使用更加了解。其实JVM相关内容看过很多次,但是从来没有过系统性的整理,大部分都停留在脑子中。第一次尝试整理这些内容,一方面可以加深自己的印象,另一方面,通过搜索其他的参考资料,可以发现很多以前忽略的地方。或许这个就是写技术博客的魅力吧。虽然千篇一律,但都是自己手敲原创。respect!

参考资料:《深入理解Java虚拟机》第三版

相关文章:

JVM学习.02 内存分配和回收策略

1、前言《JVM学习.01 内存模型》篇讲述了JVM的内存布局&#xff0c;其中每个区域是作用&#xff0c;以及创建实例对象的时候内存区域的工作流程。上文还讲到了关于对象存货后&#xff0c;会被回收清理的过程。今天这里就着重讲一下对象实例是如何被清理回收的&#xff0c;以及清…...

logstash+elasticsearch+Kibana(ELK)日志收集

文章目录一.安装ELK 7.17二.为Elasticsearch设置密码三.配置logstash四.springboot整合logstash五.spring整合Elastic Search一.安装ELK 7.17 不要一股脑执行以下语句,请观察修改要修改的地方 安装logstash # logstash安装docker run -d --name logstash \-p 5043:5043 -p 5…...

今天面试了一个2年Java经验的

今天去面试了一个26岁的程序员&#xff0c;看了简历&#xff0c;2年经验&#xff0c;本科&#xff0c;写得很牛叉。 Spring cloud alibaba全家桶、redis&#xff0c;分布式锁&#xff0c;服务调用&#xff0c;数据库事务&#xff0c;线程&#xff0c;Zookeeper、Dubbo 、Rabbi…...

逻辑覆盖测试用例设计

逻辑覆盖测试用例设计 实验目标 能够依据程序画出程序流程图理解常用覆盖方法的内涵理解常用覆盖方法的强弱关系能够使用常用覆盖方法设计测试用例 背景知识 白盒测试通常采用静态测试方法和动态测试方法开展。动态测试是参照系统需求或测试规则&#xff0c;通过预先设计一…...

面试官:说一下MySQL中的锁机制吧

5. 1MySQL有哪些锁&#xff1f; 为保证数据的一致性&#xff0c;需要对并发操作进行控制&#xff0c;因此产生了锁。同时锁机制也为实现MySQL的各个隔离级别提供了保证。 锁冲突 也是影响数据库并发访问性能的一个重要因素。所以锁对数据库而言显得尤其重要&#xff0c;也更加…...

STL库中list的迭代器实现痛点分析

前文本篇文章准备换个模式&#xff0c;之前都是先详解模拟实现&#xff0c;但是模拟实现的基本逻辑大多数老铁都是明白的&#xff0c;所以我们这次主要讲解STL库中list的独特性&#xff0c;也就是模拟实现中的重难点文末有模拟实现的源码一&#xff0c;list实现的特殊类list实现…...

字符编码对比(GBK、Unicode、UTF-8)

摘要我们在网上能看到各种文字和符号&#xff0c;那么它们是怎么存储和转化的&#xff0c;还有我们常常提及的UTF-8&#xff0c;为什么都要设置这种编码方式&#xff0c;这里就探讨下。字符集字符集&#xff1a;就是各国文字、符号、数字的集合。常见的字符集有&#xff1a;ASC…...

【百面成神】Redis基础11问,你能坚持到第几问

前 言 &#x1f349; 作者简介&#xff1a;半旧518&#xff0c;长跑型选手&#xff0c;立志坚持写10年博客&#xff0c;专注于java后端 ☕专栏简介&#xff1a;纯手打总结面试题&#xff0c;自用备用 &#x1f330; 文章简介&#xff1a;Redis最基础、重要的11道面试题 文章目录…...

十大排序算法极简汇总篇

说明 十大排序算法可以说是每个程序员都必须得掌握的了&#xff0c;如果你们像从 0 详细学习每一篇&#xff0c;那么你们可以看前面的文章。 但是呢&#xff0c;有些人可能已经学过&#xff0c;想要快速复习一下&#xff0c;看看代码怎么写的&#xff0c;那么可以看这篇十大排…...

数据结构笔记

文章目录第一章&#xff1a;数据结构与算法第二章&#xff1a;稀疏数组和队列一 、稀疏sparsearray 数组&#xff08;一&#xff09;案例需求&#xff08;二&#xff09;稀疏数组介绍&#xff08;三&#xff09;应用实列&#xff08;四&#xff09;代码实现二、队列&#xff08…...

web前端框架——Vue的特性

目录 前言&#xff1a; 一.vue 二.特性 1.轻量级 2.数据绑定 3.指令 4.插件 三.比较Angular 、React 、Vue 框架之间的比较 1. Angular Angular的优点&#xff1a; 2. React React 的优点&#xff1a; 3.vue 3.Vue的优点&#xff1a; 前言&#xff1a; 本篇文章…...

提权工具推荐(PEASS-ng、linpeas_linux_amd64、winPEASany_ofs)

介绍 在这里,您可以找到适用于Windows、Linux/Unix*和MacOS的权限提升工具。 这些工具搜索您可以利用的可能的本地权限提升路径,并用漂亮的颜色打印给您,这样您就可以很容易地识别错误配置。 查看book.hacktricks.xyz中的本地Windows权限提升检查表WinPEAS-Windows本地权限…...

Spark - 继承 FileOutputFormat 实现向 HDFS 地址追加文件

目录 一.引言 二.源码浅析 1.RDD.saveAsTextFile 2.TextOutputFormat 3.FileOutputFormat 三.源码修改 1.修改文件生成逻辑 - getRecordWriter 2.允许目录存在 - checkoutputSpecs 3.全部代码 - TextOutputFormatV2 四.追加存储代码实战 五.总结 一.引言 Output d…...

树莓派编程控制继电器及继电器组

目录 一&#xff0c;继电器说明 ● 继电器接口说明 ① 继电器输入端: ② 继电器输出端: 二&#xff0c;树莓派控制继电器 三&#xff0c;树莓派控制继电器组 一&#xff0c;继电器说明 通俗点讲&#xff0c;可以把继电器理解成是一些功能设备的控制开关。 ● LOW&#…...

oracle和mysql的区别

Oracle与MySQL的区别以及优缺点 MySQL的特点 1、性能卓越&#xff0c;服务稳定&#xff0c;很少出现异常宕机&#xff1b; 2、开放源代码无版本制约&#xff0c;自主性及使用成本低&#xff1b; 3、历史悠久&#xff0c;社区和用户非常活跃&#xff0c;遇到问题及时寻求帮助…...

<Linux开发> linux应用开发-之-uart通信开发例程

一、简介 串口全称叫做串行接口&#xff0c;串行接口指的是数据一个一个的按顺序传输&#xff0c;通信线路简单。使用两条线即可. 实现双向通信&#xff0c;一条用于发送&#xff0c;一条用于接收。串口通信距离远&#xff0c;但是速度相对会低&#xff0c;串口是一种很常用的工…...

基于深度学习的安全帽检测系统(YOLOv5清新界面版,Python代码)

摘要&#xff1a;安全帽检测系统用于自动化监测安全帽佩戴情况&#xff0c;在需要佩戴安全帽的场合自动安全提醒&#xff0c;实现图片、视频和摄像头等多种形式监测。在介绍算法原理的同时&#xff0c;给出Python的实现代码、训练数据集&#xff0c;以及PyQt的UI界面。安全帽检…...

Linux - 进程控制(进程替换)

0.引入创建子进程的目的是什么&#xff1f;就是为了让子进程帮我执行特定的任务让子进程执行父进程的一部分代码如果子进程想执行一个全新的程序代码呢&#xff1f; 那么就要使用进程的程序替换为什么要有程序替换&#xff1f;也就是说子进程想执行一个全新的程序代码&#xff…...

Java中 ==和equals的区别是什么?

作用&#xff1a; 基本类型&#xff0c;比较值是否相等引用类型&#xff0c;比较内存地址值是否相等不能比较没有父子关系的两个对象equals()方法的作用&#xff1a; JDK 中的类一般已经重写了 equals()&#xff0c;比较的是内容自定义类如果没有重写 equals()&#xff0c;将…...

Linux(网络基础---网络层)

文章目录0. 前言1. IP协议1-1 基本概念1-2 协议头格式2. 网段划分2-1 基本概念2.2 IP地址分五大类2-3 特殊的IP地址2-4 IP地址的数量限制2-5 私有IP地址和公网IP地址2-6 路由0. 前言 前面我们讲了&#xff0c;应用层、传输层&#xff1b;本章讲网络层。 应用层&#xff1a;我…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

R语言速释制剂QBD解决方案之三

本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

Vue 3 + WebSocket 实战:公司通知实时推送功能详解

&#x1f4e2; Vue 3 WebSocket 实战&#xff1a;公司通知实时推送功能详解 &#x1f4cc; 收藏 点赞 关注&#xff0c;项目中要用到推送功能时就不怕找不到了&#xff01; 实时通知是企业系统中常见的功能&#xff0c;比如&#xff1a;管理员发布通知后&#xff0c;所有用户…...

PH热榜 | 2025-06-08

1. Thiings 标语&#xff1a;一套超过1900个免费AI生成的3D图标集合 介绍&#xff1a;Thiings是一个不断扩展的免费AI生成3D图标库&#xff0c;目前已有超过1900个图标。你可以按照主题浏览&#xff0c;生成自己的图标&#xff0c;或者下载整个图标集。所有图标都可以在个人或…...