JVM 内存与 GC 概览

运行时数据区直觉、堆上对象与 GC 基本目标:先正确测量再谈调优,并标注实现相关性。

#type / concept #status / growing #tech / dev #resource / java

[!info] 关联笔记

JVM 内存与 GC 概览

这个概念为什么出现

OOM、频繁停顿、堆配置争论都指向内存与 GC。先建立对象在堆、帧在栈、GC 回收不可达对象的模型,再谈收集器名称与参数。

[!abstract] 一句话理解 对象主要在堆分配;GC 回收不可达对象;具体分代/收集器/停顿行为高度实现相关,必须测量后调优。

最小可观察示例

场景:分配大量临时对象观察程序仍可结束(示意)

public class AllocChurn {
    public static void main(String[] args) {
        long sum = 0;
        for (int i = 0; i < 1_000_00; i++) {
            sum += ("id-" + i).length(); // 产生临时字符串
        }
        System.out.println(sum);
    }
}
javac AllocChurn.java && java -Xms32m -Xmx32m AllocChurn

期望:打印正整数并正常退出(具体 sum 固定可算)。
可用 java -Xlog:gc*:file=gc.log(版本支持时)观察 GC 日志——解读依赖实现

结合场景再看三个关注点

  1. 临时对象靠 GC 回收,不是手动 free。
  2. 堆上限 -Xmx 是常见容量阀。
  3. 日志证明有回收活动,不代表你需要立刻调参。

核心概念与准确模型

1. 运行时数据区(教学模型)

  • 堆:对象实例
  • 栈:帧、局部变量
  • 元空间:类元数据(HotSpot 常见)
  • PC/本地栈等

2. 可达性

GC Root 出发不可达 → 可回收(含最终化等历史细节慎用)。

3. 收集器

Serial/Parallel/G1/ZGC… 名称与默认随 JDK 版本变

边界情况与反直觉行为

  1. 内存泄漏常是“仍可达但不该可达”(缓存、监听器)。
  2. 堆外内存(直接内存、JNI)不在同一仪表盘。
  3. 最终化 finalize 已过时,不应用。

常见误区

[!warning] 常见误区:一上来抄 GC 参数大全 先修分配与泄漏,再用指标驱动。

工程实践

  1. 固定容器内存与 -Xmx 关系。
  2. 观察分配速率、停顿、堆占用。
  3. 用 MAT/jcmd/jfr 定位保留路径。
  4. 版本升级后重测默认收集器变化。

本节总结

  • 堆对象 + 可达性回收
  • 实现相关细节要标注
  • 测量优先于调参

自测题

  1. 栈上装的是对象本身吗?
  2. 为什么“泄漏”在 GC 语言里仍可能发生?
参考答案
  1. 栈帧持有引用/基本类型局部量;对象实例通常在堆。
  2. 对象仍被无意引用保持可达,GC 无法收。

延伸阅读与资料来源

资料类型支撑内容
HotSpot GC Tuning Guide官方实现向导
JVMS Runtime Data Areas规范数据区概念
创建于 2026/7/15 更新于 2026/7/15