【问题标题】:Files reading: Out of memory error文件读取:内存不足错误
【发布时间】:2014-12-24 17:23:08
【问题描述】:

我需要浏览大约 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;
    }

【问题讨论】:

  • 你有什么问题?
  • @talex:问题是如何解决这个问题?为什么会发生,我的代码有什么问题?我认为我应该避免使用 HashMap,但我不确定。
  • 你的代码没问题。如果您需要所有这些数据,这是一个简单的解决方案。增加内存限制。用-XMX=1G运行java
  • 对不起。标志是-Xmx=1g
  • @talex:好的,谢谢。但是在这种情况下使用 HashMap 是个好主意吗? HashMaps 比数组慢得多吗?

标签: java filereader opencsv


【解决方案1】:

您的内存不足。

HashMap&lt;Integer,V&gt; 是一个相当糟糕的选择。它需要 16 个字节作为密钥,每个条目可能需要 24 个字节 + 死区。您的 double[] 然后需要 32 个字节(用于存储 16 个字节的有效负载)。在数组列表中,还需要另外 4 个字节作为引用...

例如,每行将花费您 36 个字节而不是 16 个字节。

考虑使用更紧凑的数据结构。 GNU Trove 是一个为原始类型提供大量集合的库;但不要小看数组的价值……

要处理大量原始类型(intdouble 等),请远离 java.util. 集合。相反,花更多时间整理你的记忆。

例如,您可以使用 Trove 的TDoubleArrayList,一个用于所有 x 和一个用于所有 y 值,而不是为每一行使用一个数组。读取完文件后,您可以将它们转换为最小的double[] x; double[] y; 数组,并重复使用TDoubleArrayList 来解析下一个文件。

最后但同样重要的是,Java 默认只使用 25% 的内存。使用-Xmx 增加限制。

运行内存分析器。大部分内存分配在哪里?这一切都需要吗?也许您正在使用的 CSVReader 存在内存泄漏!使用内存分析器是一种简单的查找方法。

但是算一算吧。你有多少行 - 可以你将它们全部放入内存吗?

【讨论】:

    【解决方案2】:

    这种行为一般有两个原因:

    1. 内存泄漏。这意味着您对不再需要的存储数据进行编程。分析内存转储以修复。

    2. 内存不足,因为您的程序实际上需要那么多内存。哟可以简单地给它更多的内存。或者尝试改变你的算法和数据结构。

    【讨论】:

      猜你喜欢
      • 2014-07-22
      • 2021-04-30
      • 1970-01-01
      • 2016-01-02
      • 2015-07-27
      • 2023-04-09
      • 2017-10-03
      • 2012-11-05
      • 2011-09-18
      相关资源
      最近更新 更多