繁体   English   中英

尝试将大型json数据发送到android中的服务器时出现OutOfMemoryException?

[英]OutOfMemoryException while trying to send large json data to server in android?

我正在尝试一次将多个Json字符串[每个1 MB]发送到PHP Server。 当我尝试发送10条记录时,它的工作正常。 但是,如果超过20条记录,则会显示OutOfMemoryException 我看到android内存大小限制为t0 15MB-16MB。 但是还没有任何解决办法的线索,我正在使用下面的代码一次发送多个记录。

 /** Upload Data*/
private void submitUploadData(String url, Map<String, String> param)
        throws IOException {
    URL siteUrl;
    try {
        siteUrl = new URL(url);
        HttpURLConnection conn = (HttpURLConnection) siteUrl
                .openConnection();
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
        conn.setDoInput(true);

        DataOutputStream out = new DataOutputStream(conn.getOutputStream());
        String content1 = ""; 

        Set getkey = param.keySet();
        Iterator keyIter = getkey.iterator();
        String content = "";
        for (int i = 0; keyIter.hasNext(); i++) {
            Object key = keyIter.next();
            if (i != 0) {
                content += "&"; //Crashing here
            }
            content += key + "=" + param.get(key); //Crashing here
            System.out.println("Content" + content);
        }

        System.out.println(content);
        out.writeBytes(content.trim());
        out.flush();
        out.close();

        BufferedReader in = new BufferedReader(new InputStreamReader(
                conn.getInputStream()));
        String jsonresponse = "";
        while ((jsonresponse = in.readLine()) != null) {
            System.out.println(jsonresponse);   
            if(!jsonresponse.equals("Authorisation Successful")){
            updateUploadRecords(jsonresponse);}

        }
        in.close();  

    } catch (MalformedURLException e) {
        e.printStackTrace();
    } 
}

乍一看,您的代码没有任何问题,但是您正在使用各种可能导致内存浪费的方法,而现在您正在尝试用尽内存的大型操作,那肯定会发生。

提示:

  • 不要使用刚在内存中创建了3个新字符串的str1 += str2 + "other val"字符串。 请改用StringBuilder。
  • 调用System.gc()(某些人会建议您)将无济于事,因为您正在循环中执行此操作,并且该方法仅暗示系统可能是进入GC的好时机,但直到系统实际运行四处走动,您已经崩溃了。
  • 如果每个JSON字符串的大小都在1mb左右,并且您要传递其中的20个,则您已经因为那20mb而在旧设备上内存不足而崩溃。 您将不得不重新设计很多东西,但是我的建议是只删除Map,完全删除它。

相反,您应该(在创建该地图的方法上)使用某种类型的OutputStream写入已经在临时文件中格式化的所有数据。 然后,要上传,您将使用某种类型的InputStream来读取此文件并写入您的DataOutputStream

除Streams之外,还可以使用其他一些基于与Streams相同的方法的类,它们是:JsonWriter / JsonReader,但是如果不是特定的Json,您也可以使用FileWriter / FileReader,并且不要忘记总是用BufferedReader和BufferedWriter包装它们。

通过个人经验,我发现超出一定大小(取决于设备),使用String串联来形成/下载实体是不可行的。

在您的情况下,使用JsonWriter会有所帮助。 它将json令牌写入流,并且不会占用额外的内存。 当您下载笨重的json文档时,请使用JsonReader

我已经成功地使用了这两个类。

可能受虚拟设备的内存大小限制!

您是否尝试过给它更大的内存!?

您正在用对象遍历它。 您可能会冒着保留副本等的风险。回到基础知识,尝试使用String.split('');函数String.split(''); 然后以正常循环遍历它。 然后,您知道哪些对象在内存中。 进行拆分时,您将获得两个占用内存的对象,即原始字符串和拆分产生的数组。

在拆分原始字符串的那一刻,您可以将原始字符串设置为null以释放垃圾回收器的内存(甚至可以调用System.gc()

然后只需简单地循环遍历字符串即可进行操作,使占用空间尽可能小。

暂无
暂无

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

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