1

Im getting an OutOfMemory Exception when using this code:

     class ApiTask extends AsyncTask<URI, Void, String> {

    private Exception exception;

    protected void onPreExecute() {
        dialog = ProgressDialog.show(DownloadedActivity.this, "", 
                "Contacting Server...", true);
    }

    protected String doInBackground(URI... uri) {
        try {

            HttpClient client = new DefaultHttpClient();
            HttpGet request = new HttpGet();
            try {
                request.setURI(uri[0]);
                return client.execute(request, new BasicResponseHandler());
            } catch (Exception e) {
                e.printStackTrace();
            }

            return "Error";

        } catch (Exception e) {
            this.exception = e;
            return "Error";
        }
    }

    @Override
    protected void onPostExecute(String result) {
        dialog.dismiss();
        processJSON(result);
        updateListView();
        result = null;
        System.gc();
           }
          }

The error happens when I run this code a second time in a refresh method, this makes me suspect a memory leak. The response is a large JSON object. I hope to find out what Im doing wrong Ive tried a few things but its looking like the response stays in memory.

Here is the logcat error:

05-09 13:45:13.764: E/AndroidRuntime(2438): Uncaught handler: thread AsyncTask #2 exiting due to uncaught exception
05-09 13:45:13.784: E/AndroidRuntime(2438): java.lang.RuntimeException: An error occured while executing doInBackground()
05-09 13:45:13.784: E/AndroidRuntime(2438):     at android.os.AsyncTask$3.done(AsyncTask.java:200)
05-09 13:45:13.784: E/AndroidRuntime(2438):     at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
05-09 13:45:13.784: E/AndroidRuntime(2438):     at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
05-09 13:45:13.784: E/AndroidRuntime(2438):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
05-09 13:45:13.784: E/AndroidRuntime(2438):     at java.util.concurrent.FutureTask.run(FutureTask.java:137)
05-09 13:45:13.784: E/AndroidRuntime(2438):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
05-09 13:45:13.784: E/AndroidRuntime(2438):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
05-09 13:45:13.784: E/AndroidRuntime(2438):     at java.lang.Thread.run(Thread.java:1096)
05-09 13:45:13.784: E/AndroidRuntime(2438): Caused by: java.lang.OutOfMemoryError
05-09 13:45:13.784: E/AndroidRuntime(2438):     at java.lang.String.<init>(String.java:513)
05-09 13:45:13.784: E/AndroidRuntime(2438):     at org.apache.http.util.CharArrayBuffer.toString(CharArrayBuffer.java:261)
05-09 13:45:13.784: E/AndroidRuntime(2438):     at org.apache.http.util.EntityUtils.toString(EntityUtils.java:141)
05-09 13:45:13.784: E/AndroidRuntime(2438):     at org.apache.http.util.EntityUtils.toString(EntityUtils.java:146)
05-09 13:45:13.784: E/AndroidRuntime(2438):     at org.apache.http.impl.client.BasicResponseHandler.handleResponse(BasicResponseHandler.java:76)
05-09 13:45:13.784: E/AndroidRuntime(2438):     at org.apache.http.impl.client.BasicResponseHandler.handleResponse(BasicResponseHandler.java:59)
05-09 13:45:13.784: E/AndroidRuntime(2438):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:657)
05-09 13:45:13.784: E/AndroidRuntime(2438):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:627)
05-09 13:45:13.784: E/AndroidRuntime(2438):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:616)
05-09 13:45:13.784: E/AndroidRuntime(2438):     at com.nelissen.couchforwarder.couch.DownloadedActivity$ApiTask.doInBackground(DownloadedActivity.java:382)
05-09 13:45:13.784: E/AndroidRuntime(2438):     at com.nelissen.couchforwarder.couch.DownloadedActivity$ApiTask.doInBackground(DownloadedActivity.java:1)
05-09 13:45:13.784: E/AndroidRuntime(2438):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
05-09 13:45:13.784: E/AndroidRuntime(2438):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
05-09 13:45:13.784: E/AndroidRuntime(2438):     ... 4 more
Aleks G
  • 56,435
  • 29
  • 168
  • 265
Boris
  • 73
  • 7
  • Please provide the code of your `processJSON` method - if something's fishy in there, it could easily go into an infinite recursion. – Aleks G May 09 '12 at 11:34
  • The string returned by the request is about 6mb in size, I think the problem is there. The processJson is not even called when the OutOfMemory error is there. Oh and I forgot to add the error only happend to me on devices with 24mb heap size. Ill check if it crashes when not processing. – Boris May 09 '12 at 11:43
  • It crashes on the AsyncTask not the processing, I checked by removing the parsing. I added the logcat – Boris May 09 '12 at 11:47
  • Btw, you should definitely not be processing *omghuge* JSON replies on the UI-thread, keep that in the AsyncTask - and switch to a JSON parser that can read streams instead of the crappy one included in Android that only eats entire `String`s. – Jens May 09 '12 at 12:07
  • Ok, so changing to streams should fix the memory problem. But what I dont understand is why the String remains in the memory after the AsyncTask finishes and the parseJSON is finished. – Boris May 09 '12 at 15:07

2 Answers2

1

I found that AsyncTask and Activity are kind of "loosely tied" to each other.. so maybe that AsyncTask doesn't quite..DIE!! haha :D

Try to read this link: Android AsyncTask for Long Running Operations

Anyway in my code onRefresh I killed them both!

public void onRefresh(View view){ // this is a method inside the Activity about to be killed            
    downloadXmlTaskObject = null; // Garbage Collectible 
    finish();                // Finish the Activity
    Intent intent = getIntent(); // get the intent of the Activity
    startActivity(intent);  // and Create a new Activity        
}

I don't know though if it will meet your requirements or not.. you can create an Activity solely for the purpose of downloading or parsing etc. Then kill them both! Good luck! ^_^

Community
  • 1
  • 1
Koushik Sarkar
  • 480
  • 2
  • 6
  • 18
0

I am sure this is happening due to the sentence you have written in your code:

return client.execute(request, new BasicResponseHandler());  // inside doInBackground

I would suggest you to create another AsyncTask for the same and execute this new AsyncTask inside the onPostExecute() method.

And another may be due to processJSON(result); , it may be a time consuming process.

Paresh Mayani
  • 127,700
  • 71
  • 241
  • 295