JVM内存模型和垃圾回收机制_JVM内存管理与自动垃圾回收关联

新对象默认且唯一首选分配在Eden区,仅大对象超-XX:PretenureSizeThreshold时直接入老年代;Survivor双区为复制算法服务;System.gc()仅为可忽略建议;Metaspace溢出多因类加载器泄漏。

对象分配在哪?Eden区不是“默认起点”而是“唯一首选”

新对象几乎总在 Eden 区分配,这是 JVM 分代设计的硬性约定,不是可配置的“偏好”。哪怕你把 -Xmn 设得再小,只要堆还有空闲,JVM 就不会跳过 Eden 直接往 Survivor 或老年代扔对象(大对象例外,见下条)。

  • 触发 Minor GC 的条件是 Eden 区满,不是“用了 80% 就回收”——它不看比例,只看是否还能成功分配下一个对象
  • 若对象大小超过 -XX:PretenureSizeThreshold(默认为 0,即禁用),JVM 会直接将其分配到老年代,避免在新生代反复复制造成浪费
  • 注意:字符串字面量(如 "hello")不进 Eden,它们存于堆中的运行时常量池(JDK 7+ 已移出方法区),而 new String("hello") 才会在 Eden 分配实例

为什么 Survivor 区要设两个(S0 和 S1)?不是为了“备份”,而是为复制算法腾空间

Survivor 区的存在,本质是为 复制算法 服务:每次 Minor GC 后,Eden + 当前使用的 Survivor(比如 S0)中存活的对象,被一次性复制到另一个空的 Survivor(S1),然后清空 Eden 和 S0。没有“双区”,复制就无法原子完成。

  • 比例 -XX:SurvivorRatio=8

    表示 Eden : 单个 Survivor = 8:1,不是 Eden : 总 Survivor;两个 Survivor 大小相等、角色互换
  • 对象在 Survivor 中“熬过”多少次 GC 才晋升老年代,由 -XX:MaxTenuringThreshold 控制(默认 15),但实际晋升可能更早——当某次 GC 后,To Survivor 空间不足以容纳所有存活对象时,JVM 会提前把部分对象送入老年代(动态年龄判定)
  • 误配 -XX:SurvivorRatio 过大会导致 Survivor 过小,频繁触发提前晋升,加剧老年代压力;过小则浪费空间,且易因复制失败触发 Full GC

System.gc() 不是“手动触发回收”,而是向 JVM 发送一个“可忽略的建议”

调用 System.gc() 仅等价于 Runtime.getRuntime().gc(),它不保证任何行为:G1 可能完全无视,CMS 可能转为并发模式,Serial/Parallel 则大概率触发一次 Full GC——但前提是 JVM 当前没在 GC 中、没被 -XX:+DisableExplicitGC 拦截。

  • 线上服务务必加 -XX:+DisableExplicitGC,否则第三方 SDK 或日志框架里一句 System.gc() 就可能引发数秒停顿
  • 显式 GC 常见于内存敏感场景(如 Android 应用退到后台),但在服务器端,它和手动调用 Thread.stop() 一样危险:破坏 JVM 自主调度节奏
  • 真正需要“及时释放”的资源(如 DirectByteBuffer),应依赖 Cleanertry-with-resources,而非寄望于 GC 回收

元空间(Metaspace)溢出 ≠ 类太多,很可能是类加载器泄漏

JDK 8+ 用本地内存实现的 Metaspace 替代了永久代,java.lang.OutOfMemoryError: Metaspace 错误出现时,第一反应不该是加 -XX:MaxMetaspaceSize,而应检查是否有自定义类加载器未被回收——每个加载器加载的类元数据都独占一块 Metaspace,且只有加载器本身被 GC 时,这些元数据才释放。

  • 典型泄漏场景:OSGi 容器、热部署框架(如 Spring Boot DevTools)、或反复 new URLClassLoader 加载同一 JAR
  • 排查命令:jstat -gc MU(Metaspace used)持续上涨;jcmd VM.native_memory summary 查 native 内存分布
  • 修复关键:确保类加载器引用链可被 GC(如清除静态 Map 缓存、关闭线程上下文类加载器绑定)
JVM 的自动垃圾回收不是“黑盒托管”,而是分代策略、算法约束与运行时反馈共同作用的结果;真正卡住性能的,往往不是 GC 算法本身,而是对象生命周期与分代假设不匹配,或是元数据管理脱离了类加载器的生命周期控制。