JDK 1.8 JVM内存模型核心变化是永久代被元空间取代:元空间使用本地内存而非堆内存,不参与堆GC,由-XX:MetaspaceSize和-XX:MaxMetaspaceSize控制,字符串常量池仍在堆中,运行时常量池移至元空间。

JDK 1.8 的 JVM 内存模型最核心变化是:永久代(PermGen)被彻底移除,由元空间(Metaspace)替代——这不只是换个名字,而是内存归属、GC 行为和调优逻辑的根本性重构。
为什么 Metaspace 不再报 java.lang.OutOfMemoryError: PermGen space
因为元空间不再使用 JVM 堆内存,而是直接分配在本地内存(native memory)中。只要系统物理内存或虚拟内存没耗尽,就不会因“类太多”而触发该错误。
-
-XX:PermSize和-XX:MaxPermSize参数在 JDK 1.8 中已完全失效,继续配置会被 JVM 忽略(启动时可能报 warning) - 取而代之的是
-XX:MetaspaceSize(触发首次元空间 GC 的初始阈值)和-XX:MaxMetaspaceSize(硬上限,默认不限) -
字符串常量池(
"abc"这类字面量)早在 JDK 1.7 就已从永久代移到堆中,JDK 1.8 仍保留在堆里;但运行时常量池(如类的符号引用、字段/方法签名等)现在属于元空间管理
堆内结构没变,但“方法区”的实现逻辑彻底脱离 JVM 堆
新生代(Eden + S0/S1)、老年代、GC 策略这些堆内划分与 JDK 1.7 一致,但“方法区”这个逻辑概念,现在由元空间承载,且它不参与任何堆 GC 周期。
RPCMS是一款基于PHP+MYSQL的轻量型内容管理/博客系统,支持PHP5.6版本以上,支持win/Linux系统。它自主研发的RP框架(OPP方式),采用MVC架构搭建的高效、稳定的内容管理系统。灵活小巧,但有着强大的扩展性、丰富的插件接口和大量的模板。统一采用模板标签,轻松上手,让开发更方便!智能缓存机制让网站运行方面大幅度提高。系统特点:源码简洁、体积轻巧、功能丰富、安全、灵活等特点,完
- 类加载器卸载类时,元空间会释放对应元数据,但不会像永久代那样随 Full GC 被清理——它有自己的独立 GC 触发机制(基于
MetaspaceSize水位) - 多个应用共享同一 JVM(如 Tomcat 多 WebApp)时,元空间可复用相同类的元数据(如都用
fastjson),减少重复加载开销;而永久代每个 ClassLoader 都要单独占一份 - 若未设置
-XX:MaxMetaspaceSize,元空间持续增长最终会耗尽本地内存,导致进程被 OS OOM-killer 杀掉(错误日志里看不到 Java OOM,只有Killed process)
程序计数器、栈、堆仍是线程私有/共享的老样子,但要注意“栈溢出”场景没变
虚拟机栈、本地方法栈、程序计数器这些线程私有区域,在 JDK 1.8 中行为完全不变,StackOverflowError 和 OutOfMemoryError 的触发条件也一样。
- 递归过深、局部变量表过大(比如定义了超大数组作为局部变量)、线程数过多(每个线程默认 1MB 栈空间)仍会导致栈相关异常
- 程序计数器仍是唯一不会发生
OutOfMemoryError的区域,且永远只存当前字节码行号或null(native 方法时) - 别误以为“元空间用了本地内存,堆就安全了”——堆内存不足照样抛
java.lang.OutOfMemoryError: Java heap space,该调-Xms/-Xmx还得调
真正容易被忽略的是:元空间的 GC 不是“自动友好型”,它只在达到 MetaspaceSize 后才尝试回收无用类,且是否成功取决于类加载器是否被回收。如果应用频繁生成类(如大量使用 CGLIB、Groovy 脚本、热部署),又没正确释放 ClassLoader,元空间会持续上涨直到触达 MaxMetaspaceSize 或本地内存极限——这时候看监控,会发现 GC 日志里 Metadata GC Threshold 反复出现,但元空间使用量却下不去。









