0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

JVM入门之关于GC的扩展知识1

jf_78858299 来源:北洋洋洋 作者:北洋 2023-02-10 11:35 次阅读

本章主要是对上一篇文章讲的垃圾回收机制的扩展,垃圾回收其实本身是有很多可以优化的点的,本章就进行对这些优化点进行介绍。

1.GC Roots遍历提升效率

以往做法

当垃圾回收器线程进行GC时, 第一步需要 「找到GC Roots」 ;第二步通过GC Roots进行 「遍历堆中引用GC Roots的对象形成引用链」 ;第三步,将不在引用链中的对象标记进行 「标记」 (需要回收的对象),或者 「标记」 引用链中的对象(需要复制,整理的对象),具体标记哪种对象根据堆中的分代内存不同和采用的垃圾回收算法来确定。

可优化地方以及优化原理

上述过程第二步中遍历堆中引用GC Roots的对象,这部分随着堆内存的越来越大需要的时间也会逐步增长。如果能够提前知道堆中哪部分内存是引用,来判断是否引用GC Roots这样效率是不是会更高一些。

没错,因为之前讲过从Exact VM开始就已经采用了准确式内存管理即知道哪部分内存是引用;而且在即时编译的过程中我也会知道栈中或者寄存器里哪部分内存是引用。这个时候我用一个数据结构来存储这些信息,在第二步中就不需要遍历整个堆了,只需要遍历没有标识引用内存的地方(也就是刚才数据结构中没有存储的信息)。

在HotSpot中使用OopMap这个数据结构来存储这信息,也就是可以显著提高GC Roots遍历的效率,但是在什么位置放这些信息呢?

2.提升了GC Roots遍历效率却不知道怎么安插?

前面提到过通过一个OopMap数据结构能够提升遍历效率,但是OopMap中的数据在不同的地方内容是不一样的(比如每个方法里面我的局部变量表里面的内容可能是不一样的),所以 我为每个指令附近都放一个OopMap

等等,这样未免也太浪费内存了吧~。

没错,所以我们得先办法把它放到合适的地方!嗯没错,我想想: **「这个数据结构的出现是为了优化GC第二步的效率出现的,也就是说只有GC时在放这些数据就行了~。思路找到了,但是什么时候发生GC呢?

发生GC这个时间我不能确定,但是我可以确定的是它遍历堆中内存的时候必须要进行STW【否则如果在标记的过程中堆中引用发生变化就会导致标记结果出错】(2.1中讲解),我指定只有代码中执行执行到某个地方才可以进行STW这样我就可以间接的实现我的目的」** 。

也就是说当GC发生时,只有执行到某个地方才会进行STW,然后我在这个地方附近放上这么一个OopMap的数据结构,然后加快第二步的效率。

「这个某个地方其实名字叫做“safePoint”」 ,顾名思义安全点,只有代码执行到安全点附近才可以进行STW垃圾收集,而只要将OopMap安插到安全点附近就行。

2.1为什么需要STW?

上面提到过:

【否则如果在标记的过程中堆中引用发生变化就会导致标记结果出错】

一,三色标记法

接下来用三色标记法进行解释如果没有STW会发生什么情况:一,先解释三色标记法:

二,没有STW出现的情况

在这里插入图片描述

三,解决方案

上面那种异常情况必须同时满足两个条件:1.灰色对象不引用白色对象 2.黑色读写引用白色对象

因此,只要让其中一个条件不满足即可,因此出现了两种解决方案:1.增量更新:这种方案是让第二个条件不满足,即当黑色对象引用白色对象时,将这个黑色对象保存下来,等扫描结束后,再次取出黑色对象进行扫描,可以简单理解为如果黑色对象引用了百世对象就会被标记为灰色。

2.原始快照:当灰色对象删除白色对象的引用时,将这个灰色对象记录下来,等到扫描结束后,在对这些灰色对象为根进行扫描,简单理解为:不管是否删除与否都会按照第一次刚开始的引用关系图进行扫描。

CMS垃圾回收器采用增量更新来进行并发标记,G1,Shenandoah采用原始快照

3.safePoint我又该放到哪里?

safePoint上面解释过了,但是我该在哪里放置safePoint呢?放的多了会导致GC收集过于频繁增加运行时内存压力,放的少了又会因为堆中不断增加使用的内存而没有及时回收堆里面内存导致垃圾收集器等待时间过长。

这样,我定义一个规则,只有这种**“会让程序长时间运行的指令”**特征我才会进行安插safePoint,但是这个特征“长时间”并没有具体的定义,但是却有“指令序列复用”这样的含义。比如方法调用,循环调整,异常跳转这些,只有这些指令附近才会安插safePoint。

safePoint位置选好了,但是上个问题说过执行到safePoint中需要进行STW,发生GC时,我该如何快速跑到safePoint附近进行STW?还有我这个STW该怎么实现呢?

4.如何实现STW?

首先解释为什么叫做STW,全称“Stop the Word”,因为 「通过GC Roots遍历堆中内存的过程其内存里面的引用关系不能发生变化」 ,所以需要暂停所有的用户线程操作来保障Gc Roots形成的引用链是正确的即待会标记过程不会出错。

让所有线程都暂停,这个“看起来复杂其实并不简单”的操作其实有两种方式处理:一,抢先式中断:

垃圾收集器收集时,系统将所有用户线程都中断。当发现不在safePoint附近的线程时先让他恢复运行直至跑到safePoint附近。这种方式现在几乎没有虚拟机采用这种方式来响应GC。

二,主动式中断:

我不直接对我的用户线程操作,当发生GC时,我给用户线程设立个标志位,用户线程执行的时候不断轮询这个标志位,如果轮询到了那么我将自己中断我自己的运行,由于这种方式是轮询到就立马进行挂起所以将轮询的地方和safePoint的地方重合。

优化

“不断轮询标志位”这句话听起来就很耗时哈哈,那么再虚拟机中是怎么优化的呢?还有轮询之后的操作我自己挂起我自己这个又是怎么实现的?

等等,我不放到下一个问题里面讲了,直接一遍过:

轮询标志位这个操作其实就是一条汇编指令,(对于汇编和JAVA是什么关系,之前也有讲到过,辛苦翻阅前面文章~) 这条汇编指令的意思就是当我轮询到需要中断线程的标志位的时候:我会将其中一个内存页设置为不可读,这会导致产生一个自陷异常信号,异常处理器中接受到后进行主动中断操作。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 编程
    +关注

    关注

    88

    文章

    3558

    浏览量

    93524
  • GC
    GC
    +关注

    关注

    0

    文章

    9

    浏览量

    17073
  • JVM
    JVM
    +关注

    关注

    0

    文章

    157

    浏览量

    12193
收藏 人收藏

    评论

    相关推荐

    电子技术入门维修基础知识

    电子技术入门维修基础知识
    发表于 08-17 20:03

    请问单例对象会被jvmgc时回收吗?

    单例对象会被jvmgc时回收吗?
    发表于 11-09 07:02

    JVM知识点汇总,不看肯定后悔

    JVM知识点汇总,不看肯定后悔
    发表于 11-30 06:13

    看看基于JDK中自带JVM工具的用法

    用到命令,下面围绕一个微服务的启动和运行,来看看基于JDK中自带JVM工具的用法;三、命令行工具1、jps命令jps :虚拟机进程状态工具,该命令在Java环境部署和服务启动查看时经常用到,首先在本地
    发表于 11-16 15:30

    Java:JVM虚拟机的入门知识

    Java开发现在面试越来越难了,进大厂必备的JVM、多线程高并发这都是最基础的知识了,今天我们一起来学习Java虚拟机入门
    的头像 发表于 07-01 11:43 2278次阅读
    Java:<b class='flag-5'>JVM</b>虚拟机的<b class='flag-5'>入门</b><b class='flag-5'>知识</b>

    如何解决JVM解释器导致应用崩溃的bug

    bug 导致在弱内存模型的平台上 Crash。 在分析过程中,涉及到非常多的 JVM 内部知识,比如对象头、GC 复制算法操作、CAS 操作、字节码执行、内存序等,希望对读者有所帮助。本文介绍了一般分析
    的头像 发表于 08-27 09:58 2346次阅读
    如何解决<b class='flag-5'>JVM</b>解释器导致应用崩溃的bug

    关于JVM的调优知识

    最近很多小伙伴跟我说,自己学了不少JVM的调优知识,但是在实际工作中却不知道何时对JVM进行调优。今天,我就为大家介绍几种JVM调优的场景。
    的头像 发表于 09-14 14:54 766次阅读

    一次JVM GC长暂停的排查过程

    在高并发下,Java 程序的 GC 问题属于很典型的一类问题,带来的影响往往会被进一步放大。不管是「GC 频率过快」还是「GC 耗时太长」,由于 GC 期间都存在 Stop The W
    的头像 发表于 01-17 10:08 565次阅读

    JVM入门历代垃圾回收器 1

    很多人经常把这两个搞混,当然笔者刚开始的时候也是傻傻分不清楚。其实只要记住并行说的是GC 线程之间的关系,而并发说的是GC和用户线程之间的关系
    的头像 发表于 02-10 11:29 587次阅读
    <b class='flag-5'>JVM</b><b class='flag-5'>入门</b><b class='flag-5'>之</b>历代垃圾回收器 <b class='flag-5'>1</b>

    JVM入门历代垃圾回收器 2

    很多人经常把这两个搞混,当然笔者刚开始的时候也是傻傻分不清楚。其实只要记住并行说的是GC 线程之间的关系,而并发说的是GC和用户线程之间的关系
    的头像 发表于 02-10 11:29 542次阅读
    <b class='flag-5'>JVM</b><b class='flag-5'>入门</b><b class='flag-5'>之</b>历代垃圾回收器 2

    JVM入门关于GC扩展知识2

    本章主要是对上一篇文章讲的垃圾回收机制的扩展,垃圾回收其实本身是有很多可以优化的点的,本章就进行对这些优化点进行介绍。
    的头像 发表于 02-10 11:35 538次阅读
    <b class='flag-5'>JVM</b><b class='flag-5'>入门</b><b class='flag-5'>之</b><b class='flag-5'>关于</b><b class='flag-5'>GC</b>的<b class='flag-5'>扩展</b><b class='flag-5'>知识</b>2

    JVM入门垃圾回收算法

    根据如何判定对象是垃圾,垃圾回收算法分为两类:1、 「引用计数式垃圾收集」 (判定垃圾是通过引用计数器)别名:直接垃圾收集 2、 「追踪式垃圾收集」 (判定垃圾是通过GC Roots)别名:间接垃圾收集
    的头像 发表于 02-10 11:40 761次阅读
    <b class='flag-5'>JVM</b><b class='flag-5'>入门</b><b class='flag-5'>之</b>垃圾回收算法

    JVM的一些重要参数

    ,默认GC 是G1 GC算法。Java 17 默认也是G1 GC,其中个别版本会有点差异。 下面是常用
    的头像 发表于 09-25 15:56 422次阅读

    JVM知识体系剖析

    从源码到运行、类加载,再到内存分配和垃圾回收,以及JVM调优的技巧与实战。 理论-实战-面试三结合,带大家剖析整个JVM知识体系,一站解决JVM问题。
    的头像 发表于 10-10 11:37 401次阅读
    <b class='flag-5'>JVM</b><b class='flag-5'>知识</b>体系剖析

    从原理聊JVM(一):染色标记和垃圾回收算法

    更好地优化自己的代码,并解决一些潜在的性能问题。 本文及后续文章将从原理聊起,对JVM的内存分配、GC、编译等知识进行分析和总结。 1 JVM
    的头像 发表于 08-20 15:25 164次阅读
    从原理聊<b class='flag-5'>JVM</b>(一):染色标记和垃圾回收算法