如何增大Java中字节数组的最大长度,解决数组大小超出VM限制报错
错误根因
你遇到的Requested array size exceeds VM limit报错直接原因是:
JVM对Java数组的最大长度有内置限制,该限制略小于
Integer.MAX_VALUE(通常是Integer.MAX_VALUE - 2到Integer.MAX_VALUE - 8不等,取决于具体JVM实现),你直接申请长度为Integer.MAX_VALUE的字节数组直接触发了该限制。
除此之外,一次性将2G大小的文件全部读入内存的逻辑本身也不合理,会大量占用堆内存,极易触发OOM。
修复方案
方案1:流式分段读取(最推荐)
不要一次性加载全量文件内容,每次申请固定大小的缓冲区循环读取,按需处理数据,示例代码如下:List<Data> list = Collections.synchronizedList(new ArrayList<>()); File file = new File("你的文件路径"); // 每次读取1MB缓冲区,可根据业务调整大小 int bufferSize = 1024 * 1024; byte[] buffer = new byte[bufferSize]; try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) { int readLen; while ((readLen = bis.read(buffer)) != -1) { // 这里处理读取到的buffer,长度为readLen,处理完后塞到list或者做后续逻辑 // 示例:如果需要拼接所有字节,可用ByteArrayOutputStream中转 // baos.write(buffer, 0, readLen); } } catch (Exception e) { e.printStackTrace(); }方案2:调整数组长度+JVM堆参数(仅适合必须全量加载到字节数组的场景)
- 数组长度不要写死
Integer.MAX_VALUE,取文件实际大小并预留JVM限制空间:
// 取文件大小,同时减去8字节预留JVM数组头空间 int arraySize = (int) Math.min(totalSize, Integer.MAX_VALUE - 8); byte[] bytes = new byte[arraySize];- 启动Java程序时增加JVM参数调大堆内存,至少要比文件大小大2G以上,避免堆内存不足:
-Xms4G -Xmx6G- 数组长度不要写死
方案3:用NIO内存映射读取大文件(适合2G以上大文件读取场景)
超过2G的文件无法用单个字节数组存储,可以用MappedByteBuffer做内存映射,绕过JVM数组长度限制:try (FileChannel channel = new FileInputStream(file).getChannel()) { MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); // 直接操作buffer即可,不需要申请大数组 } catch (Exception e) { e.printStackTrace(); }
内容的提问来源于stack exchange,提问作者Surge Liang
相关产品推荐
相关产品推荐

