繁体   English   中英

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

[英]Java/Android: java.lang.OutOfMemoryError while building a JSON object

我从公共数据库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.OutOfMemoryError指向buildr.append(line).append("\\n")的错误源buildr.append(line).append("\\n") 无论如何,我可以处理大型数据集而不会出现内存分配问题吗?

JSON很大!

您肯定需要使用流式JSON解析器。 Android有两个版本:GSON和Jackson。

GSON Streaming的解释如下: https//sites.google.com/site/gson/streaming

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

大多数应用程序应仅使用对象模型API。 JSON流媒体在以下几种情况下很有用:

当不可能或不希望将整个对象模型加载到内存中时。 这在内存有限的移动平台上最为相关。

Jackson Streaming记录于: http//wiki.fasterxml.com/JacksonInFiveMinutes#Streaming_API_Example

如果可能的话,只请求部分数据 - 这也减少了网络的时间,从而节省了电池。

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

你可以看看杰克逊 ,它有一个流媒体模式,可能适用。

Streaming pull解析器就是这样。 我推荐GSON,因为它有一个小内存footpring(只需拉解析约16K,杰克逊更大)

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

  • buffer来保存来自服务的所有字符串数据
  • 所有JSON DOM对象

这很慢,并且让你内存崩溃。

如果您需要JSON数据中的Java对象,您可以尝试在GSON上构建我的小型数据绑定库(羞辱自我广告关闭):

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;
            }           
        } 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM