• 【黑马程序员JVM学习笔记】03.垃圾回收


    3.1、如何判断对象可以回收

    Java 堆是垃圾收集器管理的主要区域,因此也被称作GC 堆(Garbage Collected Heap)

    引用计数法

    给对象中添加一个引用计数器,每当有一个地方引用它,计数器就加 1;当引用失效,计数器就减 1;任何时候计数器为 0 的对象就是不可能再被使用的。

    这个方法实现简单,效率高,但是目前主流的虚拟机中并没有选择这个算法来管理内存,其最主要的原因是它很难解决对象之间相互循环引用的问题。

    在这里插入图片描述
    可达性分析算法

    • Java虚拟机中的垃圾回收器采用可达性分析来探索所有存活的对象
    • 扫描堆中的对象,看是否能够沿着GCRoot对象为起点的引用链找到该对象,找不到,表示可以回收
    • 哪些对象可以作为 GC Root?

    这个算法的基本思想就是通过一系列的称为 “GC Roots” 的对象作为起点,从这些节点开始向下搜索,节点所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连的话,则证明此对象是不可用的,需要被回收。

    下图中的 Object 6 ~ Object 10 之间虽有引用关系,但它们到 GC Roots 不可达,因此为需要被回收的对象。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I8KteIf9-1663585354114)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/07cca0a4-6a62-4d17-a36c-0aa8a7b4cfdf/Untitled.png)]

    哪些对象可以作为 GC Roots 呢?

    • 虚拟机栈(栈帧中的本地变量表)中引用的对象
    • 本地方法栈(Native 方法)中引用的对象
    • 方法区中类静态属性引用的对象
    • 方法区中常量引用的对象
    • 所有被同步锁持有的对象

    对象可以被回收,就代表一定会被回收吗?

    即使在可达性分析法中不可达的对象,也并非是“非死不可”的,这时候它们暂时处于“缓刑阶段”,要真正宣告一个对象死亡,至少要经历两次标记过程;可达性分析法中不可达的对象被第一次标记并且进行一次筛选,筛选的条件是此对象是否有必要执行 finalize 方法。当对象没有覆盖 finalize 方法,或 finalize 方法已经被虚拟机调用过时,虚拟机将这两种情况视为没有必要执行。

    被判定为需要执行的对象将会被放在一个队列中进行第二次标记,除非这个对象与引用链上的任何一个对象建立关联,否则就会被真的回收。

    • Object 类中的 finalize 方法一直被认为是一个糟糕的设计,成为了 Java 语言的负担,影响了 Java 语言的安全和 GC 的性能。JDK9 版本及后续版本中各个类中的 finalize 方法会被逐渐弃用移除。忘掉它的存在吧!

    四种引用

    强引用、软引用、弱引用、虚引用、终结器应用

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8mxnfuJ3-1663585354115)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/82ad3f17-0bb8-41cc-bed6-4b13b42a782f/Untitled.png)]

    强引用:只有所有GC Roots对象都不通过【强引用】引用该对象,该对象才能被垃圾回收;

    软引用:

    • 仅有软引用引用该对象时,在垃圾回收后,内存仍不足时会再次触发垃圾回收,回收软引用对象
    • 可以配合引用队列来释放弱引用自身

    弱引用:

    • 仅有弱引用引用该对象时,在垃圾回收时,无论内存是否充足,都会回收弱引用对象
    • 可以配合引用队列来释放弱引用自身

    虚引用:

    • 必须配合引用队列使用,主要配合ByteBuffer引用。被引用对象回收时,会将虚引用入队,由Reference Handler线程调用相关方法释放直接内存

    终结器引用

    • 无需手动编码,但其内部配合引用队列使用,在垃圾回收时,终结器引用入队(被引用对象暂时没有被回收),再由Finalizer线程通过终结器引用找到被引用对象并调用它的finalize方法,第一次GC时才能回收被引用对象

    3.2、垃圾回收算法

    标记清除
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vRNQJj4V-1663585354116)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/c73a295e-77fb-4f38-b8f1-dbe6617757ed/Untitled.png)]

    标记整理
    在这里插入图片描述

    复制

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5ot9auJT-1663585354119)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/894f0769-e215-4080-b4fb-3a9b425b57e4/Untitled.png)]
    总结:
    标记清除

    • 速度快
    • 会造成内存碎片

    标记整理

    • 速度慢
    • 没有内存碎片

    复制

    • 不会有内存碎片
    • 需要占用双倍内存空间

    3.3、分代垃圾回收

    现在收集器基本都采用分代垃圾收集算法
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lZgF2UE3-1663585354120)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/bc75a4a6-5aa0-45e0-a20b-e9de9267f03e/Untitled.png)]

    • 对象首先分配在伊甸园区域
    • 新生代空间不足时,触发minor gc,伊甸园和from存活的对象使用copy复制到to中,存活的对象年龄加1并且交换from to
    • minor gc 会引发stop the world,暂停其他用户的线程,等垃圾回收结束,用户线程才恢复运行
    • 当对象寿命超过阈值时,会晋升至老年代,最大寿命是15(4bit)
    • 当老年代空间不足,会先尝试触发minor gc,如果之后空间仍不足,那么触发full gc,STW的时间更长

    相关VM参数

    参数含义
    堆初始化-Xms
    堆最大大小-Xmx 或 -XX:MaxHeapSize=size
    新生代大小-Xmn 或 (-XX:NewSize=size + -XX:MaxNewSize=size )
    幸存区比例(动态)-XX:InitialSurvivorRatio=ratio 和 -XX:+UseAdaptiveSizePolicy
    幸存区比例-XX:SurvivorRatio=ratio
    晋升阈值-XX:MaxTenuringThreshold=threshold
    晋升详情-XX:+PrintTenuringDistribution
    GC详情-XX:+PrintGCDetails -verbose:gc
    FullGC 前 MinorGC-XX:+ScavengeBeforeFullGC

    3.4、垃圾回收器

    1. 串行
    • 单线程
    • 堆内存较小,适合个人电脑
    1. 吞吐量优先
    • 多线程
    • 适合堆内存较大,多核CPU
    • 让单位时间内,STW的时间最短0.2 0.2=0.4,垃圾回收时间占比最低,这样就称吞吐量高
    1. 响应时间优先
    • 多线程
    • 堆内存较大,多核CPU
    • 尽可能让STW的时间最短0.1 0.1 0.1 0.1 0.1=0.5

    串行

    -XX:+UseSerialGC=Serial+SerialOld
    在这里插入图片描述

    吞吐量优先

    -XX:+UseParallelGC ~ -XX:+UseParallel0ldGC
    -XX:+UseAdaptiveSizePolicy
    -XX:GCTimeRatio=ratio
    -XX:MaxGCPauseMillis=ms
    -XX:ParallelGCThreads=n
    在这里插入图片描述

    响应时间优先

    XX:+UseConcMarkSweepGC ~ -XX:+UseParNewGC ~ Serial0ld
    -XX:ParallelGCThreads=n ~-XX:ConcGCThreads=threads
    -XX:CMSInitiatingOccupancyFraction=percent
    -XX:+CMSScavengeBeforeRemark
    在这里插入图片描述

    G1

    定义:Garbage First

    略(以后再补充)

    3.5、垃圾回收调优

    预备知识:

    • 掌握GC相关的VM参数,会基本的空间调整
    • 掌握相关工具
    • 明白一点:调优跟应用、环境有关,没有放之四海而皆准的法则

    调优领域

    • 内存
    • 锁竞争
    • CPU占用
    • io

    确定目标

    • 【低延迟】还是【高吞吐量】,选择合适的回收器
    • CMS,G1,ZGC
    • ParallelGC
    • Zing

    最快的GC是不发生GC

    查看FullGC前后的内存占用,考虑下面几个问题

    • 数据是不是太多?
      • resultSet=statement.executeQuery(”select *from 大表 limit n”)
    • 数据表示是否太臃肿
      • 对象图
      • 对象大小 16 Integer 24 int 4
    • 是否存在内存泄漏
      • static Map map=
      • 第三方缓存实现

    新生代调优

    • 新生代的特点:

      • 所有的new操作的内存分配非常廉价
        • TLAB thread-local allocation buffer
      • 死亡对象的回收代价是零
      • 大部分对象用过即死
      • Minor GC的时间远远低于Full GC
    • ·越大越好吗?
      -Xmn
      Sets the initial and maximum size (in bytes) of the heap for the young generation (nursery).GC is performed in this region more often than in other regions. If the size for the young generation is too small, then a lot of minor garbage collections are performed. If the size is too large, then only full garbage collections are performed, which can take a long time to complete. Oracle recommends that you keep the size for the young generation greater than 25% and less than 50% of the overall heap size.

    • 新生代能容纳所有【并发量*(请求-响应)】的数据

    • 幸存区大到能保留【当前活跃对象+需要晋升对象】

    • 晋升阈值配置得当,让长时间存活对象尽快晋升
      -XX:MaxTenuringThreshold=threshold
      -XX:+PrintTenuringDistribution

    Desired survivor size 48286924 bytes, new threshold 10 (max 10)

    • age 1: 28992024 bytes, 28992024 total
    • age 2: 1366864 bytes, 30358888 total
    • age 3: 1425912 bytes, 31784800 total

    老年代调优

    以CMS为例

    • CMS老年代内存越大越好
    • 先尝试不做调优,如果没有Full GC,那么已经…,否则先尝试调优新生代
    • 观察发生Full GC老年代内存占用,将老年代内存预设调大1/4~1/3
      • -XX:CMSInitiatingOccupancyFraction=percent

    案例:

    • 案例1 Full GC和Minor GC频繁
    • 案例2请求高峰期发生Full GC,单次暂停时间特别长(CMS)
    • 案例3老年代充裕情况下,发生Full GC(CMS jdk1.7)
  • 相关阅读:
    【数据结构初阶-复杂度】运行 只用了3ms...我真牛(得意
    按位运算符、逻辑运算符
    绕过Windows 11安装限制,Rufus带给你“奇迹”,低配电脑的春天
    unity3d客户端框架 基于类对象池的可回收变量 代码实现
    如何清理废弃pv和其对应的文件夹
    「PAT乙级真题解析」Basic Level 1077 互评成绩计算 (问题分析+完整步骤+伪代码描述+提交通过代码)
    知识图谱从入门到应用——知识图谱的存储与查询:基于原生图数据库的知识图谱存储
    Python办公自动化【Word】
    sun.security.validator.ValidatorException: PKIX path building failed
    JDBC操作BLOB类型字段
  • 原文地址:https://blog.csdn.net/qq_55123599/article/details/126939692