Java / Android:构buildJSON对象时的java.lang.OutOfMemoryError

我从一个公共数据库URI http://data.seattle.gov/api/views/3k2p-39jp/rows.json导入JSON数据,行最远达到445454.使用下面的代码我构造了JSON对象的整个数据。

HttpGet get = new HttpGet(uri); HttpClient client = new DefaultHttpClient(); HttpResponse response = client.execute(get); BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8")); StringBuilder builder=new StringBuilder(); for(String line=null;(line = reader.readLine()) != null;){ builder.append(line).append("\n"); } JSONTokener jsonTokener=new JSONTokener(builder.toString()); JSONObject finalJson=new JSONObject(jsonTokener); JSONArray data=finalJson.getJSONArray("data"); 

因为数据太大,我得到03-21 03:41:49.714: E/AndroidRuntime(666): Caused by: java.lang.OutOfMemoryErrorbuildr.append(line).append("\n") 。 无论如何,我可以处理大型数据集没有得到内存分配问题?

Solutions Collecting From Web of "Java / Android:构buildJSON对象时的java.lang.OutOfMemoryError"

这JSON是巨大的!

您肯定需要使用stream式JSONparsing器。 有两个Android:GSON和jackson。

GSONstream媒体在https://sites.google.com/site/gson/streaming解释

我喜欢GSON如何解释您遇到的问题:

大多数应用程序应该只使用对象模型API。 JSONstream在几种情况下是有用的:

当将整个对象模型加载到内存中是不可能或不可取的。 这在内存有限的移动平台上最为重要。

Jackson Streaminglogging在: http : //wiki.fasterxml.com/JacksonInFiveMinutes#Streaming_API_Example

如果可能的话,只要求数据的一部分 – 这也减less了networking的时间,从而节省电池。

否则,您可以尝试不将传入的数据保存在内存中,而是将其“stream”到SD卡上。 当它存储在那里,你可以迭代它。 这很可能意味着使用自己的JSON标记器,它不会构build完整的树,但是能够(像SAXparsing器)一次只查看对象树的一部分。

你可以看看jackson ,它有一个可能适用的stream模式。

stream式parsing器就是这样的。 我推荐GSON,因为这有小的内存footpring(只需拉parsing约16K,jackson是更大的)

你的代码是有问题的,因为你分配:

  • 缓冲区来保存来自服务的所有string数据
  • 所有的JSON DOM对象

这很慢,并给你内存崩溃。

如果你需要从JSON数据中取出java对象,你可以试试我在GSON上构build的小型数据绑定库(shameles self advert off):

https://github.com/ko5tik/jsonserializer

我做了一点不同的事情,我的JSON代码正在等待状态,最终结束。 所以我修改了代码以便返回。

 // try to get formattedAddress without reading the entire JSON String formattedAddress; while ((read = in.read(buff)) != -1) { jsonResults.append(buff, 0, read); formattedAddress = ((String) ((JSONObject) new JSONObject( jsonResults.toString()).getJSONArray("results").get(0)) .get("formatted_address")); if (formattedAddress != null) { Log.i("Taxeeta", "Saved memory, returned early from json") ; return formattedAddress; } } JSONObject statusObj = new JSONObject(jsonResults.toString()); String status = (String) (statusObj.optString("status")); if (status.toLowerCase().equals("ok")) { formattedAddress = ((String) ((JSONObject) new JSONObject( jsonResults.toString()).getJSONArray("results").get(0)) .get("formatted_address")); if (formattedAddress != null) { Log.w("Taxeeta", "Did not saved memory, returned late from json") ; return formattedAddress; } }