我正在处理未知大小的输入流,我需要将其序列化为byte []以实现故障安全行为。
我现在有基于IOUtils的代码,但是有5-50个不同的线程可能运行这个,我不知道它有多可靠。
try(final ByteArrayOutputStream output= new ByteArrayOutputStream()){
long free_memory = Runtime.getRuntime().freeMemory() / 5;
final byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
long count = 0;
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
free_memory -= n;
if (free_memory < DEFAULT_BUFFER_SIZE) {
free_memory = Runtime.getRuntime().freeMemory();
if (free_memory < (DEFAULT_BUFFER_SIZE * 10)) {
throw new IOException("JVM is low on Memory.");
}
free_memory = free_memory / 5;
}
}
output.flush();
return output.toByteArray();
}
我想在问题出现之前捕获OOM错误并杀死该线程,并且我不想将该流保存为文件。有没有更好的方法来确保你不会使用太多的记忆?
(我使用的是Java 8)
答案 0 :(得分:0)
如果多个线程正在运行相同的代码,那么太过回答你的问题,这是一种非常不可靠的方式。
代码询问系统有多少内存可用Runtime.getRuntime().freeMemory()
,这是一个在它返回的瞬间过时的值,因为其他线程在此期间会消耗更多的内存。在抛出一些不那么明显的剩余内存阈值的情况下应该抛出的相应I / O异常可能会也可能不会执行,但是它是否完全不重要。
数据的捕获是在ByteArrayOutputStream
内完成的,每次到达结束时都会增加(并复制)其缓冲区。它不受“有多少内存”检查的控制,因此多个线程将同时调整其缓冲区大小,其中任何一个都可能失败。
最安全的方法是将数据存储在磁盘上,从而制作副本。如果数据来自外部流媒体源,您可以使用
Files.copy()
。如果您获得的是文件,则可以使用copy
的其他变体,我认为将其委托给操作系统。