Java内存溢出教程


Java内存溢出 (OutOfMemoryError) 教程

1. 内存溢出简介

在Java中,**内存溢出(OutOfMemoryError)**是指JVM在运行过程中无法为对象分配足够内存时抛出的错误。常见原因包括:

  • 对象持续增加,堆内存不足
  • 无限递归导致栈空间耗尽
  • 资源未及时释放导致内存泄漏

内存溢出不同于普通异常,它是Error的一种,一般不通过try-catch处理,而是通过优化程序和配置JVM来解决。


2. JVM内存结构概览

JVM主要内存区域:

  • 堆(Heap):存放对象实例
  • 方法区(Method Area):存放类信息、常量、静态变量
  • 栈(Stack):存放方法调用及局部变量
  • 本地方法栈(Native Stack)
  • 程序计数器(PC Register)

堆内存不足会抛出java.lang.OutOfMemoryError: Java heap space
栈空间不足会抛出java.lang.StackOverflowError


3. 堆内存溢出示例

1
2
3
4
5
6
7
8
9
10
11
import java.util.ArrayList;
import java.util.List;

public class HeapOOM {
public static void main(String[] args) {
List<int[]> list = new ArrayList<>();
while (true) {
list.add(new int[1024 * 1024]); // 持续分配大数组
}
}
}

运行时会很快抛出:

1
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

解决方法:

  • 优化代码,减少对象创建
  • 使用集合时注意容量,及时释放引用
  • 增加堆内存:-Xmx512m

4. 栈内存溢出示例

1
2
3
4
5
6
7
8
9
public class StackOverflow {
public static void recursive() {
recursive(); // 无限递归
}

public static void main(String[] args) {
recursive();
}
}

运行时会抛出:

1
Exception in thread "main" java.lang.StackOverflowError

解决方法:

  • 检查递归出口,避免无限递归
  • 调整栈大小:-Xss1m

5. 元空间/方法区溢出

对于类加载过多或动态生成类的情况,可能会抛出:

1
java.lang.OutOfMemoryError: Metaspace

解决方法:

  • 优化类加载和动态代理生成的类
  • 调整元空间大小:-XX:MaxMetaspaceSize=256m

6. 内存泄漏示例

即使对象不再使用,如果仍然有引用,GC无法回收,会导致堆内存逐渐耗尽。

1
2
3
4
5
6
7
8
9
10
11
12
import java.util.ArrayList;
import java.util.List;

public class MemoryLeak {
private static List<Object> leakList = new ArrayList<>();

public static void main(String[] args) {
while (true) {
leakList.add(new Object()); // 持续添加对象导致堆溢出
}
}
}

解决方法:

  • 避免静态集合无限增长
  • 手动释放不再使用的对象引用
  • 使用内存分析工具 (如VisualVM, MAT) 进行排查

7. 总结

Java内存溢出是程序性能和稳定性的重要问题。通过理解JVM内存结构、优化代码逻辑、及时释放对象引用以及合理配置JVM参数,可以有效减少内存溢出发生。对于大规模应用,还可使用内存分析工具进行定位和优化。