深入理解Java虚拟机-GC

深入理解Java虚拟机-GC

当需要排查各种内存溢出、内存泄漏时,当垃圾回收成为系统到达更高并发量的瓶颈时,我们必须对内存动态分配和内存回收技术这样的“自动化”技术采用必要的监控和调节。

Java堆和方法区:一个接口的多个实现类需要的内存可能会不一样,一个方法所执行的不同条件分支所需要的内存也可能不一样,只有处于运行期间,我们才能知道程序究竟会创建哪些对象,创建多少个对象,这部分内存的分配和回收是动态的。

  • 哪些内存需要回收?
  • 什么时候回收?
  • 如何回收?

哪些内存需要回收?

  • 引用计数法 缺点:有很多例外情况要考虑,必须要配合大量额外处理才能保证正确地工作,譬如单纯的引用计数就很难解决对象之间相互循环引用的问题。
可达性分析算法(Java c#)

“GC Roots”的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程所走过的路径称为“引用链”(Reference Chain),如果某个对象到GC Roots间没有任何引用链相连,或者用图论的话来说就是从GC Roots到这个对象不可达时,则证明此对象是不可能再被使用的。
GC Roots

  • 在虚拟机栈(栈帧中本地变量表)中引用的对象
  • 方法区中静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI引用的对象
  • Java虚拟机内部的引用,如基本数据类型对应的Class对象,一些常驻的异常对象。
  • 所有被synchronized 关键字持有的对象
  • 反映Java虚拟机内部情况的JM XBean、JVM TI中注册的回调、本地代码缓存等。
引用
  • 强引用:引用赋值,即类似“Object obj=new Object()”这种引用关系。
  • 软引用:描述还有用,非必须的对象。在JDK 1.2版之后提供了SoftReference类来实现软引用。
  • 弱引用:被弱引用关联的对象只
    能生存到下一次垃圾收集发生为止。当垃圾收集器开始工作,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。在JDK 1.2版之后提供了WeakReference类来实现弱引用。
  • 虚引用:虚引用的存在完全不会影响对象的生命周期。为一个对象设置虚引用关联的唯一目的只是为了能在这个对象被收集器回收时收到一个系统通知。
两次标记
  • 第一次标记:可达性分析标记没有与GC Root相连的引用链的对象。
  • 进行筛选,找出需要执行finalize()方法的对象,放入F-Queue队列,稍后由虚拟机自动建立的、低调度优先级的Finalizer线程去执行它们的finalize()方法。
  • 第二次标记:收集器对F-Queue中的对象进行第二次小规模的标记,如果F-Queue中的对象重新与引用链上的任何一个对象建立关联,那么它将被移出“即将回收”的集合。
  • 两次标记都没有逃出“即将回收”的集合,那它基本上就要被回收。
  • tips:finalize()运行代价高昂,不确定性达,无法保证各个对象的调用顺序,不推荐使用。
  • tips:任何一个对象的finalize()方法都只会被系统自动调用一次
回收方法区
  • 方法区垃圾收集的“性价比”较低
  • 方法区垃圾收集主要回收废弃的常量不再使用的类型
  • 没有任何字符串对象引用常量池中的"xxx"常量,且虚拟机中也没有其他地方引用该"xxx"。则,如果在这时发生垃圾回收,且垃圾收集器判断有必要进行回收,则该“xxx"常量将会被清理出常量池。
    判断一个类型是否属于“不再被使用的类”:
  • Java堆中不存在该类及其任何派生子类的实例。该类所有的实例都已经被回收
  • 加载该类的类加载器已经被回收,除了OSGi、JSP的重载等,通常很难达成。
  • 该类对应的java.lang.Class对象没有任何地方被引用,无法通过反射访问该类的方法。

在大量使用反射、动态代理、CGLib等字节码框架,动态生成JSP以及OSGi这类频繁自定义类加载器的场景中,通常都需要Java虚拟机具备类型卸载的能力,以保证不会对方法区造成过大的内存压力。

HotSpot虚拟机参数
  • -Xnoclassgc
  • -verbose: class
  • -XX: +TraceClass-Loading
  • -XX: +TraceClassUnLoading
分代收集理论

分代假说:

  • 弱分代假说
  • 强分代假说
    经验法则:跨代引用假说:跨代引用相对于同代引用来说仅占极少数。
    所以,不应该为了少量的跨代引用去扫描整个老年代,也不必浪费空间专门记录每一个对象是否存在及存在哪些跨代引用。在新生代上建立一个全局数据结构记忆集。记忆集将老年代划分为若干小块,标识老年代的哪一块内存会存在跨代引用。**Minor GC时,**将包含了跨代引用的小块内存中的对象加入到GC Root进行扫描。
Partial GC 部分收集

Minor GC/ Young GC新生代收集
Major GC/Old GC老年代收集,请注意“M ajor GC”这个说法现在有点混淆,在不同资料上常有不同所指,读者需按上下文区分到底是指老年代的收集还是整堆收集。
Mixed GC混合收集:目标是收集整个新生代和部分老年代的垃圾收集,目前只有G1收集器有这钟行为

Full GC 整堆收集

收集整个Java堆和方法区的垃圾收集。

垃圾回收算法

标记-清除 算法
算法分为“标记”和“清除”两个阶段:首先标记出所有需要回
收的对象,在标记完成后,统一回收掉所有被标记的对象,
也可以反过来,标记存活的对象,统一回收所有未被标记的对象。
缺点:
  • 执行效率不稳定,标记和清除两个过程的执行效率都随对象数量增长而降低;
  • 内存空间的碎片化问题。
标记-复制 算法

“半区复制” 缺点:内存空间浪费大。
新生代中的对象有98%熬不过第一轮收集。因此
并不需要按照1∶1的比例来划分新生代的内存空间。

“Appel式回收”:HotSpot虚拟机默认的Eden : Survivor = 8 : 1 。“逃生门”安全设计 – Survivor空间不足以容纳一次Minor GC之后存活的对象时,需要依赖其他内存区域进行分配担保。即,Survivor空间没有足够空间存放上一次新生代收集下来的存活对象,这些对象便将通过分配担保机制直
接进入老年代。

标记-整理 算法

移动式的垃圾回收算法。
优点:解决了弥散于堆中的存活对象导致的
空间碎片化问题。
缺点Stop The World 对象移动操作必须全程暂停用户应用程序才能进行。

HotSpot虚拟机里面关注吞吐量的Parallel
Scavenge收集器是基于标记-整理算法的,而关注延迟的CM S收集器则是基于标记-清除算法的。

HotSpot

根节点枚举
  • Stop The World ,枚举根节点时必须要暂停用户线程。
  • OopMap数据结构的协助下,HotSpot可以快速准确地完成GC Roots枚举 类加载动作完成时,HotSpot会把对象内什么偏移量上是什么类型的数据计算出来,在即时编译过程中,会在特定的位置记录下栈里和寄存器里哪些位置是引用。收集器在扫描时就可以直接得知这些信息,不需要真正一个不漏地从方法区等GC Roots开始查找。
安全点 Safepoint

用户程序强制要求必须执行到达安全点后才能够停顿下来进行垃圾回收

安全点的选定既不能太少以至于让收集器等待时间过长,也不能太过频繁以至于过分增大运行时的内存负荷。
  • 安全点以“是否具有让程序长时间执行的特征”为标准进行选定。
如何让所有线程都跑到最近的安全点?
  • 抢先式中断:在垃圾收集发生时,系统首先把所有用户线程全部中断,如果发现有用户线程中断的地方不在安全点上,就恢复这条线程执行,让它一会再重新中断,直到跑到安全点上。
  • 主动式中断:当垃圾收集需要中断线程的时候,不直接对线程进行操作。设置一个标志位,各个线程在执行的过程中会不断地轮询这个标志,线程发现标志为真时,就会在最近的安全点上中断挂起。
安全区域

解决户线程处于Sleep状态或者Blocked状态时,线程无法响应虚拟机的中断请求,不能再走到安全的地方去中断挂起自己,虚拟机也显然不可能持续等待线程重新被激活分配处理器时间的问题。

  • 用户线程执行到安全区域里面的代码
  • 用户线程标志自己进入安全区域
  • 虚拟机发起垃圾收集,不关已声明自己在安全区域的线程
  • 线程要离开安全区域时,检查虚拟机是否已经完成了根节点枚举(或者垃圾收集过程中其他需要暂停用户线程的阶段)
  • 如果完成了,那线程就当作没事发生过,继续执行;
  • 否则它就必须一直等待,直到收到可以离开安全区域的信号为止。
记忆集与卡表

跨代引用的问题

  • 记忆集是一钟用于记录从非收集区域指向收集区域的指针集合的抽象数据结构
  • 记忆粒度: 字长精度;对象精度;卡精度
  • 卡表:卡表就是记忆集的一种具体实现,它定义了记忆集的记录精度、与堆内存的映射关系等。卡表最简单的形式可以只是一个字节数组。字节数组CARD_TABLE的每一个元素都对应着其标识的内存区域中一块特定大小的内存块,这个内存块被称作“卡页”。
  • 只要卡页内有一个(或更多)对象的字段存在着跨代指针,那就将对应卡表的数组元素的值标识为1,称为这个元素变脏(Dirty),没有则标识为0。
  • 在垃圾收集发生时,只要筛选出卡表中变脏的元素,就能轻易得出哪些卡页内存块中包含跨代指针,把它们加入GC Roots中一并扫描。
写屏障 -XX: +UseCondCardMark 决定是否开启卡表更新的条件判断

写屏障可以看作在虚拟机层面对“引用类型字段赋值”这个动作的AOP切面

  • 写前屏障
  • 写后屏障
    写后屏障更新卡表
  • 伪共享问题现代中央处理器的缓存系统中是以缓存行(Cache Line)为单位存储的,当多线程修改互相独立的变量时,如果这些变量恰好共享同一个缓存行,就会彼此影响(写回、无效化或者同步)而导致性能降低。
并发的可达性分析

对象消失问题:把原本存活的对象错误标记成已消亡。

对象按照“是否访问过”这个条件标记成以下三种颜色
  • 白色: 表示对象尚未被垃圾收集器访问过。若在分析结束的阶段,仍然是白色的对象,即代表不可达。
  • 黑色: 表示对象已经被垃圾收集器访问过,且这个对象的所有引用都已经扫描过。
  • 灰色:表示对象已经被垃圾收集器访问过,但这个对象上至少存在一个引用还没有被扫描过。
对象消失的两个条件
  • 赋值器插入了一条或多条从黑色对象到白色对象的新引用;
  • 赋值器删除了全部从灰色对象到该白色对象的直接或间接引用。
对象消失问题的两个解决方案
  • 增量更新 黑色对象一旦新插入了指向白色对象的引用之后,就把它变回灰色对象。
  • 原始快照 无论引用关系删除与否,都会按照刚刚开始扫描那一刻的对象图快照来进行搜索。
    写屏障实现
经典垃圾收集器
图3-6展示了七种作用于不同分代的收集器,如果两个收集器之间存在连线,就说明它们可以搭配使用
图中收集器所处的区域,则表示它是属于新生代收集器抑或是老年代收集器。

在这里插入图片描述

Serial、 ParNew、Parallel Scavenge、Serial Old、Parallel Old
  • Serial收集器:它进行垃圾收集时,必须暂停其他所有工作线程,直到它收集结束。HotSpot虚拟机运行在客户端模式下的默认新生代收集器。简单而高效、内存消耗最小、没有线程交互的开销,专心做垃圾收集自然可以获得最高的单线程收集效率。

  • ParNew erial收集器的多线程并行版本, 加粗除了Serial收集器外,目前只有它能与CMS收集器配合工作。

  • 可以使用-XX:ParallelGCThreads参数来限制垃圾收集的线程数
    在这里插入图片描述

  • Parallel Scavenge收集器“吞吐量优先收集器” CM S等收集器的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间,而Parallel Scavenge收集器的目标则是达到一个可控制的吞吐量。而高吞吐量则可以最高效率地利用处理器资源,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的分析任务。控制最大垃圾收集停顿时间的-XX:M axGCPauseM illis参数以及直接设置吞吐量大小的-XX:GCTimeRatio参数。

  • Serial Old是Serial收集器的老年代版本

  • Parallel Old是Parallel Scavenge收集器的老年代版本,支持多线程并发收集,基于标记-整理算法实现。“吞吐量优先”收集器终于有了比较名副其实的搭配组合,在注重吞吐量或者处理器资源较为稀缺的场合,都可以优先考虑Parallel Scavenge加Parallel Old收集器这个组合。

CMS Concurrent M ark Sweep [标记-清除算法]

目标:获取最短回收停顿时间
在这里插入图片描述

  • 初始标记 Stop The World 标记一下GC Roots能直接关联到的对象
  • 并发标记 从GC Roots的直接关联对象开始遍历整个对象图
  • 重新标记 Stop The World 修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录
  • 并发清除 清理删除掉标记阶段判断的已经死亡的对象,由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。
优点:并发收集,低停顿
缺点:
CMS收集器对处理器资源非常敏感。
  • CM S默认启动的回收线程数是(处理器核心数量
    +3)/4 。 处理器核心数量不足四个时,CMS对用户程序的影响就可能变得很大。可能导致用户程序的执行速度忽然大幅降低。
  • “增量式并发收集器”的CM S收集器变种。单核处理器年代PC机操作系统靠抢占式多任务来模拟多核并行多任务的思想一样。
由于CMS收集器无法处理“浮动垃圾”

浮动垃圾: 出现在标记过程结束以后的垃圾对象。CM S无法在当次收集中处理掉它们,只好留待下一次垃圾收集
时再清理掉。
由于在垃圾收集阶段用户线程还需要持续运行,CM S收集器不能像其他收集器那样等待到老年代几乎完全被填满了再进行收集,必须预留一部分空间供并发收集时的程序运作使用。
要是CM S运行期间预留的内存无法满足程序分配新对象的需要,就会出现一次“并发失败”,这时候虚拟机将不得不启动后备预案:冻结用户线程的执行,临时启用Serial Old收集器来重新进行老年代的垃圾收集。

基于“标记-清除”算法实现的收集器,意味着收集结束时会有大量空间碎片产生。
Garbage First

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[计算机网络实验]头歌 实验二 以太网帧、IP报文分析(含部分分析)

目录 第1关:Wireshark基本使用入门 【实验目的】 【实验环境】 【本地主机、平台虚拟机之间数据传递】 wireshark基本用法】 1、wireshark主界面 2、抓取分组操作 3、Wireshark窗口功能 4、筛选分组操作 【实验操作】 ​编辑 第2关:Ethernet帧…

Leaflet结合Echarts实现迁徙图

效果图如下&#xff1a; <!DOCTYPE html> <html><head><title>Leaflet结合Echarts4实现迁徙图</title><meta charset"utf-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0">…

C++:利用哈希表对unordered系列容器模拟实现

文章目录 unordered容器使用[在长度 2N 的数组中找出重复 N 次的元素](https://leetcode.cn/problems/n-repeated-element-in-size-2n-array/description/) 底层结构初步改造哈希表基本逻辑的实现 最终实现 本篇主要总结unordered系列容器和其底层结构 unordered容器使用 从使…

MYSQL索引使用注意事项

索引使用注意事项&#xff1a; 1.索引列运算 不要在索引列上进行运算操作&#xff0c;否则索引将失效&#xff1b; 2.字符串不加引号 字符串类型使用时&#xff0c;不加引号&#xff0c;否则索引将失效&#xff1b; 3.模糊查询 如果仅仅是尾部模糊匹配&#xff0c;索引将不会失…

使用EasyPlayer播放H.265视频流

使用EasyPlayer播放H.265视频流 EasyPlayer流媒体视频播放器 EasyPlayer流媒体视频播放器 EasyPlayer流媒体视频播放器可支持H.264与H.265编码格式&#xff0c;性能稳定、播放流畅&#xff0c;能支持RTSP、RTMP、HLS、FLV、WebRTC等格式的视频流播放&#xff0c;并且已实现网页…

NEJM一篇新文为例,聊聊孟德尔随机化研究mr 连锁不平衡(linkage disequilibrium)

2019年3月14日&#xff0c;新英格兰医学杂志发表了一篇论著&#xff0c;Mendelian Randomization Study of ACLY and Cardiovascular disease, 即《ACLY和心血管疾病的孟德尔随机化研究》。与小咖在2017年1月9日报道的一篇发表在新英格兰医学的孟德尔随机化研究——精读NEJM&am…

【Python】重磅!这本30w人都在看的Python数据分析畅销书更新了!

Python 语言极具吸引力。自从 1991 年诞生以来&#xff0c;Python 如今已经成为最受欢迎的解释型编程语言。 【文末送书】今天推荐一本Python领域优质数据分析书籍&#xff0c;这本30w人都在看的书&#xff0c;值得入手。 目录 作译者简介主要变动导读视频购书链接文末送书 pan…

【GUI】-- 13 贪吃蛇小游戏之食物及成绩判断

GUI编程 04 贪吃蛇小游戏 4.4 第四步&#xff1a;食物及成绩判断 首先&#xff0c;添加食物与分数的数据定义&#xff1a; //食物的坐标int foodX;int foodY;Random random new Random();//积分面板数据结构int score;在初始化方法中&#xff0c;添加(画出)食物与分数&…

编译 CUDA加速的 OpenCV-4.8.0 版本

文章目录 前言一、编译环境二、前期准备三、CMake编译四、VS编译OpenCV.sln五、问题 前言 由于项目需要用上CUDA加速的OpenCV&#xff0c;编译时也踩了不少坑&#xff0c;所以这里记录一下。 一、编译环境 我的编译环境是&#xff1a; Win10 RTX4050 CUDA-12.0 CUDNN 8.9.…

Windows、VMware问题集合

Windows、VMware问题集合 一. Windows11安装VMware17提升虚拟机性能1. 桌面右击图标点击属性——>兼容性&#xff0c;找到“以管理员身份运行此程序”勾选&#xff0c;最后点击确定即可。2. 关闭win11的内核隔离功能。 二. VMware虚拟机报错&#xff08;虚拟化性能计数器需要…

【人工智能入门学习资料福利】

总目录如下&#xff08;部分截取&#xff09;&#xff1a; 百度网盘链接&#xff1a;https://pan.baidu.com/s/1bfDVG-xcPR3f3nfBJXxqQQ?pwdifu6 提取码&#xff1a; ifu6

【电子通识】USB3.0和USB2.0有什么区别?

版本 USB2.0是2000年4月27日由USB-IF组织提出了USB2.0总线协议规范。 USB3.0是2008年11月17日由USB-IF组织提出了超高速USB3.0规范。 图标对比 USB2.0的标志就是和USB1.1的标志基本上没啥区别&#xff0c;还是以前的那个样子&#xff0c;使用黑色颜色用标识 USB3.0它有一个S…

变态跳台阶,剑指offer

目录 题目&#xff1a; 我们直接看题解吧&#xff1a; 相似题目&#xff1a; 解题方法&#xff1a; 审题目事例提示&#xff1a; 解题思路&#xff1a; 代码实现&#xff1a; 题目地址&#xff1a; 【剑指Offer】9、变态跳台阶 难度&#xff1a;简单 今天刷变态跳台阶&#xf…

不停的挖掘硬盘的最大潜能

从 NAS 上退休的硬盘被用在了监控的存储上了。 随着硬盘使用寿命的接近尾声&#xff0c;感觉就是从高附加值数据到低附加值数据上。监控数据只会保留那么几个月的时间&#xff0c;很多时候都会被覆盖重新写入。 有人问为什么监控数据不保留几年的&#xff0c;那是因为监控数据…

Golang 中的良好代码与糟糕代码

最近&#xff0c;有人要求我详细解释在 Golang 中什么是好的代码和坏的代码。我觉得这个练习非常有趣。实际上&#xff0c;足够有趣以至于我写了一篇关于这个话题的文章。为了说明我的回答&#xff0c;我选择了我在空中交通管理&#xff08;ATM&#xff09;领域遇到的一个具体用…

Apache POI简介

三十二、Apache POI 32.1 介绍 Apache POI 是一个处理Miscrosoft Office各种文件格式的开源项目。简单来说就是&#xff0c;我们可以使用POI在Java程序中对Miscrosoft Office各种文件进行读写操作。 一般情况下&#xff0c;POI都是用于操作Excel文件。 Apache POI 的应用场…

【开源】基于JAVA的开放实验室管理系统

项目编号&#xff1a; S 013 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S013&#xff0c;文末获取源码。} 项目编号&#xff1a;S013&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 实验室类型模块2.2 实验室模块2.3 实…

LeetCode 2304. 网格中的最小路径代价:DP

【LetMeFly】2304.网格中的最小路径代价&#xff1a;DP 力扣题目链接&#xff1a;https://leetcode.cn/problems/minimum-path-cost-in-a-grid/ 给你一个下标从 0 开始的整数矩阵 grid &#xff0c;矩阵大小为 m x n &#xff0c;由从 0 到 m * n - 1 的不同整数组成。你可以…

#gStore-weekly | ​gAnswer源码分析:基于通用数据集的NE、RE服务开发

PART1 简 介 目前基于知识图谱的问答模式有两种&#xff0c;一种是基于信息检索的方式&#xff0c;一种是基于语义分析的方式。前者较之于后者&#xff0c;没有真正关心语义&#xff0c;主要是ranker算法&#xff0c;擅于处理简单问题&#xff0c;后者则是从语义的角度将用户…

数环通入选中国信通院《高质量数字化转型技术方案集(2023)》,积极推动企业数字化转型

近日&#xff0c;中国信息通信研究院“铸基计划”发布《高质量数字化转型技术方案集&#xff08;2023&#xff09;》&#xff0c;数环通《数字化协同管理解决方案》成功入选。 随着科技的快速发展和市场竞争的日益激烈&#xff0c;数字化转型已成为企业持续发展和提升竞争力的关…