调用DigestInputStream的readAllBytes()忽略返回值是否仍触发OutOfMemoryError?
问题解答
核心结论
忽略readAllBytes()的返回值仍然会触发OutOfMemoryError,因为该方法的内部逻辑必然会创建一个容纳整个文件内容的byte[]——不管你是否接收这个返回值,内存分配的动作已经完成,只要文件大小超出JVM可用内存上限,OOM就会抛出。
原因分析
InputStream.readAllBytes()(Java 9+引入)的底层逻辑是:不断读取文件内容,动态扩容内部数组直到装下所有字节,最后返回这个数组。哪怕你不把返回值赋值给变量,这个数组在方法执行期间已经占用了内存,大文件场景下的内存溢出风险完全没消除。
而且你用DigestInputStream的场景根本不需要加载整个文件到内存——它的设计初衷就是边读取字节边计算摘要,完全不需要缓存全部文件内容。
正确的校验和计算方式
放弃使用readAllBytes(),改用固定大小的缓冲区循环读取,示例代码:
try (DigestInputStream d = new DigestInputStream(new FileInputStream("example.txt"), MessageDigest.getInstance("SHA-1"))) { byte[] buffer = new byte[8192]; // 8KB缓冲区,可根据实际情况调整 // 循环读取,DigestInputStream会自动更新摘要 while (d.read(buffer) != -1) {} // 获取最终计算出的校验和 MessageDigest digest = d.getMessageDigest(); byte[] checksum = digest.digest(); // 后续处理校验和逻辑 } catch (IOException | NoSuchAlgorithmException e) { e.printStackTrace(); }
这种方式不管文件多大,只会占用固定大小的缓冲区内存,彻底避免大文件导致的OOM问题。
内容的提问来源于stack exchange,提问作者Pestro
相关产品推荐
相关产品推荐

