深入解析JVM内存结构与垃圾回收机制

java是强类型高级语言
JVM(Java Virtual Machine,Java虚拟机)是Java平台的核心组件,它是一个虚拟的计算机,能够执行Java字节码(bytecode)。

1、区域划分

JVM对Java内存的管理也是分区分块进行,方便管理。

这一部分称之为
运行时数据区域
这个区域也可以进行细分
区域a:线程私有,对别的线程不可见
        栈——存储方法调用和局部变量
                本地方法栈——用于本地方法的存储,本质上和虚拟机栈没有 区别(很多虚拟机都将二者一起管理)
        本地方法(Native Method) 是指由非 Java 语言(如 C、C++ 等)实现,并通过 Java 虚拟机(JVM)调用的方法。它的作用是让 Java 代码能够与底层系统或硬件交互,弥补 Java 语言在性能或系统级操作上的局限性。
                虚拟机栈——存储方法的局部变量,出口等一系列数据(栈帧)
程序计数器——指向线程正在执行的字节码行号(唯一不会发生OOM(OutOfMemoryError)的区域
区域b:线程共享
        方法区——类信息,常量,静态变量,JDK 8后由元空间(Metaspace)实现,使用本地内存
运行时常量池:方法区的一部分,存放编译期生成的各种字面量和符号引用
        堆(最大)——为对象和数组分配内存的地方,CG主要管理的区域

2、对象的组成

创建对象和销毁对象的过程是什么
2.1 分配内存给对象的方式
都采用循环CAS策略进行并发情况下的差错避免
假如内存是规整的:指针碰撞,移动指针分配空间即可,但当某块内存被回收后需要对当前内存进行整理
假如内存是不规整:建立空闲列表,需要挑选一个合适大小的空间分配,但会出现大量的空间碎片
TLAB:考虑到对象的创建是一个十分频繁的内容,指针争夺和CAS要大量进行,所以每个线程提前分配一块内存,以减少争夺指针的次数,这个叫本地线程分配缓存(Thread Local Allocation Buffer,TLAB),分配后初始化为零值。
2.2 对象的内存布局
对象头
MarkWord标记字——存储对象信息,是一个动态定义的数据结构。会有不同的标志位,不同标志位代表后续存储的内容不同
指向对象类型的指针——表明对象类型
如果对象是数组时,会额外存储数组长度
实例数据
private string name等的和对象相关信息,就是实例数据。可以存基本类型也可以存地址指针。
对齐填充
填充到要求大小
2.3对象的访问方式
我们的Java程序会通过栈上的reference数据来操作堆上的具体对象。
使用句柄
reference中存储的就是对象的句柄地址,句柄中包含了对象实例数据与类型数据各自具体的地址信息,栈——>句柄池——>实例池&方法区
直接指针
reference中存储的直接就是对象地址,栈——>堆——>方法区
  • 使用句柄来访问的最大好处就是reference中存储的是稳定句柄地址,对象位置发生移动时,只需要修改句柄地址,不需要修改reference
  • 直接指针来访问最大的好处就是速度更快,它节省了一次指针定位的时间开销,但在大量访问的情况下这个好处可以被忽略

3.垃圾收集

3.1 哪些是垃圾?
判断生死
脑门刻字法(引用计数法):引用指向该对象——>计数+1
引用断开指向该对象——>计数-1,为0就回收,但单纯的引用计数就很难解决对象之间相互循环引用的问题。
平地长树法(可达性分析):现行虚拟机使用的主要方式。从CGRoot开始向下搜索,不可达的对象被判定为可回收对象。
GC Roots的对象包括以下几种:虚拟机栈中的对象、方法区静态属性引用的对象、方法区常量引用的对象、本地方法栈引用的对象、虚拟机内部对象、同步锁持有的对象,还有一些会被临时加入
引用类型
        强引用:在代码中普遍存在的引用赋值
        软引用:还有用但非必须可以作为缓存使用
        弱引用:可以作为缓存,被下一次垃圾回收回收
        虚引用
3.2 怎样回收?
分代收集理论
JVM会把性质类似的对象放在一起集中管理
弱分代假说
        不需要分代,因为大部分对象死的都很快
强分代假说
        需要分代,获得时间越长的对象越倾向于活下去
把Java堆划分为不同的区域,回收对象根据年龄划分:新生代、老年代。
新生代的回收频率要高于老年代。
跨代引用假说
        相对于同代引用仅占极少数。新生代引用老年代。老年代引用新生代。这种情况下会在被老年代引用的新生代上做标记(记忆集),标记出该新生代被哪个老年代的区域引用,此时把老年代的那一内存小块放入CGRoot中进行扫描(CGRoot的特殊部分
3.3 收集算法
标记-清除算法
        算法简单,但缺点明显:空间碎片问题,stop the world问题这要求用户线程完全停止。
空间碎片化的解决方式:
标记-复制算法
         划分为AB区域,左右复制删除清空,仅适用于收集效率高的场合(朝生夕死),并且只有一半的有效空间。(适用于新生代
        标记复制优化——划分为三个区域:Eden区(8)Survivor区(From/To)(1)
标记-整理算法
        把存活的部分集中在前部,清除后部分的。没有空间碎片,但是需要移动对象
3.4 HotSpot算法实现细节
根节点枚举
我们通过OopMap来实现根节点枚举,让虚拟机在扫描时就直接得到根节点的信息,它的核心作用是让垃圾回收器快速准确地识别栈和寄存器中哪些位置包含指向对象的引用(即 "对象指针")。
遍历oopmap即可搜集到根节点
安全点
OopMap 与安全点紧密相关,安全点是程序执行过程中可以暂停并执行 GC 的位置,每个安全点都关联一个 OopMap。
安全点位置的选取基本上是以“是否具有让程序长时间执行的特征”为标准进行选定的。(方法调用,循环跳转,异常跳转等指令序列复用
如何在垃圾收集时,让所有线程都跑到安全点?
抢占式中断-先中断所有线程,不能中断时恢复。不好
主动式中断-借助标志
安全区域
安全区域是指能够确保在某一段代码片段之中,引用关系不会发生变化,因此,在这个区域中任意地方开始垃圾收集都是安全的。
记忆集与卡表
记忆集:所有涉及部分区域收集行为的垃圾收集器中,用于记录从非收集区域指向收集区域的指针集合的抽象数据结构
记忆集有三种精度:字长精度、对象精度、卡精度
卡精度——卡表实现,卡页内存有跨代指针,标志位置1,此时该卡表”变脏“,只需遍历变脏卡页就可得到区域。
写屏障
HotSpot通过写屏障维护卡表状态。这是对引用对象赋值的一个环形通知(细分为写前、写后屏障)
3.5并发的可达性分析
基于一个保持一次性快照——对象引用关系不可改变
三色标记:
        黑:已经被垃圾收集器放问过,且所有引用已经被扫描
        白:尚未被标记
        灰:已经被垃圾收集器放问过,且有引用未被扫描
        由于这个过程会和用户进程并发进行,此时会有浮动垃圾的产生和引用被误删的情况:当同时满足 1 赋值器插入了一条或多条从黑色对象到白色对象的新引用,2 赋值器删除了全部从灰色对象到该白色对象的直接和间接引用
解决方案:
        增量更新:破坏1
        原始快照:破坏2
3.6常见的收集器
Serial收集器
        新生代标记-复制,老年代标记-整理
ParNew收集器
        是Serial收集器并发版本。新生代标记-复制,老年代标记-整理
Parallel Scavenge收集器
        标记-复制法目标是达到一个可控制的吞吐量
Serial Old收集器
        标记-整理法。它作为CMS发生失败的后备预案,在并发收集发生Concurrent Mode Failure时使用
Parallel Old收集器
        标记-整理算法
CMS(Concurrent Mark Sweep)收集器
        是一种以获取最短回收停顿时间为目标的收集器。基于标记-清除算法实现,整个过程分为四个阶段
        初始标记(stop the world)标记直接关联到的对象,速度很快
        并发标记 遍历整个路径,但可以并发运行
        重新标记(stop the world)
        并发清除 也可以并发运行
其中耗时最长的并发标记和并发清除阶段
有三个明显的缺点:
  1. CMS对处理器资源非常敏感
  2. 由于CMS收集器无法处理“浮动垃圾”(产生于标记结束后的垃圾)
  3. CMS运行期间预留内存无法满足新对象分配需要(启动阈值为92%)
  4. 产生空间碎片
GI收集器(Garbage First)
        是一种主要面向服务端应用的垃圾收集器。收集器面向局部收集的设计思路和基于Region的内存布局形式。
        目标是:支持一个在长度为M毫秒的时间段内,花在垃圾收集上的时间不超过N毫秒。
基于Region帮助实现这个目标,把Java内存划分为多个大小相等的区域,采用MixedGC模式,使回收收益最大
        内存碎片问题不严重,但内存负载较高
3.7低延迟垃圾收集器
衡量垃圾收集器的三项最重要的指标是:
        内存占用(Footprint)
        吞吐量(Throughput)
        延迟(Latency)
3.8内存分配与回收策略
  • 对象优先在Eden区
  • 大对象直接进老年代
  • 长期存活对象将进入老年代:对象年龄计数器(对象头)
  • 动态年龄判定:动态调整进入老年代的年龄限制
  • 空间分配担保:判断老年代空间是否满足新生代晋升(与历史平均值对比)

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

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

相关文章

Java 流程控制详解:从顺序执行到跳转语句,掌握程序逻辑设计

作为一名Java开发工程师,你一定知道,流程控制(Flow Control) 是编写任何程序的核心。它决定了代码的执行路径、分支走向和循环次数。本文将带你系统梳理 Java中的所有常用流程控制结构,包括:顺序结构分支结…

面试150 环形链表

思路 采用双指针法,slow指针每次走一步,fast指针每次走两步,如果相遇的情况下,slow指针回到开始的位置,此时快慢指针各走一步,当相遇的时候也就是说明链表中有环。 # Definition for singly-linked list. # class ListNode: # def __init…

AI技术正在深度重构全球产业格局,其影响已超越工具属性,演变为推动行业变革的核心引擎。

一、AI如何重塑AI的工作与行业(AI助手领域)能力升级理解与生成:基于LLM(大语言模型),AI能处理开放式问题、撰写报告、翻译代码,替代部分人类知识工作。个性化交互:通过用户历史对话分…

Kafka的无消息丢失配置怎么实现

那 Kafka 到底在什么情况下才能保证消息不丢失呢? Kafka 只对“已提交”的消息(committed message)做有限度的持久化保证。 第一个核心要素是“已提交的消息”。什么是已提交的消息?当 Kafka 的若干个 Broker 成 功地接收到一条…

集成CommitLInt+ESLint+Prettier+StyleLint+LintStaged

代码可读性低代码 代码规范落地难代码格式难统一代码质量低下 配置 ESLint ESLint 是一个用来识别 ECMAScript 并且按照规则给出报告的代码检测工具,使用它可以避免低级错误和统一代码的风格。它拥有以下功能: 查出 JavaScript 代码语法问题。根据配置…

寻找两个正序数组的中位数(C++)

给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。算法的时间复杂度应该为 O(log (mn)) 。示例 1:输入:nums1 [1,3], nums2 [2] 输出:2.00000 解释&#x…

Expected Sarsa 算法的数学原理

🌟 一、Expected Sarsa 算法的数学原理 1. 什么是 Expected Sarsa? Expected Sarsa 是一种基于 时序差分(Temporal Difference, TD)学习 的强化学习算法,用于估计 动作值函数 ( q_{\pi}(s, a) )。它是 Sarsa 算法的一种…

Vue的watch和React的useEffect

参考文章:https://zhuanlan.zhihu.com/p/686329898

idea中合并git分支

1.把本地dev代码合并到本地master代码在提交代码之前,先确保dev和master都拉取了最新的代码都进行了Git->pull了这时候确保Local的第一个分支是master分支,然后选择dev分支 ,鼠标右键-》Merge dev into master这时候会提示 有合并到本地master最新的代…

《Spring 中上下文传递的那些事儿》Part 7:异步任务上下文丢失问题详解

📝 Part 7:异步任务上下文丢失问题详解 在现代 Java 应用中,异步编程已经成为提升性能、解耦业务逻辑的重要手段。无论是使用 CompletableFuture、线程池(ExecutorService)、定时任务(ScheduledExecutorSe…

大语言模型驱动智能语音应答:技术演进与架构革新

在智能客服、电话银行等场景中,用户时常遇到这样的困境:“请描述您的问题...抱歉没听清,请重试...正在为您转接人工”。传统语音应答(IVR)系统受限于规则引擎与浅层语义理解,难以应对复杂多变的自然语言表达…

【Linux】内存管理

要求:1、编写程序,实现如下功能。(1)随机生成 1000000 个 0~1 之间的数;(2)统计分析这些数据,计算均值、方差和分布情况,分布情况按0.01 的步长进行统计;&…

苍穹外卖—day1

文章目录前言一、接口文档导入与生成二、前端环境搭建三、后端环境搭建1. 了解项目结构2. 环境搭建常见问题总结前言 (简要说明笔记的目的:记录搭建过程、关键配置和结构理解) 一、接口文档导入与生成 Apifox 导入 使用工具:https…

基于微信小程序的在线疫苗预约小程序源码+论文

基于微信小程序的在线疫苗预约系统源码论文代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹 分享万套开题报告任务书答辩PPT模板 作者完整代码目录供你选择: 《SpringBoot网站项目》800套 《SSM网站项目》1200套 《小程序项目》600套…

Windows 11 安装过程中跳过微软账户创建本地账户

背景 在 Windows 11 的安装和设置过程中,Microsoft 账号登录是默认的认证方式。然而,在某些情况下,可能需要绕过此步骤以创建本地账户。 微软在 2025 年 3 月推送的 Windows 11 预览版(Build 26120.3653 和 Build 26200.5516&am…

利用DBeaver实现异构数据库数据定时任务同步

1、背景 本需求需要实现抽取KingBaseEs数据库的某几张表数据,定时同步到MySQL中 2、工具准备 2.1 DBeaverEE25.1(必须要企业版,如果用社区版没有定时任务功能) https://dbeaver.io/download/ 2.2 KingBaseEs数据库及驱动 https://www.kingbase.com…

【TCP/IP】1. 概述

1. 概述1. 概述1.1 因特网及技术催生新时代1.1.1 信息化时代1.1.2 关键技术1.1.3 国家战略1.2 网络互联的动机和技术1.2.1 网络互联的动机1.2.2 网络互联技术1.3 因特网的形成和发展1.3.1 国际因特网发展轨迹1.3.2 中国互联网发展1.4 有关因特网的组织机构1.5 请求注解&#xf…

中老年人的陪伴,猫咪与机器人玩具有什么区别?

在人口结构深度老龄化的背景下,中老年群体的精神需求与情感陪伴已成为重要的社会议题。猫咪作为活生生的伴侣动物,与日新月异的智能陪伴机器人,代表了两种截然不同的情感慰藉路径——前者承载着生命互动的温度与责任,后者则彰显了…

day11-微服务面试篇

微服务在面试时被问到的内容相对较少,常见的面试题如下:SpringCloud有哪些常用组件?分别是什么作用?服务注册发现的基本流程是怎样的?Eureka和Nacos有哪些区别?Nacos的分级存储模型是什么意思?R…

昇腾 k8s vnpu配置

参考文档: https://www.hiascend.com/document/detail/zh/mindx-dl/500/AVI/cpaug/cpaug_018.html 此文档实现为NPU910B3卡 主机设置静态虚拟npu 设置虚拟化模式 !本命令只支持再物理机执行,取值为0或1,(如果是在虚拟机内划分vNPU…