如何删除Java OutOfMemoryError
我有一个程序,它获取了一个非常大的txt数据,并改变了这个txt数据中某些列的顺序。有关它的具体功能的更多详细信息,请参见我的问题。我使用带有映射的列表,我可以想象这对于java虚拟机来说太多了,因为txt文件有400000个条目,但我不知道还能做什么。我用一个较小的txt文件试过,然后效果很好。否则它会运行一个多小时,然后我会得到一个OutOfMemory错误 这是我的密码:如何删除Java OutOfMemoryError,java,out-of-memory,Java,Out Of Memory,我有一个程序,它获取了一个非常大的txt数据,并改变了这个txt数据中某些列的顺序。有关它的具体功能的更多详细信息,请参见我的问题。我使用带有映射的列表,我可以想象这对于java虚拟机来说太多了,因为txt文件有400000个条目,但我不知道还能做什么。我用一个较小的txt文件试过,然后效果很好。否则它会运行一个多小时,然后我会得到一个OutOfMemory错误 这是我的密码: import java.io.BufferedReader; import java.io.File; import
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class Final {
public static void main(String[] args) {
String path = "C:\\\\\\\\Users\\\\\\\\Ferid\\\\\\\\Downloads\\\\\\\\secdef\\\\\\\\secdef.txt";
File file = new File(path);
new Final().updateFile(file);
}
private void updateFile(File file) {
List<String> allRows = getAllRows(file);
String[] baseRow = allRows.get(0).split("\\|");
List<String> columns = getBaseColumns(baseRow);
System.out.println(columns.size());
appendNewColumns(allRows, columns);
System.out.println(columns.size());
List<Map<String, String>> mapList = convertToMap(allRows, columns);
List<String> newList = new ArrayList<String>();
appendHeader(columns, newList);
appendData(mapList, newList, columns);
String toPath = "C:\\\\\\\\Users\\\\\\\\Ferid\\\\\\\\Downloads\\\\\\\\secdef\\\\\\\\finalz2.txt";
writeToNewFile(newList, toPath);
}
/**
* Gibt alle Zeilen aus der Datei zurück.
*/
private static List<String> getAllRows(File file) {
List<String> allRows = new ArrayList<>();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
String row = null;
int i = 0;
while ((row = reader.readLine()) != null) {
allRows.add(row);
}
} catch (IOException e) {
e.printStackTrace();
}
return allRows;
}
/**
* Gibt die Hauptspalten aus der 1. Zeile zurück.
*/
private static List<String> getBaseColumns(String[] baseRow) {
List<String> columns = new ArrayList<>();
for (String rowEntry : baseRow) {
String[] entry = rowEntry.split("=");
columns.add(entry[0]);
}
return columns;
}
/**
* Fügt alle neuen Spalten hinzu.
*/
private static void appendNewColumns(List<String> rows, List<String> columns) {
for (String row : rows) {
String[] splittedRow = row.split("\\|");
for (String column : splittedRow) {
String[] entry = column.split("=");
if (columns.contains(entry[0])) {
continue;
}
columns.add(entry[0]);
}
}
}
/**
* Konvertiert die Listeneinträge zu Maps.
*/
private static List<Map<String, String>> convertToMap(List<String> rows, List<String> columns) {
List<Map<String, String>> mapList = new ArrayList<>();
for (String row : rows) {
Map<String, String> map = new TreeMap<>();
String[] splittedRow = row.split("\\|");
List<String> rowList = Arrays.asList(splittedRow);
for (String col : columns) {
String newCol = findByColumn(rowList, col);
if (newCol == null) {
map.put(col, "null");
} else {
String[] arr = newCol.split("=");
map.put(col, arr[1]);
}
}
mapList.add(map);
}
return mapList;
}
/**
*
*/
private static String findByColumn(List<String> row, String col) {
return row.stream().filter(o -> o.startsWith(col)).findFirst().orElse(null);
}
/**
* Fügt die Header-Zeile in die neue Liste hinzu.
*/
private static void appendHeader(List<String> columns, List<String> list1) {
String header = "";
for (String column : columns) {
header += column + "|";
}
list1.add(header + "\n");
}
/**
* Fügt alle Daten in die entsprechenden neuen Dateien hinzu.
*/
private static void appendData(List<Map<String, String>> mapList, List<String> list1, List<String> columns) {
for (Map<String, String> entry : mapList) {
String line = "";
for (String key : columns) {
// for (String key : entry.keySet()) {
line += entry.get(key) + "|";
}
list1.add(line + "\n");
}
}
/**
* Schreibt alle Werte in die neue Datei.
*/
private static void writeToNewFile(List<String> list, String path) {
FileOutputStream out = null;
try {
out = new FileOutputStream(new File(path));
for (String line : list) {
out.write(line.getBytes());
}
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
您可以通过指定:-Xmx指定JVM可以使用的最大内存 例如-Xmx8G,
使用M或G我们实际上无法给出分配内存量的具体建议,因为这在很大程度上取决于您的服务器设置、用户群的大小以及他们的行为。您需要找到一个适合您的值,即没有明显的GC暂停,也没有OutOfMemory错误 作为参考,用于更改内存堆分配的3个最常见参数为: Xms—堆的最小大小 Xmx-堆的最大大小 XX:MaxPermSize-PermGen的最大大小这在Java 8及更高版本中未使用 如果您确实决定增加内存设置,则需要遵循一些一般准则 以小的增量增加Xmx,例如每次512mb,直到 经历OutOfMemory错误的时间越长。这是因为 堆超出了服务器的能力,因此无法充分回收垃圾 收集可能会导致其他问题,例如性能/冻结 如果您的错误是java。朗。OutOfMemoryError:永久空间, 以256mb的增量增加-XX:MaxPermSize参数,直到 错误停止发生。 如果您的错误未引用PermGen,则无需 增加它。简单地说,PermGen用于存储 类,并且在大小上通常是静态的,并且已被删除 在Java8中。更多信息请点击这里。考虑将XMS和XMX设置为相同 值,因为这可以减少GC发生所需的时间 不要尝试在每个集合上调整堆的大小。 如果在Windows上启动Confluence作为服务,则不应使用这些说明。请参阅下面的Windows服务部分 只有在通过批处理文件启动Confluence时,才应遵循这些说明。当Confluence作为服务启动时,不使用批处理文件 要在Windows安装中从.bat文件启动时配置系统属性 停堆汇流 从/bin单机版或/bin EAR-WAR安装,打开setenv.bat。 找到该部分 CATALINA_OPTS=-Xms1024m-Xmx1024m-XX:+UseG1GC$CATALINA_OPTS在汇流5.8或以上 CATALINA_OPTS=$CATALINA_OPTS-Xms1024m-Xmx1024m-XX:MaxPermSize=256m-XX:+UseG1GC在汇流5.6或5.7中 在以前的版本中,JAVA_OPTS=-Xms256m-Xmx512m-XX:MaxPermSize=256m Xmx是最大值,Xms是最小值,MaxPermSize是PermGen。 起始汇流
在这种情况下,如果可能的话,可以逐行读取文件并分别处理每一行,而不是将整个文件保存在内存中 当前,您的代码如下所示:
BufferedReader reader = null;
BufferedWriter writer = null;
try {
reader = new BufferedReader(new FileReader(file));
String row = null;
int i = 0;
List<String> columns = new ArrayList<>();
while ((row = reader.readLine()) != null) {
columns.addAll(getColumns(row));
}
reader = new BufferedReader(new FileReader(file));
writer = new BufferedWriter(new FileWriter(outFile));
int i = 0;
while ((row = reader.readLine()) != null) {
writeRow(row, columns, writer);
}
} catch (IOException e) {
e.printStackTrace();
}
将所有行读入列表L
对于L中的每一行,查找所有列
在映射中使用空字符串将L中的行转换为映射,而不是不设置值!!这可能是最终真正让你心痛的原因!
将映射序列化为行
我只需要增加可用内存就可以调用bs,然后它稍后就会失败。您在内存使用和性能方面存在一般性问题。让我提出另一种方式:
1. for each line read (don't read the whole file at once!):
1.1 find columns, collect in List C
2. for each line read (again, don't read the whole file at once, do it as you read):
2.2 for each column in C, write value if the row contains it, or null
2.3 append to the result file (also don't keep the result in memory!)
有点像这样:
BufferedReader reader = null;
BufferedWriter writer = null;
try {
reader = new BufferedReader(new FileReader(file));
String row = null;
int i = 0;
List<String> columns = new ArrayList<>();
while ((row = reader.readLine()) != null) {
columns.addAll(getColumns(row));
}
reader = new BufferedReader(new FileReader(file));
writer = new BufferedWriter(new FileWriter(outFile));
int i = 0;
while ((row = reader.readLine()) != null) {
writeRow(row, columns, writer);
}
} catch (IOException e) {
e.printStackTrace();
}
你给Java分配了多少内存?@JFMeier在哪里可以看到这个?