方法区 / 元空间:JDK 1.7 到 JDK 1.8 到底变了什么?

如果你只想记一个结论:

  • JDK 1.7 :有永久代(PermGen)
  • JDK 1.8 :移除永久代,用元空间(Metaspace,走本地内存)

但只记结论不够,因为你线上会遇到:

  • OutOfMemoryError: PermGen space
  • OutOfMemoryError: Metaspace
  • 动态代理/反射/生成类太多导致内存异常

这篇把"方法区是什么、放什么、为什么改、怎么排"讲透。


1. 方法区是什么:放"类本身的信息"的地方

方法区是 JVM 规范里的一个概念,主要存:

  • 类元数据:类结构、字段/方法信息、访问标志等
  • 运行时常量池:字符串常量、符号引用等
  • 静态变量相关信息(具体实现上会有差异)
  • JIT 相关的一些元数据(不同实现有所不同)

一句话:

  • 堆里放对象
  • 方法区(元空间)放类

2. JDK 1.7:永久代(PermGen)

2.1 它为什么容易 OOM

永久代属于 HotSpot 的实现细节(不是 JVM 规范硬规定),它的问题在于:

  • 空间大小受 JVM 参数限制(配置不当很容易顶满)
  • 类卸载条件苛刻(尤其在容器里反复热部署)

典型场景:

  • Tomcat 反复热部署,类加载器泄露
  • 大量动态生成类(CGLIB、ASM、Javassist)
  • 运行时常量池/字符串占用膨胀

2.2 常见参数(JDK 1.7)

  • -XX:PermSize
  • -XX:MaxPermSize

3. JDK 1.8:元空间(Metaspace)

3.1 为什么要改

把类元数据从永久代迁到元空间,核心动机:

  • 永久代太容易 OOM,且难以调优
  • 类元数据更适合放到本地内存,避免和 Java 堆争抢

3.2 元空间还会 OOM 吗

会。

  • 元空间用的是本地内存,不等于无限
  • 如果你不设上限,可能把机器内存吃光
  • 如果你设了上限,达到上限一样会 OutOfMemoryError: Metaspace

3.3 常见参数(JDK 1.8)

  • -XX:MetaspaceSize(触发扩容/GC 的阈值,不是硬上限)
  • -XX:MaxMetaspaceSize(硬上限)

4. 运行时常量池:很多人混淆的点

你会听到"常量池在方法区里",但要注意几个历史变化:

  • 规范层面:运行时常量池属于方法区的一部分
  • HotSpot 实现上,JDK 版本间有多次迁移/调整

工程上你记住就行:

  • 类加载越多、常量越多,方法区/元空间压力越大

5. 实战:怎么判断是 Metaspace 泄露还是堆泄露

5.1 快速判断现象

  • 堆泄露:Java heap space,对象一直涨,Full GC 也回不去
  • 元空间泄露:Metaspace,类数量/类元数据一直涨

5.2 常用观测(低侵入)

  • 看类直方图:jcmd <pid> GC.class_histogram
  • 看类加载统计:jcmd <pid> VM.classloaders

你重点盯两件事:

  • 类数量是否持续增长
  • 是否存在"旧类加载器"长期存活(热部署/插件系统常见)

6. 一个常见根因:类加载器泄露

"类卸载"发生的前提通常是:

  • 对应的 ClassLoader 变成不可达

如果你有:

  • 静态集合缓存了某个类加载器加载的对象
  • 线程本地变量(ThreadLocal)引用了它
  • 第三方库注册监听器但不注销

就会导致:

  • 类加载器无法回收
  • 其加载的所有类元数据也无法卸载
  • 最终 Metaspace OOM

7. 总结

  • 方法区(元空间)放"类",堆放"对象"
  • JDK 1.7 的 PermGen 改成 JDK 1.8 的 Metaspace
  • Metaspace 也会 OOM,关键看类是否不断增加、类加载器是否泄露
  • 排障优先从 class_histogram 和 classloaders 入手
相关推荐
kimnoic2 小时前
Python数据库学习心得:SQLite、MySQL、PostgreSQL优缺点
开发语言·python
别动我齐刘海3 小时前
C++ 工程化学习
java·linux·前端·c++·学习·机器学习·机器人
必须得开心呀3 小时前
python编写带界面的软件,需要安装哪些插件
开发语言·python
code2cat4 小时前
Java进阶篇之AtomicLongFieldUpdater:把累计额度留在对象字段中
java·cas·并发编程
WeiXin_DZbishe4 小时前
基于springboot城市公交实时运营与调度系统-计算机毕设 附源码【课程设计】66173
java·vue.js·spring boot·后端·python·php·课程设计
泡茶喝茶写代码4 小时前
A股量化数据工程:从 REST 接口到策略信号(第 18 篇):放量缩量异动扫描
java·python·股票数据api·股票数据api接口·股票api数据接口·股票量化数据api·股票量化数据接口
wewowilling5 小时前
认识微服务
java·运维·微服务·springcloud
代码什么用5 小时前
Java Web 7-10
java·servlet
沫璃染墨5 小时前
《Qt从零入门系列(十三):QSS样式表详解——从选择器与层叠规则到控件美化实战》
开发语言·css·c++·qt·ui·qt6.3·qss