【问题标题】:Wordlist generator, heap size error in JavaWordlist 生成器,Java 中的堆大小错误
【发布时间】:2018-04-13 14:16:45
【问题描述】:

我正在尝试创建一个程序,该程序根据几个 (10-100) 原始输入单词生成单词列表。最终结果包含数百万行,可能是数十亿行,每行一个单词。我已经走得够远了,我可以生成大约 500 万左右的单词,但是每当我运行会生成更多单词的东西时,比如 1 亿左右,程​​序在大约 1 分 9 秒后崩溃。这是错误输出:

    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3210)
    at java.util.Arrays.copyOf(Arrays.java:3181)
    at java.util.ArrayList.grow(ArrayList.java:265)
    at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
    at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
    at java.util.ArrayList.add(ArrayList.java:462)
    at wordlistgen.WordlistGen2.combineWords(WordlistGen2.java:129)
    at wordlistgen.WordlistGen2.main(WordlistGen2.java:25)
    /home/NAME/.cache/netbeans/8.1/executor-snippets/run.xml:53: Java 
returned: 1
BUILD FAILED (total time: 1 minute 9 seconds)

我尝试通过在我的 netbeans.conf 文件(运行 Ubuntu 17.10)中输入 -J-Xms1024m -J-Xmx2048m 来增加 Netbeans 的堆大小,但错误仍然存​​在。

程序所做的基本上是导入原始的 10-100 个单词:

static void importList() throws IOException{
    ArrayList<String> rawList = new ArrayList<>();

    try(BufferedReader br = new BufferedReader(new FileReader("textfile"))) {
        for(String line; (line = br.readLine()) != null; ) {
            rawList.add(line);
        }

        listOfLists.add(rawList);
        loll++;
    }

}

然后,通过一堆 for 循环,我创建了带有大写字母、末尾数字、整个单词的子字符串等的单词的新变体。单词存储在不同的数组列表中,这些数组列表又存储在 ArrayList 的 ArrayList 中。所以在一个 ArrayList 中。

当我完成组合和操作单词后,我使用以下方法将整个最终数组列表逐行输出到输出文件:

static void outputFile(String fileName) throws IOException{
    try (FileWriter writer = new FileWriter(fileName)) {
        for(String str: finalList) {
            writer.write(str +"\n");
        }
    }
}

完整的代码可以在这里找到:https://pastebin.com/0fkvwYbx

我希望我遗漏了一些明显的东西,或者我误解了错误消息,无论哪种方式,如果有人能找到解决方案以便我能够生成更长的列表,我将非常感激.

【问题讨论】:

  • 生成单词的时候不能直接写入文件吗?还是一堆字?我的意思是,将它们保存在内存中真的有好处吗?
  • 我认为你是因为试图破解密码而受到编程之神的惩罚。
  • 你给它最多 2G 的内存并生成 100M 的东西。除非这些东西中的每一个都占用不到 20 个字节,否则肯定会耗尽内存。请注意,所有 Java 对象在对这些对象的任何引用(包括对象引用的空间,如 ArrayList 的支持数组)之上至少占用 12 个字节。因此,内存不足听起来完全合理。
  • 如果您分享生成密码变体的代码,我们或许可以提供帮助。
  • 尝试分配 4G RAM 而不是 2G。在我看来,发生错误所花费的时间应该翻了一番。但它仍然是 1 分 9 秒,这是否意味着其他原因导致了问题?平安迪:)

标签: java heap-memory word-list


【解决方案1】:

也许 ArrayList 不适合您的问题的 List 实现。请看:When to use LinkedList over ArrayList?

我认为你在(引用)时经常遇到最坏的情况

add(E element) 是 O(1) 摊销,但 O(n) 最坏情况,因为数组 必须调整大小并复制

不仅时间效率低,而且内存效率低,因为您不断需要为 ArrayLists 复制大量的后备数组。考虑使用 LinkedList,特别是因为您的代码似乎没有通过索引对列表进行随机访问

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-04
    • 2011-11-24
    • 2015-05-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多