安卓:流转换为字符串,而不运行内存而不、字符串、内存

2023-09-03 22:30:26 作者:微雨清涼夏已盡

我有一个Android客户端,通过REST-FUL端点和JSON服务器通信。正因为如此,我有必要检索之前将其转换成一个散列的完整服务器响应。我有这个code的地方要做到这一点(在互联网上某个地方找到):

I have an android client that communicates with the server via REST-ful endpoints and JSON. Because of this, I have the need to retrieve the full server response prior to converting it into a Hash. I have this code in place to do that (found on the internet someplace):

private static String convertStreamToString(InputStream is) {

    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
    StringBuilder sb = new StringBuilder();

    String line = null;
    try {
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return sb.toString();
}

在code ++工程,在大多数情况下,但是我看到崩溃的报告,在该领域的客户就行了内存不足异常:

The code works for the most part, however I am seeing reports of crashes in the field from clients with an OutOfMemory exception on the line:

    while ((line = reader.readLine()) != null) {

完整的堆栈跟踪是:

The full stack trace is:

java.lang.RuntimeException: An error occured while executing doInBackground()
    at android.os.AsyncTask$3.done(AsyncTask.java:200)
    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
    at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
    at java.util.concurrent.FutureTask.run(FutureTask.java:137)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
    at java.lang.Thread.run(Thread.java:1102)
Caused by: java.lang.OutOfMemoryError
    at java.lang.String.(String.java:468)
    at java.lang.AbstractStringBuilder.toString(AbstractStringBuilder.java:659)
    at java.lang.StringBuilder.toString(StringBuilder.java:664)
    at java.io.BufferedReader.readLine(BufferedReader.java:448)
    at com.appspot.myapp.util.RestClient.convertStreamToString(RestClient.java:303)
    at com.appspot.myapp.util.RestClient.executeRequest(RestClient.java:281)
    at com.appspot.myapp.util.RestClient.Execute(RestClient.java:178)
    at com.appspot.myapp.$LoadProfilesTask.doInBackground(GridViewActivity.java:1178)
    at com.appspot.myapp.$LoadProfilesTask.doInBackground(GridViewActivity.java:1)
    at android.os.AsyncTask$2.call(AsyncTask.java:185)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
    ... 4 more

我的问题:有没有什么办法,以留出解决这个问题从服务器发送数据的较小的块?

My question: is there any way to solve this problem aside from sending smaller chunks of data from the server?

谢谢!

推荐答案

在一般情况下,答案是否定的,但你一定可以调整它们会让你耗尽内存的条件。特别是,如果你领先你流的发送字符串的长度,你将能够创建具有正确的数组大小的StringBuilder它里面。数组不能创建之后被调整,因此,如果您运行的阵列容量的StringBuilder,实施有分配一个新的数组,然后复制旧数组内容(通常为两次,避免过多的大小调整大小)。考虑尺寸的X流,以调整StringBuilder的,只是碰巧是个X-1的能力,你需要几乎X * 3的内存量。浆纱StringBuilder的这种需要改变避免将让你挤更大的流进内存。

In general, the answer is no, but you can certainly tune the conditions that cause you to run out of memory. In particular, if you send string length ahead of your stream, you will be able to create a StringBuilder with correct array size inside of it. Arrays cannot be resized after creation, so if you run out of array capacity in StringBuilder, the implementation has to allocate a new array (typically twice the size to avoid too many resizes) and then copy the old array contents. Consider stream of size X, to resize StringBuilder that just happened to be a X-1 capacity, you need almost X*3 amount of memory. Sizing StringBuilder such that resizes are avoided will allow you squeeze larger streams into memory.

您可能想要做的另一件事情是调整的内存可用于您的服务器进程的数量。启动服务器进程时,请使用像-Xmx1024m开关。

Another thing you may want to do is to tune the amount of memory available to your server process. Use a switch like -Xmx1024m when launching the server process.

当然,它会好得多修改你的算法不要求整个流将保存在内存中。它将使您能够处理更多的客户提供硬件的相同数量。

Of course, it would be much better to revise your algorithm to not require the entire stream to be held in memory. It will enable you to handle more clients with the same amount of hardware.