JVM-GC 相关知识

问题1:什么是JVM?

问题2:JVM的内存区是如何划分的?(运行时数据区)


JVM 运行时数据区:堆、栈、方法区(JDK8之前是 永久代实现的,之后就是元空间了)、程序计数器。其中堆和方法区是线程共享数据。

在Java虚拟机规范中的描述是:所有的对象实例 以及数组 都要在上分配。

是垃圾回收管理器管理的主要区域。

GC: 垃圾回收机制

1、什么是垃圾回收机制(什么是GC?)

程序在运行的时候会产生大量的内存垃圾,为了确保运行是的性能,JVM在程序运行过程中,不断的进行自动的垃圾回收(GC)。

1.1 什么是"垃圾"?

一些没有引用指向的内存对象都属于内存垃圾,因为这些对象已经无法被访问到了,程序用不了他们了,对程序而言,他们已经死亡。

总结:程序中不再被任何存活对象引用的对象。


2、什么是GC Roots

对象可达性的起点:

  • 虚拟机栈中的局部变量引用
  • 本地方法栈中的JNI引用的对象
  • 方法区中的静态变量引用
  • 方法区中常量引用
  • 所有被同步锁持有的对象
  • JVM内部引用(如系统类加载器)

3、垃圾判定算法

引用计数法(不推荐使用)

  • 原理:每个对象维护一个引用计数器,引用增减时更新计数器。计数器=0时判定为垃圾
  • 缺点:无法解决循环引用问题(A->B ,B->A)。

可达性分析算法

  • 原理:从 GC Roots 出发,遍历所有引用链。不在引用链上的对象即为垃圾。
  • 步骤:
    • 1、枚举所有GC Roots。
    • 2、递归标记所有可达对象
    • 3、清除所有未标记的对象(或将其回收)。

4、垃圾回收算法

标记-清除

  • **过程:**标记存活对象 -> 清除未标记对象。
  • 缺点: 内存碎片化,效率低(需要扫描全堆)
  • **适用场景:**老年代回收(如:CMS的并发标记阶段)

复制算法

  • **过程:**将内存分为两块(如 From / To)。将存活的对象复制到To区 -> 清空From区。
  • **缺点:**内存利用率低(需要保留一半空闲空间)
  • **优点:**无内存碎片、效率高(仅扫描存活对象)
  • **适用场景:**年轻代回收(如:Minor GC )

标记-整理

  • **过程:**标记存活对象 -> 将对象移动到一端 -> 清理边界外的内存
  • **优点:**无碎片。内存利用率高
  • **缺点:**移动对象开销大(需要新引用地址)
  • **适用场景:**老年代回收(如:Serial Old、Parallel Old)。

分代收集(重点)

  • 核心思想:对不同代使用不同算法
    • 年轻代:对象死亡率高 -> 复制算法(高效)
    • 老年代:对象存活率高 -> 标记-清除 或 标记-整理 (减少复制开销)。

5、堆内存模型与分代设计

Young Generation 年轻代

  • Eden 区(伊甸园)
    • 新创建的对象都会分配到Eden区(一些大对象特殊处理)。
  • Survivor(辛存者)
    • From-S0
    • To-S1
  • 分配比例:(Eden)8:(S0)1:(S1)1

Old Generation 老年代

MetaSpace 元空间

  • 以后会出一篇专门的文章说这个事(JDK 8 后元空间 取代了永久代
  • 如果感兴趣可以去了解:什么是永久代、永久代的缺点、永久代被替换的原因、元空间特点、元空间内存查看分析方法(以后的文章也是围绕这几点讲的)

6、核心回收流程(以分代收集为例)

对象分配

  • 新对象 --> Eden区
  • 大对象 --> 直接进入老年代
    • 大对象是我们设置 : -XX:PretenureSizeThreshold

Minor GC 触发条件

  • Eden区满时触发,执行过程
    • 在GC开始的时候,对象只会存在Eden区和名为"From-S0"区,"To-S1"区是空的。
    • 紧接着进行GC,Eden区中所有存活的对象都会被复制到To-S1区,
    • 在From-S0区中仍然存活的对象会根据年龄决定去向: 年龄达到一定值的对象会被移动到老年代中。没有达到阈值的对象会被复制到To-S1区
      • 年龄阈值:XX:MaxTenuringThreshold设置
    • 经过这次GC后,Eden区和From-S0区已经被清空。
    • From-S0 和 To-S1 会交换他们的角色,也就是新的To-S1就是上次GC前的Form-S0,不管怎么样,都会使To-S1是空的。

对象晋升规则

  • 年龄阈值:XX:MaxTenuringThreshold=15(默认)
  • 动态判定:当某年龄对象大小 > Survivor区50% -----> 大于等于该年龄的对象集体晋升

Major GC / Full GC 触发

  • 老年代空间不足
  • 元空间不足
  • 显示调用 System.gc()
相关推荐
tanxiaomi13 小时前
通过HTML演示JVM的垃圾回收-新生代与老年代
前端·jvm·html
_extraordinary_17 小时前
Java JVM --- JVM内存区域划分,类加载,GC垃圾回收
java·开发语言·jvm
羚羊角uou18 小时前
【Linux】多线程创建及封装
jvm
Nᴏsᴛᴀʟɢɪᴀ念19 小时前
多线程奇幻漂流:从单核到多核质变(一)
java·开发语言·jvm·多线程
艾菜籽1 天前
JVM中的垃圾回收机制
java·jvm
꒰ঌ 安卓开发໒꒱1 天前
Java面试-并发面试(一)
java·jvm·面试
讓丄帝愛伱3 天前
Arthas & JVM 性能排查
linux·jvm
铅笔侠_小龙虾4 天前
JVM深入研究--JHSDB (jvm 分析工具)
java·开发语言·jvm
码码哈哈0.05 天前
从“类加载的五个阶段”逐步分析 JVM“ 在每个阶段的内存变化”
jvm
寻星探路5 天前
Java EE初阶启程记04---线程的状态
java·开发语言·jvm·java-ee