由大字符串引起的OutOfMemoryException

时间:2013-04-26 13:34:31

标签: java android string out-of-memory

我正在使用以下方法从webapi中捕获数据:

public static String sendRequest(String requestURL, String data)
        throws IOException {
    URL url = new URL(requestURL + "?" + data);
    URLConnection conn = url.openConnection();
    conn.setReadTimeout(10000);
    BufferedReader in = new BufferedReader(new InputStreamReader(
            conn.getInputStream()));

    String inputLine;
    StringBuilder answerBuilder = new StringBuilder("");
    try {
        while ((inputLine = in.readLine()) != null)
            answerBuilder.append(inputLine);
        in.close();
    } catch (Exception e) {
    }

    return answerBuilder.toString();
}

对于一些请求,这会导致由HeapSize太小引起的OutOfMemoryError:

(...)Caused by: java.lang.OutOfMemoryError: (Heap Size=17927KB, Allocated=14191KB, Bitmap Size=2589KB)
at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:95)
at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:132)
at java.lang.StringBuilder.append(StringBuilder.java:272)
at java.io.BufferedReader.readLine(BufferedReader.java:423)
at com.elophant.utils.HTTPUtils.sendRequest(HTTPUtils.java:23)
at (..)

我已经从像String answer += inputLine这样的普通字符串操作交换到了StringBuilder,但这并没有帮助。我怎么解决这个问题?通过export JVM_ARGS="-Xmx1024m -XX:MaxPermSize=256m"增加最大堆大小不是一个选项,因为它是一个Android应用程序。

5 个答案:

答案 0 :(得分:3)

使用文件进行临时存储,例如当硬盘驱动器开始分页时,因为内存不足。

答案 1 :(得分:2)

一种解决方案是将要下载的内容保留为storage

根据您下载的内容,您可以在阅读时解析它并将其存储在SQL Lite DataBase中。这将允许您使用Query语言来处理数据。如果下载的文件是JSON或XML,这将非常有用。

在JSON中,您可以像现在一样获得InputStream并使用JSON Reader读取流。对于从JSON读取的每个记录,您可以存储在一个表中(或者更多表,具体取决于每个记录的结构)。这种方法的好处在于,最后您不需要文件处理,并且您已经将数据分布在数据库中的表中,以便进行查询。

答案 2 :(得分:1)

您应该将stringbuilder内容写入文件并不时清除它。

答案 3 :(得分:1)

如果您的String真的那么大,您需要暂时将其存储在一个文件中并以块的形式处理它(或者在收到它时以块的形式处理它)

答案 4 :(得分:0)

不是胆小的人,而是编写自己的MyString类,每个char使用一个字节〜50%的内存节省!并且肯定地,MyStringBuilder上课。只假设您正在处理ASCII。