2

我正在尝试调试此方法,但似乎没有任何效果...
我怀疑在条件语句中 pathName.add() 正在引起麻烦。执行此方法后,它会占用 50 MB,再执行一次它会占用 150 MB,直到达到 800 MB。但一切都是分配的空间。为什么 gc 不清理这个烂摊子???

Ps 此方法基于已用条件语句构造的给定路径创建目录

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

Ps Ps Ps 我已经尝试了 Andreas 的建议,它部分工作。调用 pathName.clean() 后,伊甸园空间下降,但分配的空间仍在增长,达到最大值。

内存快照

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

调用 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());
                    }
}
}

写入目录(...)

   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;
}
4

2 回答 2

3

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

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

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

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


更新

根据评论,即使使用了 800MB,该程序仍会继续运行。

在这种情况下,这就是 JVM 的工作方式。该程序可以正常运行,而您只是认为自己有问题。你没有。

您可以通过在方法的末尾、语句之后调用来强制进行完整的垃圾回收,但只是为了确认完整的 GC 会释放所有使用的内存。仅用于测试,请勿将电话留在那里。System.gc()actionPerformed()trygc()

要查看 GC 运行情况,您可以在运行代码时添加-Xloggc:path/to/file.log-XX:+PrintGCDetails -XX:+PrintGCTimeStamps选项。有关更多详细信息,请参阅文档。再次,仅用于测试。

于 2015-09-16T07:20:23.570 回答
0

在意识到单击开始按钮创建了新对象WriteFile writeFile = new WriteFile(...)之后,GetFileCount getFileCount = new GetFileCount(...)XMLSaxLogic stax = new XMLSaxLogic(...)将 thouse 对象的创建移到了其他地方(那里只会创建一个!)。

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

经验教训:避免过于频繁地创建太多对象^^

非常感谢@Andreas 和@ouflak !!

于 2015-09-16T08:27:41.793 回答