我需要浏览大约 3000 个文件夹,每个文件夹包含 300 个 CSV 文件。
这是在((nextLine=csvReader.readNext()) != null)
时在行上发生的错误:
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded
at au.com.bytecode.opencsv.CSVParser.parseLine(CSVParser.java:206)
at au.com.bytecode.opencsv.CSVParser.parseLineMulti(CSVParser.java:174)
at au.com.bytecode.opencsv.CSVReader.readNext(CSVReader.java:237)
at DA.readTelemetryData(DA.java:78)
at DA.main(DA.java:24)
问题是如何解决这个问题?为什么会发生这种情况,我的代码中出了什么问题?
在这里我提供代码:
private static HashMap<Integer,HashMap<Integer,List<double[]>>> readTelemetryData() throws Exception
{
HashMap<Integer,HashMap<Integer,List<double[]>>> xy_total = new HashMap<Integer,HashMap<Integer,List<double[]>>>();
for (int i=0; i<Constants.MAX_FOLDERS; i++)
{
HashMap<Integer,List<double[]>> xy_total_per_folder= new HashMap<Integer,List<double[]>>();
for (int j=0; j<Constants.MAX_FILES_INSIDE_FOLDER; j++)
{
CSVReader csvReader = null;
File f = new File("data/"+ (i+1) +"/"+ (j+1) +".csv");
if(f.exists())
{
csvReader = new CSVReader(new FileReader(f));
List<double[]> xyArr = new ArrayList<double[]>();
String[] firstLine=csvReader.readNext();
if (firstLine != null)
{
String[] nextLine=null;
while ((nextLine=csvReader.readNext()) != null)
{
double[] d = new double[2];
d[0]=Double.parseDouble(nextLine[0]);
d[1]=Double.parseDouble(nextLine[1]);
xyArr.add(d);
}
}
xy_total_per_folder.put(j, xyArr);
csvReader.close();
}
}
xy_total.put(i, xy_total_per_folder);
}
return xy_total;
}
内存不足。
HashMap<Integer,V>
是一个相当糟糕的选择。它需要 16 个字节作为密钥,每个条目可能需要 24 个字节 + 死区。然后,您的double[]
需要 32 字节(用于存储 16 字节的有效负载)。在数组列表中,您需要另外 4 个字节作为参考...
例如,每行将花费您 36 个字节的 instad 16。
请考虑使用更紧凑的数据结构。GNU Trove 是一个为基元类型提供大量收藏的库;但不要低估数组的价值...
对于处理大量的基元类型(int
、double
等),请远离java.util.
集合。相反,花额外的时间来组织你的记忆。
例如,您可以使用 Trove 的 TDoubleArrayList
,一个用于所有 x 值,一个用于所有 y 值,而不是为每行使用一个数组。读取完文件后,可以将它们转换为最小double[] x; double[] y;
数组,并重用TDoubleArrayList
来分析下一个文件。
最后但并非最不重要的一点是,Java 默认只使用内存的 25%。 使用-Xmx
来增加限制。
运行内存探查器。大部分内存分配在哪里?所有这些都需要吗?也许您正在使用的 CSV 浏览器有内存泄漏!使用内存探查器是一种简单的查找方法。
但是要算一算。你有多少行 - 你能把它们全部放进内存里吗?
这种行为通常有两个原因:
-
内存泄漏。这意味着您编程存储不再需要的数据。分析要修复的内存转储。
-
内存不足,因为您的编程实际上需要那么多内存。哟可以简单地给它更多的记忆。或者尝试更改算法和数据结构。