0

我有一个 Java 类,它分配目录 (6GB) 中的所有文件。然后对每个文件进行一些文本处理。当我检查内存使用情况时,我可以看到当我从一个文件完成并开始到下一个文件时,内存并没有摆脱前一个文件——我猜是垃圾收集不好。有没有办法以编程方式释放完成的文件及其数据?

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

4 回答 4

0

即使您从某个分析器检查内存并“正确”推断该文件保留在内存中是正确的,为什么您认为应该立即释放它?

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

同样从您的问题来看,我怀疑您是否使用了探查器或类似的工具来衡量 JVM 内存使用情况。相反,您更有可能检查整个 JVM 正在使用的内存。

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

于 2013-05-09T09:40:15.123 回答
0

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

于 2013-05-09T09:25:33.233 回答
0

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

JVM 可能会分配大量内存并且即使在使用它的对象在内部被垃圾处理之后也不会释放它。它可能会在一段时间后被释放或根本不被释放。

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

System.gc()在我看来,就你而言,按照你的做法使用是可以接受的。是否有帮助-我不知道。

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

于 2013-05-09T09:39:03.137 回答
0

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

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

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

尝试自己释放内存意味着给堆提供过多内存(您的应用程序的内存效率不高)并自己触发 GC(您的应用程序也不省时)。

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

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

希望有帮助!

于 2013-05-10T09:14:35.127 回答