• Java基础之jvm2


    三、垃圾回收

    1. 确定对象是否被销毁的方法

    1.1 引用计数算法

    1.1.1 原理

    (1)为对象添加一个引用计数器
    (2)每当对象在一个地方被引用,则该计数器加 1,每当对象引用失效时,计数器减 1。
    (3)当计数器为 0 的时候,就表明该对象没有被引用。

    1.1.2 缺点

    无法处理循环引用的问题。

    1.2 可达性分析算法(jvm采用)

    1.2.1 图在这里插入图片描述

    1.2.2 图解说

    (1)通过 “GC Roots” 的根节点开始,沿着引用链进行搜索。
    (2)绿色部分的对象都在 GC Roots 的引用链上,就不会被垃圾回收器回收,
    (3)灰色部分的对象没有在引用链上,就被判定为可回收对象。

    2.jvm垃圾回收算法

    2.1 标记–清除算法

    对无效的对象进行标记,然后清除。
    在这里插入图片描述

    2.2 复制算法

    把Java 堆分成两块,每次垃圾回收时只使用其中一块,然后把存活的对象全部移动到另一块区域。

    在这里插入图片描述

    2.3 标记–整理算法

    2.3.1 概念

    (1)结合前面两个算法特点
    (2)标记的存活对象移动到堆的一端
    (3)清理存活对象以外的区域

    2.3.2 优缺点

    (1)优点:避免了内存碎片,也不存在堆空间浪费
    (2) 缺点:
    每次进行垃圾回收的时候,都要暂停所有的用户线程;特别是对老年代的对象回收,则需要更长的回收时间,用户体验差。

    3.垃圾收集器

    高效记忆:

    (1)单行程(单线程)的Siri(serial)老(serial old)了,收集信息速度太慢了,于是派来了新( ParNew)的多行程的语音助手来帮忙。
    (2)可是收集量还是不够大,于是又派来了斯克文(Parallel Scavenge)提高收集量,而且和之前派来了老(parallel Old)的一起收集很合拍。
    (3)收集量越来越多累得他们不得不停顿休息。还好西姆斯(CMS)也来帮忙收集了。
    而且他不仅停顿休息少而且收集量也大,只是有一点,收集完比较多碎片化的东西。
    不过他找到朋友G1来帮他解决了这个问
    题。

    3.1 Serial 收集器

    (1)最基础、最悠久的收集器,是一个单线程工作的收集器。
    (2)清理堆空间时,进行 Minor gc 和Full GC,所有的应用线程都会被暂停。
    在这里插入图片描述

    3.2 ParNew 收集器

    (1)是 Serial 收集器的多线程并行版本,同时使用多条线程进行垃圾收集。
    (2)其余包括 Serial 收集器可用的所有控制参数、收集算法、Stop The World、对象分配规则、回收策略等都与 Serial 收集器完全一致。

    在这里插入图片描述

    3.3 Parallel Scavenge 收集器

    (1)新生代收集器,基于标记——复制算法实现,
    (2)能够并行收集的多线程收集器,和 ParNew 非常相似。
    (3)目标则是达到一个可控制的吞吐量(Throughput)。

    备注吞吐量
    a.处理器用于运行用户代码的时间与处理器总消耗时间的比值。
    b.如:虚拟机完成某个任务,用户代码加上垃圾收集总共耗费了 100 分钟,其中垃圾收集花掉 1 分钟,那吞吐量就是 99%。

    3.4 Serial Old 收集器

    Serial 收集器的老年代版本,单线程收集器,使用 “标记-整理算法”。
    在这里插入图片描述

    3.5 Parallel Old 收集器

    是 Parallel Scavenge 收集器的老年代版本,支持多线程并发收集,基于标记-整理算法实现。
    在这里插入图片描述

    3.6 CMS收集器

    Concurrent Mark Sweep

    3.6.1 概念

    (1)目标是为了消除 Parallel 收集器和 Serial 收集器 Full gc 周期中的长时间停顿。
    (2)在 Minor gc 时会暂停所有的应用线程,并以多线程的方式进行垃圾回收。

    在这里插入图片描述

    3.6.2 步骤

    (1)初始标记(CMS initial mark) :

    仅仅标记一下GC Roots能直接关联到的对象,速度很快。

    (2)并发标记(CMS concurrent mark) :

    a.从GC Roots的直接关联对象,开始遍历整个对象图的过程。
    b.这个过程耗时较长但是不需要停顿用户线程,可以与垃圾收集线程一起并发运行;

    (3)重新标记(CMS remark) :

    a.是为了修正并发标记期间,因用户程序继续运作,而导致标记产生变动那一部分对象的标记记录,
    b.这个阶段的停顿时间通常会比初始标记阶段稍长一 些,但也远比并发标记阶段的时间短;

    (4)并发清除(CMS concurrent sweep):

    a.并发清除阶段,清理删除掉标记阶段判断的已经死亡的 对象,
    b.由于不需要移动存活对象,所以这个阶段也是可以与用户线程同时并发的。

    3.7 G1收集器

    3.7.1 概念

    (1)Garbage-First,垃圾优先。
    (2)服务类型收集器,针对配备多核处理器及大容量内存的机器。
    (3)可设置垃圾收集暂停时间,高吞吐量,CPU利用率高。
    (4)G1保留了年轻代和老年代的概念,但不再是物理隔阂了,它们都是(可以不连续)Region的集合,年轻代和老年代会动态变化甚至相互转换。
    (5)重要参数
    a.XX:MaxGCPauseTimeMillis :
    设置GC可以暂停虚拟机的最大时间量。
    默认:停顿时间200ms
    b.-Xmx - 允许虚拟机的最大堆空间。

    在这里插入图片描述

    3.7.2 特点

    (1)并行与并发
    (2)分代收集
    (3)空间整合
    整体:基于标记-整理算法实现
    局部:基于标记-复制算法实现
    (4)可预测的停顿
    G1除了追求低停顿(CMS也是)外,还能建立可预测的停顿时间模型(后台维护的优先列表)

    3.7.3 垃圾收集分类

    3.7.3.1 YoungGC

    (1)初始值只占堆内存5%
    (2)若Eden区回收时间远小于-XX:MaxGCPauseMills设定的值,则增加年轻代的region,继续给新对象存放,不会马上做Young GC。
    (3)若回收时间接近参数 -XX:MaxGCPauseMills设定值,则触发Young GC

    3.7.3.2 MixedGC:混合收集

    (1)老年代的堆占有率达到参数-XX:InitiatingHeapOccupancyPercent设定的值触发
    (2)回收所有的年轻代和部分老年代(根据筛选回收阶段计算优先级后排序)以及大对象区。
    (3)正常情况G1的垃圾收集是先做MixedGC,主要使用复制算法,
    需要把各个region中存活的对象拷贝到别的region里去,
    拷贝过程中如果发现没有足够的空region能够承载拷贝对象就会触发一次Full GC。

    3.7.3.3 Full GC

    停止系统程序,然后采用单线程进行标记、清理、压缩整理,以空闲出来一批Region,来供下一次MixedGC使用,这个过程非常耗时。

    3.7.4 适合场景

    (1)50%以上的堆被存活对象占用
    (2)对象分配和晋升的速度变化非常大:前提是大内存的主机才有优势,否则还不如其他
    (3)垃圾回收时间特别长,超过1秒
    (4)8GB以上的堆内存(建议值)
    共2048个Region,内存太小的话每个Region也很小,很容易就超过Region的一半被识别为超大对象,这样Humongous区东西会很多,反而不能很好的进行GC收集
    (5)停顿时间是500ms以内

    3.8 垃圾收集器总结

    3.8.1 重要概念

    3.8.1.1 jvm参数打印jdk、收集器信息
       -XX:+PrintCommandLineFlags  -version
    
    
    • 1
    • 2
    3.8.1.2 收集器并发与并行

    (1)并发
    是指GC可以在应用程序运行时执行工作,但是G1不能在应用程序运行时执行所有的工作,而且仍然有停止世界的事件。
    (2)并行
    是指一个GC可以使用多个线程来执行其工作。

    3.8.1.3 收集器吞吐量

    吞吐量=用户代码运行时间/(代码运行时间+垃圾收集时间)

    3.8.2 java8默认:Paralle收集器

    3.8.1.1 年轻代:Parallel Scavenge收集器

    (1)使用复制算法,目标是达到一个可控制的吞吐量
    (2)重要参数:XX:UserAdaptiveSizePolicy
    a.该参数激活后,不需要人工的指定新生代大小(-Xmn)、Eden与Surivivor区的比例,晋升老年代对象大小等参数
    b.虚拟机会根据当前系统运行情况,收集性能监控信息,动态调整这些参数,以提供最合适的停顿时间、最大的吞吐量。

    3.8.1.2 老年代:Parallel Old收集器

    (1)使用标记-整理算法,支持多线程并行收集。
    (2)弥补了之前Parallel Scavenge收集器与别的优秀的老年代收集器不搭的情况。

    3.8.3 比较

    (1)内存效率(时间复杂度):复制算法>标记清除算法>标记压缩算法
    (2)内存效率整齐度:复制算法=标记压缩算法>标记清除算法
    (3)内存利用率:标记清除算法=标记压缩算法>复制算法

    在这里插入图片描述

    四、GC

    1.GC类型

    1.1 分类

    (1)Minor GC/Young GC:针对新生代的垃圾收集;
    (2)Major GC/Old GC:针对老年代的垃圾收集。
    (3)Full GC:针对整个 Java 堆以及方法区的垃圾收集。
    在这里插入图片描述

    1.2 Minor GC

    (1)复制算法,收集间隔较短,年轻代堆空间紧张时会触发。
    (2)初次被创建的对象存放在新生代的 Eden 区,当第一次触发 Minor GC,Eden 区存活的对象被转移到 Survivor区 的某一块区域。
    (3)再次触发 Minor GC 的时候,Eden区的对象连同一块 Survivor 区的对象一起,被转移到了另一块 Survivor 区。

    在这里插入图片描述

    1.3 Full GC

    (1)标记整理算法,非常耗时,老年代堆空间满了触发。
    (2)期间会停止所有线程等待 GC 的完成。

    在这里插入图片描述

    2.GC日志

    2.1 GC 日志开启

    在这里插入图片描述

    在这里插入图片描述

    2.2 GC 日志的理解

    在这里插入图片描述

    Full GC 日志:
    在这里插入图片描述

    五、JMM(java内存模型)

    1.概念

    (1) JMM(java内存模型)Java Memory Model,是一个抽象的概念,不是真实存在的
    (2)它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段、静态字段和构成数组对象的元素)的访问方式。
    (3)JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(Main Memory)中,每个线程都有一个私有的本地内存(Local Memory),本地内存中存储了该线程读/写共享变量的副本。
    在这里插入图片描述

    2.JMM内存模型三大特性:

    2.1 原子性

    使用 synchronized 互斥锁来保证操作的原子性

    2.2 可见性:

    (1)volatile

    会强制将该变量自己和当时其他变量的状态都刷出缓存。

    (2)synchronized

    对一个变量执行 unlock 操作之前,必须把变量值同步回主内存。

    (3)final

    被 final 关键字修饰的字段在构造器中一旦初始化完成,并且没有发生 this 逃逸(其它线程通过 this 引用访问到初始化了一半的对象),那么其它线程就能看见 final 字段的值。

    2.3 有序性

    (1)源代码 -> 编译器优化的重排 -> 指令并行的重排 -> 内存系统的重排 ->最终执行的命令。
    (2)重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。
    (3)处理器在进行重排时必须考虑数据的依赖性,多线程环境线程交替执行,由于编译器优化重排的存在,两个线程中使用的变量能否保证一致性是无法确定的。


    上一篇跳转—Java基础之jvm1                 下一篇跳转—Java基础之jvm3


    参考链接1

    参考链接2


    随心所往,看见未来。Follow your heart,see night!

    *欢迎点赞、关注、留言,收藏及转发,一起学习、交流!

  • 相关阅读:
    uni-app h5、app模式下集成turn.js 翻书动画
    css3 函数汇总(笔记)
    Spring @Valid @Validated实现验证的方法
    2023-09-14力扣每日一题
    源码安装nginx及其配置
    什么是VHDL?一文带你了解VHDL语言
    java基础面试:继承、final关键字、抽象类、接口
    面试算法14:字符串中的变位词
    实验模拟TCP连接的各种异常情况(三次握手丢包,两端异常)
    工业控制系统面临的安全问题分析
  • 原文地址:https://blog.csdn.net/qq_45738250/article/details/126358506