java - 将文本文件加载到列表时出现内存不足错误,即使我指定了足够大的 xmx

标签 java list collections out-of-memory heap-memory

当我尝试使用 -Xms32m -Xmx128m 加载列表中的 39MB 文本时出现内存不足错误。所以我开始一点一点地增加Xmx,直到加载成功,发现我至少需要Xmx170m才能加载内存中的39MB文件

我想知道,为什么我需要这么大的内存?我尝试使用 UTF-8、UTF-16 和 UTF-32 计算在列表中分配的内存量,但在出现内存不足异常时,它们似乎都不匹配 Xmx。那么计算分配内存的正确方法是什么?

有人可以解释一下我在这里遗漏了什么吗?

下面是带有 at -Xms32m -Xmx128m 的输出和代码示例

Max memory 129 MB.
Total memory 32 MB.
Free memory 32 MB.
Input file size 39 MB.
Out Of Memory Error
List size in UFT-8 29 MB.
List size in UFT-16 58 MB.
List size in UFT-32 116 MB.
Free memory 4 MB.
End 

java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Unknown Source)
    at java.util.Arrays.copyOf(Unknown Source)
    at java.util.ArrayList.ensureCapacity(Unknown Source)
    at java.util.ArrayList.add(Unknown Source)
    at com.nrx.util.SortUtil.main(SortUtil.java:288)



public static void main(String[] args)
{
    System.out.println("Max memory "+Runtime.getRuntime().maxMemory()/1000 /1000+" MB.");
    System.out.println("Total memory "+Runtime.getRuntime().totalMemory()/1000 /1000+" MB.");
    System.out.println("Free memory "+Runtime.getRuntime().freeMemory()/1000 /1000+" MB.");

    long utf8 = 0;
    long utf16 = 0;
    long utf32 = 0;
    List<String> strList = new ArrayList<String>();
    try 
    {
        File inFile = new File("data/input38.log");
        System.out.println("Input file size "+inFile.length()/1000 /1000+" MB.");
        BufferedReader fileReader = new BufferedReader(new FileReader(inFile));
        String line = fileReader.readLine();
        while (line != null)
        {
            utf8 = utf8 + line.getBytes("UTF-8").length;
            utf16 = utf16 + line.getBytes("UTF-16").length;
            utf32 = utf32 + line.getBytes("UTF-32").length;

            StringTokenizer st = new StringTokenizer(line, " ");
            while(st.hasMoreTokens())
                strList.add(st.nextToken().trim());
            line = fileReader.readLine();
        }

    } 
    catch (OutOfMemoryError e) 
    {
        System.out.println("Out Of Memory Error ");
        System.out.println("List size in UFT-8 "+utf8/1000 /1000+" MB.");
        System.out.println("List size in UFT-16 "+utf16/1000 /1000+" MB.");
        System.out.println("List size in UFT-32 "+utf32/1000 /1000+" MB.");
        System.out.println("Free memory "+Runtime.getRuntime().freeMemory()/1000 /1000+" MB.");
        e.printStackTrace();
    }
    catch (FileNotFoundException e) 
    {
        e.printStackTrace();
    } 
    catch (IOException e) 
    {
        e.printStackTrace();
    }
    System.out.println("End ");
}

最佳答案

我相信这是因为您正在使用 ArrayList。 ArrayList 是对简单数组的智能包装。当列表增长时,ArrayList 创建新数组并将旧内容复制到新数组。首先,效率极低。其次,它每次都需要列表三倍大小:旧数组中的 n 个元素和新数组中的 n*2 个元素。

因此,尝试使用 LinkedList 代替。我希望它对你有用。

关于java - 将文本文件加载到列表时出现内存不足错误,即使我指定了足够大的 xmx,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9180655/

相关文章:

python - 如何将 2 个输出一个作为键,另一个作为值存储在字典中

java - 使用 Google Guava 过滤 JavaBean 列表

java - 如何更新 Spark 流中的广播变量?

java - 使用 Java 将 PDF 转换为 Swf

r - 基于另一个数据框在数据框中扩展行和添加列

使用子字符串检查字符串是否存在(使用链表)

c# - 使用分组依据以删除重复项

java - org.postgresql.util.PSQLException : ERROR: relation "sequence-gen" does not exist

Java 优先级队列 : Is it better to poll() and then add() or peek() and then remove()

java - 我如何在 Eclipse 中使用 maven shade 插件