Bohr-L Bohr-L
首页
技术
常见面试题
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

刘博

I'm a slow walker, But I never walk backwards.
首页
技术
常见面试题
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 数据处理与存储类

  • Spring 生态类

  • 缓存问题类

  • 多线程类

  • JVM 类

    • JVM 中一次完整的 GC 流程(从 ygc 到 fgc)是怎样的
    • 如何判断对象可以被回收
    • 你知道哪些垃圾收集算法
    • 虚拟机为什么使用元空间替换了永久代
      • 简述 CMS 垃圾收集器的工作流程,它有什么优缺点?
      • 简述一下 JVM 的内存模型
      • 说说堆和栈的区别
      • 简述 Java 的对象结构
      • JVM 中的即时编译器(JIT)如何工作?
      • 什么是内存屏障?JVM 如何使用内存屏障保证指令执行顺序?
      • 如何排查和解决 JVM 内存泄漏问题?有哪些常用的工具和方法?
      • JVM 如何处理异常?try-catch-finally 结构在字节码层面是如何实现的?
    • MySQL 类

    • Java 8 + 特性类

    • 其他技术类

    • 常见面试题
    • JVM 类
    刘博
    2025-12-28
    目录

    虚拟机为什么使用元空间替换了永久代

    在 JDK 8 中,JVM 用元空间(Metaspace) 替代了永久代(Permanent Generation),核心原因是 “解决永久代的内存溢出问题、提升内存管理灵活性、适配 JVM 规范”,具体如下:

    # 1. 永久代的固有问题(核心原因)

    • 1. 容易引发 OOM:PermGen Space:

    永久代的内存大小通过

    -XX:PermSize
    
    1

    (初始大小)和

    -XX:MaxPermSize
    
    1

    (最大大小)固定,若加载的类过多(如 Spring、Hibernate 等框架生成大量动态代理类)、或常量池过大(如大量字符串常量),容易超出

    MaxPermSize
    
    1

    ,抛出

    OutOfMemoryError: PermGen Space
    
    1

    ;

    而元空间的内存默认使用

    本地内存(Native Memory)

    ,本地内存大小受操作系统可用内存限制(而非 JVM 堆内存),大幅降低 OOM 风险。

    • 2. 内存大小难以预估:

    永久代存储类元信息(类结构、方法信息、常量池),类的加载数量和大小受应用影响(如动态类生成、反射频繁的应用),难以提前预估

    MaxPermSize
    
    1

    的合理值;

    若设置过小,易 OOM;若设置过大,会浪费内存(永久代内存无法回收给操作系统,即使类被卸载);

    元空间无需手动设置大小(默认自动扩容),仅在本地内存不足时才会 OOM,内存利用率更高。

    • 3. 类卸载效率低:

    永久代的类卸载条件严格(如类的 ClassLoader 被回收、无对象引用该类),且 JVM 对永久代的 GC 频率低(通常仅在 FGC 时回收),导致大量无用类元信息堆积在永久代,浪费内存;

    元空间的类元信息存储在本地内存,类卸载时可直接释放本地内存,回收效率更高,且元空间的 GC 独立于堆内存 GC(无需等待 FGC)。

    # 2. 元空间的优势(替换后的改进)

    • 1. 内存管理更灵活:

      • 元空间默认使用本地内存,大小无固定上限(可通过-XX:MetaspaceSize和-XX:MaxMetaspaceSize限制),避免永久代的固定大小限制;
      • 当元空间内存不足时,JVM 会自动扩容(从MetaspaceSize开始,每次扩容一定比例),直到达到MaxMetaspaceSize;
      • 当元空间内存充足时,JVM 会自动缩容(释放未使用的本地内存给操作系统),提升内存利用率。
    • 2. 适配 JVM 规范(JSR-292):

    JDK 7 引入的 JSR-292(支持动态类型语言,如 Groovy、Scala)要求 JVM 支持更灵活的类元信息存储;

    永久代的设计基于 “类元信息静态存储”,难以支持动态类生成(如动态代理、Lambda 表达式);

    元空间的设计更符合 JSR-292 规范,可高效存储和管理动态生成的类元信息。

    • 3. 简化 JVM 内存模型:

    永久代属于堆内存的一部分(逻辑上),但存储的是类元信息(非对象),与堆内存的 “对象存储” 职责冲突,导致 JVM 内存模型复杂;

    元空间独立于堆内存,专门存储类元信息,堆内存仅存储对象,使 JVM 内存模型更清晰(堆内存负责对象、元空间负责类元、本地内存负责直接内存)。

    • 4. 提升 GC 效率:

    永久代的 GC 需与老年代 GC 同步(通常在 FGC 时回收),增加 FGC 的 STW 时间;

    元空间的 GC 独立进行(称为 “Metaspace GC”),仅在元空间内存不足时触发,且 STW 时间短(仅需清理无用类元信息),不影响堆内存的 YGC/FGC。

    # 3. 元空间的关键配置参数

    虽然元空间默认无需配置,但可通过以下参数优化:

    • -XX:MetaspaceSize:元空间的初始阈值,当元空间内存达到该值时,触发 Metaspace GC(默认约 21MB);
    • -XX:MaxMetaspaceSize:元空间的最大内存限制,超过该值会抛出OutOfMemoryError: Metaspace(默认无上限,推荐设置为 256MB-1GB,避免本地内存耗尽);
    • -XX:MinMetaspaceFreeRatio:GC 后元空间的最小空闲比例(默认 40%),若空闲比例低于该值,元空间会扩容;
    • -XX:MaxMetaspaceFreeRatio:GC 后元空间的最大空闲比例(默认 70%),若空闲比例高于该值,元空间会缩容。

    # 总结

    元空间替换永久代的核心是 “解决永久代的 OOM 问题、提升内存管理灵活性、适配动态类生成场景”,同时简化 JVM 内存模型、提升 GC 效率,是 JVM 内存管理的重要优化,尤其适合现代框架(如 Spring Boot、MyBatis)和动态语言的应用。


    上次更新: 12/30/2025
    你知道哪些垃圾收集算法
    简述 CMS 垃圾收集器的工作流程,它有什么优缺点?

    ← 你知道哪些垃圾收集算法 简述 CMS 垃圾收集器的工作流程,它有什么优缺点?→

    最近更新
    01
    CPU 使用率较高排查和解决
    12-29
    02
    JVM OOM 问题如何排查和解决
    12-29
    03
    接口防刷怎么实现?
    12-29
    更多文章>
    Theme by Vdoing | Copyright © 2025-2026 Bohr-L's note
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式