我们使用简单,简单,简单的代码面临内存泄漏,如下所示。 该代码旨在从源获取文件,使用每个文件执行某些操作并继续。 这个简单的代码总是使用相同的文件,但行为没有改变。
package it.datapump.main;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class TifReader {
public static void main (final String[] a){
for (int i = 0; i < 100000; i++) {
try {
getBytesFromFile(new File("test.tif"));
Thread.sleep(1000);
System.gc() ;
} catch (Exception ex) {
}
}
}
public static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
long length = file.length();
byte[] bytes = new byte[(int)length];
int offset = 0;
int numRead = 0;
while (offset < bytes.length
&& (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
offset += numRead;
}
is.close();
// Do something with the read bytes
//
if (offset < bytes.length) {
throw new IOException("Could not completely read file "+file.getName());
}
return bytes;
}
}
现在......我们只是看不出这个代码消耗内存到顶部的有效原因,最后会抛出OutOfMemoryError异常。
有什么想法吗?
更多东西
问题出现在Java Development Kit Version 6 Update 23上,但它不适用于JRE 1.7
答案 0 :(得分:2)
这段代码运行正常(除了创建新文件这么多次没有意义)。
我在一个循环中运行你的代码1000万次并且它没有产生OOME。事实上,它的内存使用量一直保持在50Mb左右。
所以,我认为问题应该是别的。
答案 1 :(得分:1)
我会针对像Visual VM这样的探查器运行您的代码,并查看内存耗尽的位置。
我猜测“带字节代码的东西”可能会导致问题。通常不建议调用System.gc(),因为garabge收集器应该在调用它时知道它自己。
答案 2 :(得分:0)
由于你在每次迭代时都有效地丢弃了从文件读取的字节,我认为没有理由获得OOME,除非文件的大小超过了JVM进程的默认Xmx
(只是一个思考过程,因为我知道TIF文件与其他图像格式相比,因其巨大的尺寸而臭名昭着。)
另外,打印出迭代编号。你是否总是以相同的迭代次数获得OOME?或者是你“使用”从文件流中读取的字节?
答案 3 :(得分:0)
在浪费时间并对此进行操作后,我们发现问题是由于包装在目标机器上的安装方式
我们的程序员构建了一个可运行的jar,包含所有需要的jar,而不是使用目标机器上安装的alt。
所以......“某些东西”是不同的,即使我们实际上并不知道什么,而且现在的程序不会再失去记忆。
有人可以向我解释一下吗? (我不得不说我是一名C / C ++开发人员,而不是Java开发人员,而且我正在撰写关于我的同事的工作)。