测试中,遇到的错误是:
java.lang.OutOfMemoryError: PermGen space
这个错误表示 JVM 的永久代(PermGen)内存溢出,常见于 Java 7 及更早版本。PermGen 是 JVM 内存模型中用于存储类的元数据(如类定义、方法、常量池等)的一部分。
🧠 原因分析
✅ 主要原因:
- 加载了大量类(例如使用反射、动态代理、JSP 编译、OSGi、Groovy、Spring AOP 等)
- 频繁重新部署 Web 应用(在 Tomcat 中热部署导致旧类未被卸载)
- JVM 默认的 PermGen 空间较小
🔧 解决方案
✅ 1. 增加 PermGen 内存
在启动参数中增加以下 JVM 参数:
-XX:PermSize=128m -XX:MaxPermSize=256m
示例(Tomcat setenv.sh
或 startup.bat
):
Linux/Unix (setenv.sh
):
export JAVA_OPTS="$JAVA_OPTS -XX:PermSize=128m -XX:MaxPermSize=256m"
Windows (setenv.bat
):
set JAVA_OPTS=%JAVA_OPTS% -XX:PermSize=128m -XX:MaxPermSize=256m
✅ 2. 使用 -XX:+CMSClassUnloadingEnabled
(配合 CMS GC)
如果你使用的是并发标记清除垃圾回收器(CMS),可以启用类卸载功能:
-XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled
这有助于在 Full GC 时回收无用类的元数据,缓解 PermGen 溢出问题。
✅ 3. 升级到 Java 8+
从 Java 8 开始,永久代(PermGen)被元空间(Metaspace)取代,默认情况下 Metaspace 会自动扩展,不再有固定大小限制。
你可以通过以下参数控制 Metaspace 大小(可选):
-XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m
如果你正在使用 Java 8 或更高版本,但仍看到 PermGen 错误,请检查是否设置了兼容性参数或使用了旧版工具链。
✅ 4. 检查应用是否有类泄漏
常见的类泄漏场景包括:
- 使用自定义 ClassLoader 加载类但未正确卸载
- Spring / Hibernate / OSGi 等框架管理不当
- JSP 页面频繁修改导致重复编译生成新类
建议:
- 使用 VisualVM 或 MAT (Memory Analyzer) 分析堆转储(heap dump)
- 查看类加载器和已加载类的数量趋势
📌 总结
方案 | 描述 |
增加 PermGen |
|
启用类卸载 |
|
升级 Java 版本 | 使用 Java 8+,替换为 Metaspace |
分析内存泄漏 | 使用内存分析工具排查类加载问题 |