好的,阿杰,我们来系统讲解 Java 中 java.lang.OutOfMemoryError: Java heap space
的解决方法,以及常用的 JVM 参数设置。我会分步骤详细说明。
1️⃣ 问题概述
错误信息:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
- 含义:JVM 堆内存不足,无法分配对象。
- 常见场景:
- 对象创建过多(如大集合、缓存、数组)。
- 内存泄漏(对象无法被 GC 回收)。
- 堆内存设置过小,无法满足程序需求。
2️⃣ JVM 堆内存结构
- Heap(堆):存放 Java 对象实例。
- Metaspace / PermGen:存放类信息(Java 8 及以上使用 Metaspace)。
- 堆内存分区:
- Young Generation(Eden + Survivor)
- Old Generation(Tenured)
Java heap space
指堆整体空间不足。
3️⃣ 解决方法
方法一:增大 JVM 堆内存
使用 JVM 参数:
-Xms512m # 初始堆大小
-Xmx2g # 最大堆大小
-XX:NewSize=256m # 年轻代初始大小
-XX:MaxNewSize=1g # 年轻代最大大小
示例:
java -Xms512m -Xmx2g -jar myapp.jar
- 建议:
-Xms
设置与-Xmx
相同可以减少堆扩展带来的性能消耗。- 根据程序需求调整,一般应用服务器 1-4G 堆内存较常见。
方法二:分析对象和内存使用
- 使用工具查看堆使用情况
jconsole
/jvisualvm
(JDK 自带 GUI)jmap
+jhat
(命令行)- Eclipse Memory Analyzer (MAT)
- 排查大对象 / 内存泄漏
- 过大的集合,如
List<String>
放入百万条数据 - 缓存未清理
- 静态对象长期占用
- 过大的集合,如
方法三:优化代码
- 减少不必要的对象创建
- 尽量用基本类型或对象复用
- 对集合使用合理的初始容量,避免频繁扩容
- 关闭或清理不再使用的资源(如
InputStream
、ResultSet
)
方法四:使用堆外内存(适合高性能缓存)
- 使用
DirectByteBuffer
或off-heap
技术 - JVM 参数示例:
-XX:MaxDirectMemorySize=1g
适合 Netty、缓存类应用。
方法五:调整 GC 策略(可选)
- 默认 GC:并行收集器(Parallel GC)
- 可以尝试 G1 GC 进行大堆优化:
-XX:+UseG1GC
-XX:MaxGCPauseMillis=200
4️⃣ 常用 JVM 堆内存参数总结
参数 | 含义 | 示例 |
---|---|---|
-Xms | 堆初始大小 | -Xms512m |
-Xmx | 堆最大大小 | -Xmx2g |
-XX:NewSize | 年轻代初始大小 | -XX:NewSize=256m |
-XX:MaxNewSize | 年轻代最大大小 | -XX:MaxNewSize=1g |
-XX:+UseG1GC | 使用 G1 GC | – |
-XX:MaxPermSize | PermGen 大小(Java 7 及以下) | -XX:MaxPermSize=256m |
-XX:MaxMetaspaceSize | Metaspace 最大大小(Java 8+) | -XX:MaxMetaspaceSize=256m |
✅ 小结
- 快速解决 → 增大
-Xmx
。 - 长期优化 → 分析内存使用,优化代码。
- 适用场景:
- 开发阶段:小堆 + 内存分析
- 生产环境:合适堆大小 + GC 调优 + 内存监控
发表回复