【问题标题】:Java memory leak - FileReaders, BufferedReaders and StacksJava 内存泄漏 - FileReaders、BufferedReaders 和 Stacks
【发布时间】:2012-02-22 11:06:30
【问题描述】:

我不是世界上最有经验的 Java 程序员,我正在尝试创建一个工具来提取数据并将其存储起来,但我遇到了内存泄漏(至少我认为这是正在发生的事情,无论哪种方式我得到一个 java.lang.OutOfMemoryError: Java heap space)。

这是有问题的代码:

public static void main(String[] args)
{
    File inputDirectory = new File(args[0]);
    File[] files = inputDirectory.listFiles();
    for(int i = 0 ; i < files.length ; ++i)
    {
        DoSomethingWithTheFile(files[i]);
    }
}

public static void DoSomethingWithTheFile(File inputFile) throws VariousExceptions
{
    boolean result = false;
    if(inputFile.exists())
    {
        FileReader fr = new FileReader(inputFile);
        BufferedReader br = new BufferedReader(fr);
        Stack lines = new Stack();
        String line;
        while((line = br.readLine()) != null)
        {
            lines.push(line);
        }
        br.close();
        int numberOfRecords = lines.size();
        for(int i = 0 ; i < numberOfRecords ; ++i)
        {
            String theString = (String)lines.pop();
        }
        result = true;
    }
    return result;
}

我正在读取堆栈,以便在开始处理之前知道文件中的行数,以便我可以让用户了解我们在文件中的距离。

显然这是一个玩具示例,在实际版本中它的作用远不止于此,但是我可以使用上述精简版代码复制问题。我目前正在尝试读取 4 个文件,其中第一个文件刚刚超过一百万行,第二个文件刚刚超过一百万行。程序在尝试读取第三个文件时崩溃了。

对我做错了什么有任何想法吗?

谢谢, 里克

【问题讨论】:

  • 我认为在 finally 块中包含 close() 语句以确保它被执行是一种很好的做法。
  • 文件有多大(以字节为单位,而不是行)? Java 可能需要大约两倍的内存,具体取决于输入的字符编码。
  • 尝试使用JConsole监控内存使用情况,看看是否有内存被释放;如果需要,增加 -Xmx JVM 设置以分配更多内存

标签: java memory-management memory-leaks


【解决方案1】:

您可以使用 -Xmx 选项增加分配给程序的最大内存:

java -Xmx256m -jar yourApplication.jar

此外,关闭流的更好方法是使用 try / catch / finally。 “finally”语句始终运行,即使抛出异常也是如此。它会是这样的:

boolean result = false;
if(inputFile.exists())
{
    FileReader fr = null;
    BufferedReader br = null;
    try{
        fr = new FileReader(inputFile);
        br = new BufferedReader(fr);
        Stack lines = new Stack();
        String line;
        while((line = br.readLine()) != null)
        {
            lines.push(line);
        }
        br.close();
        int numberOfRecords = lines.size();
        for(int i = 0 ; i < numberOfRecords ; ++i)
        {
            String theString = (String)lines.pop();
        }
        result = true;
    }
    finally{
        if( br != null ) br.close();
        if( fr != null ) fr.close();
    }
}
return result;

最后,这是“堆栈线”对象,它保留了大量内存。如果您不想增加内存,请在 while(...) 循环中执行操作。

【讨论】:

【解决方案2】:

您是否尝试过增加最大堆大小?

java -Xms<initial heap size> -Xmx<maximum heap size>

已编辑:哦.. 已经有答案了

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-29
    • 2015-08-14
    • 2012-08-11
    • 2015-12-14
    相关资源
    最近更新 更多