方法区 / 元空间: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.7PermGen 改成 JDK 1.8Metaspace
  • Metaspace 也会 OOM,关键看类是否不断增加、类加载器是否泄露
  • 排障优先从 class_histogramclassloaders 入手
相关推荐
kkeeper~14 小时前
0基础C语言积跬步之深入理解指针(5下)
c语言·开发语言
一直不明飞行14 小时前
Java的equals(),hashCode()应该在什么时候重写
java·开发语言·jvm
REDcker14 小时前
有限状态机与状态模式详解 FSM建模Java状态模式与C++表驱动模板实践
java·c++·状态模式
盲敲代码的阿豪14 小时前
Python 入门基础教程(爬虫前置版)
开发语言·爬虫·python
你的保护色14 小时前
【无标题】
java·服务器·网络
basketball61615 小时前
C++ 构造函数完全指南:从入门到进阶
java·开发语言·c++
互联科技报15 小时前
2026超融合选型:Top5品牌与市场格局解读
开发语言·perl
weixin1997010801615 小时前
[特殊字符] 智能数据采集:数字化转型的“数据石油勘探队”(附Python实战源码)
开发语言·python
淘矿人15 小时前
Claude辅助DevOps实践
java·大数据·运维·人工智能·算法·bug·devops
想唱rap15 小时前
IO多路转接之poll
服务器·开发语言·数据库·c++