由大字符串引起的OutOfMemoryException

我使用以下方法从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操作(如String answer += inputLine到StringBuilder,但这没有帮助。 我怎么解决这个问题? 通过export JVM_ARGS="-Xmx1024m -XX:MaxPermSize=256m"增加最大堆大小export JVM_ARGS="-Xmx1024m -XX:MaxPermSize=256m"不是一个选项,因为它是一个Android应用程序。

一种解决方案是将要下载的内容持久保存到存储中 。

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

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

使用文件进行临时存储,就像硬盘驱动器开始分页一样,因为内存不足。

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

如果你的String真的很大,你需要暂时将它存储在一个文件中并以块的forms处理它(或者在收到它时以块的forms处理它)

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