Java堆内存不足致线程执行异常:文件仅创建未写入原因探究
堆内存不足导致文件写入异常问题分析
测试场景描述
- JVM参数为
-Xms10m -Xmx10m时
程序正常运行,成功创建1000个带有内容的文件,代码如下:
import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; public class Test { public static final int COUNT = 1_000; public static void main(String[] args) { testByThread(); } public static void testByThread() { long start = System.currentTimeMillis(); for (int i = 0; i < COUNT; i++) { int finalI = i; new Thread(() -> { int num = write1("threadTest", finalI); System.out.println(num); }).start(); } System.out.println("total: " + (System.currentTimeMillis() - start)); } public static int write1(String name, int i) { try { String content = "This is the content to write into create file"; String path = "D:" + name + i + ".txt"; File file = new File(path); FileWriter fw = new FileWriter(file.getAbsoluteFile()); BufferedWriter bw = new BufferedWriter(fw); bw.write(content); bw.close(); } catch (Exception e) { e.printStackTrace(); } return i + 1; } }
- JVM参数调整为
-Xms2m -Xmx2m时
控制台抛出大量如下异常:
Exception in thread "Thread-253" java.lang.OutOfMemoryError: Java heap space Exception in thread "Thread-254" java.lang.OutOfMemoryError: Java heap space ...
此时虽成功创建1000个文件,但其中275个文件大小为0KB,无内容写入。
问题解析
为何部分线程仅创建文件未写入内容?
核心原因是堆内存耗尽导致线程在写入逻辑执行阶段抛出OutOfMemoryError,写入流程被直接中断。
write1方法的完整执行异常拆解
逐个阶段看线程执行write1时的情况:
- 文件创建阶段:
new File(path)和new FileWriter(file.getAbsoluteFile())会触发文件创建,这部分操作依赖本地文件系统,几乎不占用堆内存,所以即使堆内存不足,这一步也能完成,空文件因此被创建。 - 写入准备/执行阶段触发OOM:
- 创建
BufferedWriter时,它默认会在堆内存中分配8KB左右的缓冲区。如果此时堆内存已经耗尽,这一步会直接抛出OutOfMemoryError,后续的bw.write(content)和bw.close()完全没机会执行。 - 就算缓冲区创建成功,执行
bw.write(content)时,字符串的处理、缓冲区扩容(如果需要)也会占用堆内存,同样可能触发OOM,导致写入中断。
- 创建
- 异常无法被捕获:方法中的
catch (Exception e)只能捕获Exception及其子类,而OutOfMemoryError属于Error类,根本不会被这个catch块捕获。线程抛出OOM后直接终止,写入流程彻底中断,文件自然为空。
额外说明
- 部分线程能正常写入,是因为它们启动较早,在堆内存耗尽前就完成了缓冲区分配、内容写入、资源关闭的全流程。
- 最终能创建1000个文件,是因为文件创建操作不依赖堆内存,即便线程后续因OOM挂掉,文件已经被成功创建。
内容的提问来源于stack exchange,提问作者Criwran
相关产品推荐
相关产品推荐

