3

我们使用如下简单、简单、简单的代码面临内存泄漏。该代码旨在从源获取文件,使用每个文件做某事并继续。这个简单的代码总是使用相同的文件,但行为没有改变。

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 上没有

4

4 回答 4

2

这段代码应该可以正常运行(除了多次创建新文件没有任何意义)。

我在循环中运行了你的代码 1000 万次,但它没有产生 OOME。事实上,它的内存使用量一直保持在 50Mb 左右。

所以,我认为问题应该是别的。

于 2011-02-02T09:31:36.950 回答
1

我会针对Visual VM之类的分析器运行您的代码,并查看内存在哪里被用完。

我猜测做“字节码的东西”可能会导致问题。通常也不建议调用 System.gc(),因为 garabge 收集器应该知道自己何时应该调用它。

于 2011-02-02T09:39:10.727 回答
0

由于您在每次迭代中有效地丢弃了从文件中读取的字节,因此我认为没有理由获得 OOME,除非文件的大小超过XmxJVM 进程的默认值(只是一个思考过程,因为我知道 TIF 文件是与其他图像格式相比,它们的巨大尺寸而臭名昭著)。

另外,打印出迭代次数。您是否总是以相同的迭代次数获得 OOME?还是您正在“使用”从文件流中读取的字节?

于 2011-02-02T09:40:55.077 回答
0


在为此浪费时间和健康之后,我们发现问题出在目标计算机上的安装方式。
我们的程序员构建了一个可运行的 jar,其中包含所有需要的 jar,而不是使用已经安装在目标机器上的那些。所以......“某事”是不同的,即使我们实际上不知道是什么,而且现在的程序不会再丢失记忆了。

有人可以向我解释吗?(我不得不说我是一名 C/C++ 开发人员,而不是 Java 开发人员,而且我正在写我的一位同事的工作)。

于 2011-02-03T09:53:48.147 回答