Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
284 views
in Technique[技术] by (71.8m points)

java - OutOfMemoryError : When receiving XML response of 2.3 MB

Following is simple method that connects to web service and receives the XML response from server which is about 2.3MB and I'm getting OutOfMemoryError (I've referred this) but not being able to find my way, stuck badly

public synchronized String getUpdates(boolean news) throws Exception {
        String response = null; 
        HttpPost httppost;
        DefaultHttpClient httpclient;
        ResponseHandler <String> res=new BasicResponseHandler();  
        List<NameValuePair> nameValuePairs;
        httppost = new HttpPost(context.getString(R.string.SYNCURL));  
        HttpParams params = new BasicHttpParams();  
        HttpProtocolParams.setContentCharset(params, "UTF-8");

        String lastupdate = null;
        SharedPreferences preferences = context.getSharedPreferences(context.getPackageName(), Context.MODE_PRIVATE);
        lastupdate = preferences.getString(LAST_UPDATE, DatabaseHelper.updateDate);
        if(news) lastupdate = preferences.getString(LAST_UPDATE_NEWS, lastupdate);

        httpclient = new DefaultHttpClient(params);
        nameValuePairs = new ArrayList<NameValuePair>(2);  
        nameValuePairs.add(new BasicNameValuePair("reqDTTM", lastupdate));
        if(news)nameValuePairs.add(new BasicNameValuePair("doAction", "news"));
        if(!preferences.getString(LAST_UPDATE, "").equalsIgnoreCase(DatabaseHelper.updateDate)) {
            String timezon = UDFHelper.getTimeZon(context);
            nameValuePairs.add(new BasicNameValuePair("tz", timezon));
        }
        httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));  
        response = httpclient.execute(httppost, res);
        return response;
}

Here it causes problem trying to retrieve large text in String response :

response = httpclient.execute(httppost, res);

I'm storing the response in String. Is that a problem? What is alternative solution of that?

Here is LogCat

09-23 10:07:31.654: INFO/ActivityManager(59): Displayed activity uk.co.dodec.rcgpapp/.SplashScreen: 1267 ms (total 1267 ms)
09-23 10:07:35.854: INFO/dalvikvm-heap(334): Grow heap (frag case) to 3.213MB for 262160-byte allocation
09-23 10:07:38.203: INFO/dalvikvm-heap(334): Grow heap (frag case) to 3.586MB for 524304-byte allocation
09-23 10:07:42.753: INFO/dalvikvm-heap(334): Grow heap (frag case) to 4.336MB for 1048592-byte allocation
09-23 10:07:52.024: INFO/dalvikvm-heap(334): Grow heap (frag case) to 5.836MB for 2097168-byte allocation
09-23 10:08:09.844: INFO/dalvikvm-heap(334): Grow heap (frag case) to 8.836MB for 4194320-byte allocation
09-23 10:08:09.864: INFO/ActivityManager(59): Process com.android.mms (pid 227) has died.
09-23 10:08:45.984: INFO/dalvikvm-heap(334): Forcing collection of SoftReferences for 8388624-byte allocation
09-23 10:08:46.033: ERROR/dalvikvm-heap(334): Out of memory on a 8388624-byte allocation.
09-23 10:08:46.033: INFO/dalvikvm(334): "AsyncTask #1" prio=5 tid=7 RUNNABLE
09-23 10:08:46.033: INFO/dalvikvm(334):   | group="main" sCount=0 dsCount=0 s=N obj=0x43e54fd8 self=0x224d58
09-23 10:08:46.033: INFO/dalvikvm(334):   | sysTid=340 nice=10 sched=0/0 cgrp=bg_non_interactive handle=2248344
09-23 10:08:46.033: INFO/dalvikvm(334):   | schedstat=( 1248172861 2043417240 1093 )
09-23 10:08:46.033: INFO/dalvikvm(334):   at org.apache.http.util.CharArrayBuffer.expand(CharArrayBuffer.java:~59)
09-23 10:08:46.033: INFO/dalvikvm(334):   at org.apache.http.util.CharArrayBuffer.append(CharArrayBuffer.java:77)
09-23 10:08:46.033: INFO/dalvikvm(334):   at org.apache.http.util.EntityUtils.toString(EntityUtils.java:136)
09-23 10:08:46.033: INFO/dalvikvm(334):   at org.apache.http.util.EntityUtils.toString(EntityUtils.java:146)
09-23 10:08:46.033: INFO/dalvikvm(334):   at org.apache.http.impl.client.BasicResponseHandler.handleResponse(BasicResponseHandler.java:76)
09-23 10:08:46.033: INFO/dalvikvm(334):   at org.apache.http.impl.client.BasicResponseHandler.handleResponse(BasicResponseHandler.java:59)
09-23 10:08:46.033: INFO/dalvikvm(334):   at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:657)
09-23 10:08:46.033: INFO/dalvikvm(334):   at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:627)
09-23 10:08:46.033: INFO/dalvikvm(334):   at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:616)
09-23 10:08:46.033: INFO/dalvikvm(334):   at uk.co.dodec.rcgpapp.helper.HttpHelper.getUpdates(HttpHelper.java:172)
09-23 10:08:46.033: INFO/dalvikvm(334):   at uk.co.dodec.rcgpapp.SplashScreen.getUpdate(SplashScreen.java:155)
09-23 10:08:46.033: INFO/dalvikvm(334):   at uk.co.dodec.rcgpapp.SplashScreen$getUpdates.doInBackground(SplashScreen.java:126)
09-23 10:08:46.033: INFO/dalvikvm(334):   at uk.co.dodec.rcgpapp.SplashScreen$getUpdates.doInBackground(SplashScreen.java:1)
09-23 10:08:46.043: INFO/dalvikvm(334):   at android.os.AsyncTask$2.call(AsyncTask.java:185)
09-23 10:08:46.043: INFO/dalvikvm(334):   at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
09-23 10:08:46.043: INFO/dalvikvm(334):   at java.util.concurrent.FutureTask.run(FutureTask.java:137)
09-23 10:08:46.043: INFO/dalvikvm(334):   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
09-23 10:08:46.043: INFO/dalvikvm(334):   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
09-23 10:08:46.043: INFO/dalvikvm(334):   at java.lang.Thread.run(Thread.java:1096)
09-23 10:10:37.353: WARN/dalvikvm(334): threadid=7: thread exiting with uncaught exception (group=0x4001d800)
09-23 10:10:37.375: ERROR/AndroidRuntime(334): FATAL EXCEPTION: AsyncTask #1
09-23 10:10:37.375: ERROR/AndroidRuntime(334): java.lang.RuntimeException: An error occured while executing doInBackground()
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at android.os.AsyncTask$3.done(AsyncTask.java:200)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at java.util.concurrent.FutureTask.run(FutureTask.java:137)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at java.lang.Thread.run(Thread.java:1096)
09-23 10:10:37.375: ERROR/AndroidRuntime(334): Caused by: java.lang.OutOfMemoryError
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at org.apache.http.util.CharArrayBuffer.expand(CharArrayBuffer.java:59)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at org.apache.http.util.CharArrayBuffer.append(CharArrayBuffer.java:77)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at org.apache.http.util.EntityUtils.toString(EntityUtils.java:136)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at org.apache.http.util.EntityUtils.toString(EntityUtils.java:146)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at org.apache.http.impl.client.BasicResponseHandler.handleResponse(BasicResponseHandler.java:76)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at org.apache.http.impl.client.BasicResponseHandler.handleResponse(BasicResponseHandler.java:59)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:657)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:627)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:616)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at uk.co.dodec.rcgpapp.helper.HttpHelper.getUpdates(HttpHelper.java:172)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at uk.co.dodec.rcgpapp.SplashScreen.getUpdate(SplashScreen.java:155)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at uk.co.dodec.rcgpapp.SplashScreen$getUpdates.doInBackground(SplashScreen.java:126)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at uk.co.dodec.rcgpapp.SplashScreen$getUpdates.doInBackground(SplashScreen.java:1)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
09-23 10:10:37.375: ERROR/AndroidRuntime(334):     ... 4 more
09-23 10:10:37.393: WARN/ActivityManager(59):   Force finishing activity uk.co.dodec.rcgpapp/.SplashScreen

I've tried following not worked

HttpResponse r = httpclient.execute(httppost);

HttpEntity entity = r.getEntity();

InputStream in = new ByteArrayInputStream(EntityUtils.toByteArray(entity));

File fl = new File(Environment.getDataDirectory().toString() + "/data/" + context.getPackageName() + "/" + FOLDER_NAME);
if(!fl.exists()) fl.mkdir();

String PATH = Environment.getDataDirectory().toString() + "/data/" + context.getPackageName() + "/" + FOLDER_NAME + "/" + "update.xml";
FileOutputStream f = new FileOutputStream(PATH);

byte[] buffer = new byte[1024];
int len1 = 0;
while ((len1 = in.read(buffer)) > 0) {
    f.write(buffer, 0, len1);
}
f.close();
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

That is indeed a problem: don't do that. You should write the response to a file or parse the stream but definitely don't try generating a 2.3 MB string. Write a response handler that returns the HttpEntity behind the response, then get the InputStream using the getContent method, then save that to a file and then process the file.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...