JSoup - Java OutOfMemoryError - 在巨大的文件中使用jsoup解析器

时间:2014-05-19 19:58:31

标签: java jsoup

我正在使用jsoup解析器来读取HTML文件并使用提取的数据创建XML文件。我将在一个目录中运行这个代码/脚本,该目录有几个html文件(~250k - 300k文件),有些文件很大。

我遇到了

java.lang.OutOfMemoryError: Requested array size exceeds VM limit" or Java heap space

错误。我尝试使用不同的-Xmx-Xms值运行VM,但我仍然遇到同样的错误。我附上了我的代码段。 我假设读取大文件时发生错误。有关如何解决此问题的任何想法?

String target_dir_output = "/test/";
File dir = new File(target_dir);
File[] files = dir.listFiles();
for (File f : files) {
    if(f.isFile()) {
        String fileName = f.getName();
        String testValue = null;
        try {
            Document doc = Jsoup.parse(f, "UTF-8", "");
            Elements metalinks = doc.select("meta[name=testValue]");
            testValue = metalinks.first().attr("content");
            String output = "<data>" + "\n";
            output += "<testValue>" + testValue + "</testValue>" ;
            output += "</data>";
            FileOutputStream out = new FileOutputStream(fileName + ".xml");
            out.write(output.getBytes());
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

1 个答案:

答案 0 :(得分:4)

Java对程序可以分配的最大数组大小有限制。确切的限制是特定于平台的,但通常介于1到21亿个元素之间。

因此,当您面对java.lang.OutOfMemoryError:请求的数组大小超过VM限制时,手头的应用程序正在尝试分配比Java虚拟机可支持的更大的数组。

JVM中的本机代码引发错误。它在为数组分配内存之前发生,当JVM执行特定于平台的检查时:分配的数据结构是否可在此平台中寻址。

此错误不如您最初想象的那么常见。原因是基于Java数组由int索引的事实。如果你还记得,java中的最大正int是2 ^ 31 - 1 = 2,147,483,647。特定于平台的限制可以非常接近这个数字 - 例如在Java 1.7上的64位MB Pro上,我可以愉快地初始化最多2,147,483,645或Integer.MAX_VALUE-2元素的数组。

将数组的长度增加1,增加到Integer.MAX_VALUE-1会导致抛出熟悉的OutOfMemoryError。

但限制可能不是那么高 - 在使用OpenJDK 6的32位Linux上,在分配一个包含大约11亿个元素的数组时,你会遇到“java.lang.OutOfMemoryError:请求的数组大小超过VM限制”。要了解特定环境的限制,请运行一个小测试找出它。