2

我正在尝试一次将多个 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();
    } 
}
4

4 回答 4

4

乍一看,您的代码没有任何问题,但是您正在使用以浪费内存而闻名的所有可能类型的方法,并且现在您正在尝试内存不足的大型操作,这是肯定会发生的。

尖端:

  • 不要用str1 += str2 + "other val"你刚刚在内存中创建 3 个新字符串来连接字符串。请改用 StringBuilder。
  • 调用 System.gc() (有些人会建议你)对你没有帮助,因为你在一个循环中执行这个操作,而那个方法只会提示系统它可能是 GC 的好时机,但直到系统实际赶紧去做吧,你已经崩溃了。
  • 如果每个 JSON 字符串大约为 1mb 并且您传递了其中的 20 个,那么您已经在具有 20mb 的旧设备上因内存不足而崩溃。您将不得不重新设计很多东西,但我的建议是删除地图,完全删除它。

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

Streams 的替代方法是使用基于与流相同的方法的其他一些类,它们是:JsonWriter/JsonReader,但是如果不是特定的 Json,那么你也有 FileWriter/FileReader,并且不要忘记总是用 BufferedReader 和 BufferedWriter 包装它们。

于 2013-03-06T10:11:19.597 回答
2

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

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

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

于 2013-03-06T10:09:50.457 回答
0

也许它受到虚拟设备内存大小的限制!?

你试过给它更大的内存吗!?

于 2013-03-06T09:41:29.720 回答
0

您正在使用对象迭代它。你有他们保留副本等的风险......回到基础并尝试使用该功能String.split('');,然后通过正常循环迭代它。然后你知道哪些对象在内存中。进行拆分时,您会得到两个占用内存的对象,即原始字符串和拆分产生的数组。

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

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

于 2013-03-06T09:46:03.140 回答