这种方法占用如此多内存的原因是什么?

时间:2015-09-16 07:03:26

标签: java file loops directory-structure mkdirs

我试图调试这个方法,但似乎没有任何作用...
我怀疑在条件语句中pathName.add()是麻烦的。执行此方法后,需要再次执行50 MB,占用150mb,直到达到800mb。但所有都是分配空间。为什么gc不能清理这个烂摊子???

P.s此方法基于已使用条件语句

构造的给定路径创建目录

P.s P.s方法writeDir(...)是从actionListener中调用的(当点击gui ic上的按钮时)。可以点击该按钮

P.s P.s P.s我尝试了安德烈亚斯的建议,并且部分工作。在调用pathName.clean()时,eden空间被droped但已分配的空间仍然在增长达到最大值。

memory snapshot

会对您的意见感兴趣:)谢谢

  

调用writeDir(...)

startButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
            try {
                        progress(0);
                        XMLSaxLogic stax = new XMLSaxLogic(xmlPath);

                        DetectionFilter detectionFilter = new DetectionFilter(stax.getObjets());
                        try {
                            WriteFile writeFile = new WriteFile(detectionFilter.getDetectionList());
                            writeFile.writeDir(savedDirPath, detectionFilter.getHardwareList(), stax.getSiteName());
                            progress(100);
                        } catch (Exception a) {
                            System.out.println(a.getLocalizedMessage());
                        }
                        GetFileCount getFileCount = new GetFileCount(savedDirPath, detectionFilter.getDetectionList(), combo.getSelectedIndex());

                        getFileCount.getFile(savedDirPath.getAbsoluteFile().toString());
                    } catch (Exception a) {
                        System.out.println(a.getLocalizedMessage());
                    }
}
}
  

writeDir(...)

   private ArrayList<String> detectList;
   private String detection = null;
   private String build = null;
   private Set<String> pathName = new LinkedHashSet<>();
   public WriteFile(ArrayList<String> detectList) {
       this.detectList = detectList;
   }
public void writeDir(File root, ArrayList<String> sevenElementList, ArrayList<String> oneElementList) {

    for (String site : oneElementList) {
        for (String s : sevenElementList) {
            int indexx = s.indexOf("_");
            int id = Character.getNumericValue(s.charAt(indexHardware - 1));

            for (String detectionList : detectList) {
                int index = detectionList.indexOf("_");
                int sId = Character.getNumericValue(detectionList.charAt(index + 1));

                if (detectionList.contains("Apple") && sId == id) {
                    detection = site.trim() + "/" + s + "/" + detectionList.trim();
                    pathName.add(format(detection));
                } else if (detectionList.contains("Banana") && sId == id) {
                    build = detection.trim() + "/" + detectionList.trim();
                    pathName.add(format(build.trim()));
                } else if (detectionList.contains("nananana") && sId == id) {
                    pathName.add(format(build.trim() + "/" + detectionList.trim()));
                } else if (detectionList.contains("Watermelone") && sId == id) {
                    pathName.add(format(build.trim() + "/" + detectionList));
                } else if (detectionList.contains("Orange") && sId == id) {
                    pathName.add(format(site.trim() + "/" + s.trim() + "/" + detectionList.trim()));
                }
            }
        }
    }
    createDirTest(pathName, root);
}
private void createDirTest(Set<String> pathArray, File root) {
    for (String s : pathArray) {
        File subdir = new File(root, s);
        subdir.mkdirs();
    }
}

private String format(String toBeFormated) {
    String toBeTrimmed = trimLastChar(toBeFormated.replace("ä", "ae").replace("ß", "ss").replace("ü", "ue").replace("ö", "oe").trim());
    return toBeTrimmed;
}

2 个答案:

答案 0 :(得分:3)

您将所有路径存储在Set<String> pathName 字段中,即使您显示的部分代码仅将其用作createDirTest的参数。

{1}}使用的所有内存在1)清除集合之前不会被释放,或者2)停止引用相关类的实例。

在某些未指定的未来时间点,JVM GC将回收该空间。

如果你真的需要它作为一个字段,为什么要作为参数传递? Set可以访问该字段。如果没有,删除该字段,并声明一个局部变量。

<强>更新

根据评论,该程序即使在使用800MB后也会继续运行。

在这种情况下,它只是JVM的工作方式。该程序没有问题,你只能感觉到你有问题。你没有。

您可以在createDirTest方法结束时调用System.gc() 强制 actionPerformed()之后强制完整垃圾回收声明,但仅用于确认完整GC释放所有使用的内存。仅用于测试,请不要将try电话留在那里。

要查看GC运行,您可以在运行代码时添加gc()-Xloggc:path/to/file.log选项。有关详细信息,请参阅documentation。再次,仅用于测试。

答案 1 :(得分:0)

在意识到单击开始按钮创建了新对象的WriteFile writeFile = new WriteFile(...)GetFileCount getFileCount = new GetFileCount(...)XMLSaxLogic stax = new XMLSaxLogic(...)之后,我已经将thouse对象的创建移动到其他位置(其中只创建一个对象!)。

现在没有内存问题,即使连续点按按钮也不会超过150MB。一切看起来都很正常。但我确信代码中仍然存在一些引用问题但是由于调试主要问题已经消失了:)

获得的经验教训:避免过多地创建太多物体^^

非常感谢@Andreas和@ouflak !!