在Java中释放未使用的RAM

时间:2013-05-09 09:20:34

标签: java garbage-collection

我有一个Java类,它分配目录中的所有文件(6GB)。然后为每个文件做一些文本处理。当我检查ram的用法时,我可以看到当我从一个文件完成并开始到下一个文件时,RAM没有摆脱以前的文件 - 垃圾收集不好,我想。有没有办法以编程方式释放已完成的文件及其数据?

public void fromDirectory(String path) {

        File folder = new File(path);
        disFile = path + "/dis.txt";
        if (folder.isDirectory()) {
            File[] listOfFiles = folder.listFiles();

            for (int i = 0; i < listOfFiles.length; i++) {
                File file = listOfFiles[i];
                if (file.isFile() && file.getName().contains("log")) {
                    System.out.println("The file will be processed is: "
                            + file.getPath());
                    forEachFile(file.getPath());
                    //Runtime.getRuntime().exec("purge");
                    //System.gc();

                } else
                    System.out.println("The file " + file.getName()
                            + " doesn't contain log");
            }

        } else {
            System.out.println("The path: " + path + " is not a directory");
        }

}

private void forEachFile(String filePath) {
    File in = new File(filePath);
    File out = new File(disFile);

    try {
        out.createNewFile();
        FileWriter fw = new FileWriter(out.getAbsoluteFile());
        BufferedWriter bw = new BufferedWriter(fw);
        BufferedReader reader = new BufferedReader(new FileReader(in));

        String line = null;
        while ((line = reader.readLine()) != null) {

            if (line.toLowerCase().contains("keyword")) {
                bw.write(line);
                bw.newLine();
                numberOfLines++;
            }
        }
        reader.close();
        bw.close();

    } catch (IOException e) {
        e.printStackTrace();
    }
}

4 个答案:

答案 0 :(得分:0)

您可以通过调用System.gc()强烈建议VM执行垃圾回收。这通常被认为是代码气味。

答案 1 :(得分:0)

我认为你在这里误解了两件事:JVM内存分配和分配空间内的内存使用情况。

JVM可能会分配大量内存并且不会自由它甚至在使用它的对象被内部包含之后。它可能在一段时间后被释放或根本没有释放。

您可以尝试减少应用程序的内存占用量,例如不使用toLowerCase,因为它会创建一个新对象。也许预编译的正则表达式搜索会更快?

使用System.gc()就像你做的那样,在你看来,我认为是可以接受的。是否有帮助 - 我不知道。

只要你有大量可用内存且Java因为无法分配更多而不会减速,我会保持原样。代码看起来很好。

答案 2 :(得分:0)

即使您正确检查某个探查器的内存并正确推断该文件仍保留在内存中,您认为它应该立即发布吗?

当内存耗尽时(取决于JVM配置),JVM将在开发人员认为应该的时候进行垃圾收集。

同样根据您的问题判断我怀疑您是否使用了分析器或类似的工具来衡量JVM内存的使用情况。相反,你更有可能检查整个JVM使用的内存。

除非您遇到内存不足错误,否则不要担心这些事情。

答案 3 :(得分:0)

如上所述,垃圾收集器在没有更多可用内存时运行。如果您有10100MB个文件,并且将堆设置为4GB,那么很可能您根本不会获得任何GC。

现在,对于“释放已完成的文件及其数据”部分,您无法自己做到这一点,也不应该尝试这样做。

  • 如果您希望应用程序具有内存效率,那么您可以将最大堆大小设置为较小的值。
  • 另一方面,如果您希望您的应用程序非常快,那么您不希望遭受任何GC的影响,因此消除了每个System.gc()调用并为您的堆提供尽可能多的内存。 / LI>

尝试释放自己的内存意味着给你的堆太多内存(你的应用程序没有内存效率)并自己触发GC(你的应用程序也没有时间效率)。

请注意,在某些情况下,JVM可以将内存返回给操作系统。例如,对于G1,它会,但对于CMS,它不会。有关详细信息,请参阅this article

最后,如果您使用Java7,则应将InputStream / OutputStream包装在try-with-resources中。或者,至少将.close()包装在finally块中。

希望有所帮助!