为什么这种方法占用这么多内存?
Why this method takes so much memory?
我正在尝试解开这个谜团,为什么这种创建目录的方法会占用这么多内存(大约 530MB PS Eden Space)。方法执行后,GC 会清理一些内存,但之后仍会保留一些内存。但分配的内存总是保持不变(大约 700MB 分配所有池)。看来我没有取消引用对象:(
如果有人能给我一些处理建议,那就太好了。
public void writeDir(File root, ArrayList<String> hardwareList, ArrayList<String> detectionListFormated, ArrayList<String> siteName, int depth) {
if (depth == 1) {
return;
}
if (depth == 2) {
for (int i = 0; i < listToDestroy.size(); i++) {
String toBeFormated = listToDestroy.get(i);
String toBeTrimmed = toBeFormated.replace("ä", "ae").replace("ß", "ss").replace("ü", "ue").replace("ö", "oe").trim();
String s = trimLastChar(toBeTrimmed);
int index = s.indexOf("_");
if (s.charAt(index + 1) == this.stationNumber) {
if (s.contains("Manuelle Gruppe")) {
File subdir = new File(root, s);
File samePath = new File(root, "");
subdir.mkdir();
detectionListFormated.remove(i);
listToDestroy.remove(i);
writeDir(samePath, hardwareList, detectionListFormated, siteName, depth);
} else if (s.contains("Automatische Gruppe")) {
File subdir = new File(root, s);
File samePath = new File(root, "");
subdir.mkdir();
detectionListFormated.remove(i);
listToDestroy.remove(i);
writeDir(samePath, hardwareList, detectionListFormated, siteName, depth);
} else if (s.contains("Abschnitt")) {
writeDir(root.getParentFile(), hardwareList, detectionListFormated, siteName, depth + 1);
} else if (s.contains("Stations-Objekt")) {
writeDir(root.getParentFile().getParentFile(), hardwareList, detectionListFormated, siteName, depth + 2);
}
}
}
}
if (depth == 3) {
for (int i = 0; i < listToDestroy.size(); i++) {
String toBeFormated = listToDestroy.get(i);
String toBeTrimmed = toBeFormated.replace("ä", "ae").replace("ß", "ss").replace("ü", "ue").replace("ö", "oe").trim();
String s = trimLastChar(toBeTrimmed);
int index = s.indexOf("_");
if (s.charAt(index + 1) == stationNumber) {
if (s.contains("Abschnitt")) {
File subdir = new File(root, s);
subdir.mkdir();
detectionListFormated.remove(s);
listToDestroy.remove(i);
writeDir(subdir, hardwareList, detectionListFormated, siteName, depth - 1);
} else if (s.contains("Detektions-Objekt")) {
writeDir(root.getParentFile(), hardwareList, detectionListFormated, siteName, depth + 1);
} else if (s.contains("Stations-Objekt")) {
writeDir(root.getParentFile(), hardwareList, detectionListFormated, siteName, depth + 1);
}
}
}
}
if (depth == 4) {
for (int i = 0; i < listToDestroy.size(); i++) {
String toBeFormated = listToDestroy.get(i);
String toBeTrimmed = toBeFormated.replace("ä", "ae").replace("ß", "ss").replace("ü", "ue").replace("ö", "oe").trim();
String s = trimLastChar(toBeTrimmed);
int index = s.indexOf("_");
if (s.charAt(index + 1) == stationNumber) {
if (s.contains("Stations-Objekt")) {
File subdir = new File(root, s);
subdir.mkdir();
listToDestroy.remove(i);
detectionListFormated.remove(i);
// if added it uses literaly no memory at allSystem.gc();
writeDir(root, hardwareList, detectionListFormated, siteName, depth - 3);
} else if (s.contains("Detektions-Objekt")) {
File subdir = new File(root, s);
subdir.mkdir();
listToDestroy.remove(i);
detectionListFormated.remove(i);
// if added it uses literaly no memory at allSystem.gc();
writeDir(subdir, hardwareList, detectionListFormated, siteName, depth - 1);
}
}
}
}
if (depth == 5) {
for (String s : hardwareList) {
String toBeFormated = s;
String toBeTrimmed = toBeFormated.replace("ä", "ae").replace("ß", "ss").replace("ü", "ue").replace("ö", "oe").trim();
String a = trimLastChar(toBeTrimmed);
File subdir = new File(root, a);
subdir.mkdir();
this.stationNumber = a.charAt(0);
// if added it uses literaly no memory at allSystem.gc();
writeDir(subdir, hardwareList, detectionListFormated, siteName, depth - 1);
}
}
if (depth == 6) {
for (String s : siteName) {
String toBeFormated = s;
String toBeTrimmed = toBeFormated.replace("ä", "ae").replace("ß", "ss").replace("ü", "ue").replace("ö", "oe").trim();
String a = trimLastChar(toBeTrimmed);
File subdir = new File(root, a);
subdir.mkdirs();
listToDestroy = new CopyOnWriteArrayList<>(detectionListFormated);
ArrayList<String> test = new ArrayList<>(listToDestroy);
// if added it uses literaly no memory at allSystem.gc();
writeDir(subdir, hardwareList, test, siteName, depth - 1);
}
}
}
}
谢谢:)
您正在使用递归。这意味着您在方法内调用方法本身。
例如:你调用方法,然后它用if语句看它是什么深度,在条件下再次调用方法。但是第一个方法的执行还没有完成,它只是被暂停了,因为新的方法调用是 运行。
这会创建一堆方法调用,可以说是嵌套。每次调用都会有自己的变量,都占用内存..一次又一次...你不应该在它自己内部调用方法!
这是真的,因为您不是在循环中执行此操作,所以您将维护您下方堆栈中的任何内容。我不相信递归是这里的主要问题。我的意思是你只有 6 个深度级别,所以堆栈上最多有 6 个实例。
您是否考虑过使用 nio
库而不是旧的 'io' 库来执行此操作。旧 io
库的 cited problems 之一是它在处理大目录时遇到问题,这与资源处理直接相关。
也就是说,这可以通过循环或 Stack
迭代完成,这也会提高一些内存效率。此外,在后面的 if
语句中使用 else if
。
我正在尝试解开这个谜团,为什么这种创建目录的方法会占用这么多内存(大约 530MB PS Eden Space)。方法执行后,GC 会清理一些内存,但之后仍会保留一些内存。但分配的内存总是保持不变(大约 700MB 分配所有池)。看来我没有取消引用对象:(
如果有人能给我一些处理建议,那就太好了。
public void writeDir(File root, ArrayList<String> hardwareList, ArrayList<String> detectionListFormated, ArrayList<String> siteName, int depth) {
if (depth == 1) {
return;
}
if (depth == 2) {
for (int i = 0; i < listToDestroy.size(); i++) {
String toBeFormated = listToDestroy.get(i);
String toBeTrimmed = toBeFormated.replace("ä", "ae").replace("ß", "ss").replace("ü", "ue").replace("ö", "oe").trim();
String s = trimLastChar(toBeTrimmed);
int index = s.indexOf("_");
if (s.charAt(index + 1) == this.stationNumber) {
if (s.contains("Manuelle Gruppe")) {
File subdir = new File(root, s);
File samePath = new File(root, "");
subdir.mkdir();
detectionListFormated.remove(i);
listToDestroy.remove(i);
writeDir(samePath, hardwareList, detectionListFormated, siteName, depth);
} else if (s.contains("Automatische Gruppe")) {
File subdir = new File(root, s);
File samePath = new File(root, "");
subdir.mkdir();
detectionListFormated.remove(i);
listToDestroy.remove(i);
writeDir(samePath, hardwareList, detectionListFormated, siteName, depth);
} else if (s.contains("Abschnitt")) {
writeDir(root.getParentFile(), hardwareList, detectionListFormated, siteName, depth + 1);
} else if (s.contains("Stations-Objekt")) {
writeDir(root.getParentFile().getParentFile(), hardwareList, detectionListFormated, siteName, depth + 2);
}
}
}
}
if (depth == 3) {
for (int i = 0; i < listToDestroy.size(); i++) {
String toBeFormated = listToDestroy.get(i);
String toBeTrimmed = toBeFormated.replace("ä", "ae").replace("ß", "ss").replace("ü", "ue").replace("ö", "oe").trim();
String s = trimLastChar(toBeTrimmed);
int index = s.indexOf("_");
if (s.charAt(index + 1) == stationNumber) {
if (s.contains("Abschnitt")) {
File subdir = new File(root, s);
subdir.mkdir();
detectionListFormated.remove(s);
listToDestroy.remove(i);
writeDir(subdir, hardwareList, detectionListFormated, siteName, depth - 1);
} else if (s.contains("Detektions-Objekt")) {
writeDir(root.getParentFile(), hardwareList, detectionListFormated, siteName, depth + 1);
} else if (s.contains("Stations-Objekt")) {
writeDir(root.getParentFile(), hardwareList, detectionListFormated, siteName, depth + 1);
}
}
}
}
if (depth == 4) {
for (int i = 0; i < listToDestroy.size(); i++) {
String toBeFormated = listToDestroy.get(i);
String toBeTrimmed = toBeFormated.replace("ä", "ae").replace("ß", "ss").replace("ü", "ue").replace("ö", "oe").trim();
String s = trimLastChar(toBeTrimmed);
int index = s.indexOf("_");
if (s.charAt(index + 1) == stationNumber) {
if (s.contains("Stations-Objekt")) {
File subdir = new File(root, s);
subdir.mkdir();
listToDestroy.remove(i);
detectionListFormated.remove(i);
// if added it uses literaly no memory at allSystem.gc();
writeDir(root, hardwareList, detectionListFormated, siteName, depth - 3);
} else if (s.contains("Detektions-Objekt")) {
File subdir = new File(root, s);
subdir.mkdir();
listToDestroy.remove(i);
detectionListFormated.remove(i);
// if added it uses literaly no memory at allSystem.gc();
writeDir(subdir, hardwareList, detectionListFormated, siteName, depth - 1);
}
}
}
}
if (depth == 5) {
for (String s : hardwareList) {
String toBeFormated = s;
String toBeTrimmed = toBeFormated.replace("ä", "ae").replace("ß", "ss").replace("ü", "ue").replace("ö", "oe").trim();
String a = trimLastChar(toBeTrimmed);
File subdir = new File(root, a);
subdir.mkdir();
this.stationNumber = a.charAt(0);
// if added it uses literaly no memory at allSystem.gc();
writeDir(subdir, hardwareList, detectionListFormated, siteName, depth - 1);
}
}
if (depth == 6) {
for (String s : siteName) {
String toBeFormated = s;
String toBeTrimmed = toBeFormated.replace("ä", "ae").replace("ß", "ss").replace("ü", "ue").replace("ö", "oe").trim();
String a = trimLastChar(toBeTrimmed);
File subdir = new File(root, a);
subdir.mkdirs();
listToDestroy = new CopyOnWriteArrayList<>(detectionListFormated);
ArrayList<String> test = new ArrayList<>(listToDestroy);
// if added it uses literaly no memory at allSystem.gc();
writeDir(subdir, hardwareList, test, siteName, depth - 1);
}
}
}
}
谢谢:)
您正在使用递归。这意味着您在方法内调用方法本身。
例如:你调用方法,然后它用if语句看它是什么深度,在条件下再次调用方法。但是第一个方法的执行还没有完成,它只是被暂停了,因为新的方法调用是 运行。 这会创建一堆方法调用,可以说是嵌套。每次调用都会有自己的变量,都占用内存..一次又一次...你不应该在它自己内部调用方法!
这是真的,因为您不是在循环中执行此操作,所以您将维护您下方堆栈中的任何内容。我不相信递归是这里的主要问题。我的意思是你只有 6 个深度级别,所以堆栈上最多有 6 个实例。
您是否考虑过使用 nio
库而不是旧的 'io' 库来执行此操作。旧 io
库的 cited problems 之一是它在处理大目录时遇到问题,这与资源处理直接相关。
也就是说,这可以通过循环或 Stack
迭代完成,这也会提高一些内存效率。此外,在后面的 if
语句中使用 else if
。