java.lang.OutOfMemoryError bei StringBuilder.Append()

H

hs1

Fortgeschrittenes Mitglied
8
Hallo Leute,

in meiner App werden Daten via http gesynct (Up- und Download). Auf Serverseite wickelt eine c# Restful Api den Sync ab. Die Daten werden in einem json-Array an die App gesendet.

Mittlerweile sind es recht große Daten geworden und ich vermute dass der Fehler auch daher kommt.
Meine Funktion die die Daten vom Server herunterläd sieht wie folgt aus:

Code:
HttpURLConnection urlConnection = null;

        String requestBody = buildPostParameters(params[0].getValues());
        try {
            urlConnection = (HttpURLConnection) HttpCommunicationUtils.makeRequest(params[0].getRequestType(), params[0].getUrl(), params[0].getToken(), "application/x-www-form-urlencoded", requestBody);
            InputStream inputStream;
            // get stream
            if (urlConnection.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST) {
                inputStream = urlConnection.getInputStream();
            } else {
                inputStream = urlConnection.getErrorStream();
            }

            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }

            retVal = sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
        }

Die Zeile sb.append(line); führt zum Fehler. Der StringBuilder enthält am Ende das komplette JSON-Array welches dann weiter verarbeitet wird.

Code:
java.lang.RuntimeException: An error occured while executing doInBackground()
    at android.os.AsyncTask$3.done(AsyncTask.java:299)
    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 android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
    at java.lang.Thread.run(Thread.java:856)
Caused by: java.lang.OutOfMemoryError
    at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:94)
    at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:145)
    at java.lang.StringBuilder.append(StringBuilder.java:216)
    at de.software.xxxx.Sync.HttpRequestMapList.request(HttpRequestMapList.java:44)
    at de.software.xxxx.Sync.Data.SyncData.StartSync(SyncDataBuchungen.java:115)
    at de.software.xxxx.Sync.Data.SyncProcessAsync.doInBackground(SyncProcessAsync.java:144)
    at de.software.xxxx.Sync.Data.SyncProcessAsync.doInBackground(SyncProcessAsync.java:34)
    at android.os.AsyncTask$2.call(AsyncTask.java:287)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
    ... 5 more


Wie kann ich das ganze anders lösen, um diesem Fehler zu umgehen?

Danke & Gruß

hs1
 
Hallo hs1,

Deine Vermutung könnte zutreffen.
Darf ich fragen , wieviel Bytes Du denn schon im Stringbuilder hast, bevor Schuss gemacht wird ?

Was sagt dein Memory-Monitor in dem Moment (AS)

Das Erste was mir dazu eingefallen ist : In Häppchen auslagern.(File)
 
Ich versuche gerade das Problem bei mir nachzustellen. Im Hinblick darauf, dass die Datenmenge aber auf alle Fälle stark wachsen wird, werde ich wohl die Daten die ich per HTTP erhalte in eine Datei speichern und diese dann mit der JsonFactory verarbeiten.
 
Das wird auch nicht viel bringen. Die beste Möglichkeit ist es, die Datenmengen zu reduzieren. Z.B mehrere Http - Request zu benutzen. Und danach nur die Daten zu senden, die wirklich neu sind. Das macht schon Sinn, weil die meisten Benutzer nur beschränkte Datenvolumen gebucht haben (z.T 300 MB).

Und sonst trage einfach mal im Manifest im Node <application ../> folgenden Zeile ein:
android:largeHeap="true"
 
Datenvolumen spielt keinerlei Rolle. Ich konnte das Problem mit meiner beschriebenen Vorgehensweise lösen.
 

Ähnliche Themen

Y
Antworten
4
Aufrufe
1.170
swa00
swa00
R
  • RudolfHagen
Antworten
1
Aufrufe
629
koje71
koje71
Muecke1982
Antworten
8
Aufrufe
1.004
Skyhigh
Skyhigh
Zurück
Oben Unten