android - Why won't my Threads die and cause a memory leak? -
an app of mine accumulating lot of thread
instances gc can't pick , clear out. memory leak crashes app in long run.
i'm not 100% sure come from, have distinct feeling following might code in question:
public class urahosthttpconnection extends abstracturahostconnection { private handler uithreadhandler = new handler(looper.getmainlooper()); private executor taskexecutor = new executor() { public void execute(runnable command) { new thread(command).start(); } }; private connectiontask task = null; @override public void sendrequest(final httpurirequest request) { this.task = new connectiontask(); this.uithreadhandler.post(new runnable() { public void run() { task.executeonexecutor(taskexecutor, request); } }); } @override public void cancel() { if (this.task != null) this.task.cancel(true); } }
this code allows me run several http connections in parallel won't block each other on default asynctask
executor
(which single threaded queue).
i checked, asynctask
s in fact reaching onpostexecute()
methods , don't run forever. after inspecting memory dumps suspect wrapping thread
-objects not stop running after asynctask
s completed.
is possible above code still responsible memory leak, or should start looking elsewhere?
any appreciated.
edit: should noted, sendrequest
ever called once. other parts of code not in sample above make sure of that.
edit 2: super-class looks this:
public abstract class abstracturahostconnection { protected iurahostconnectionlistener listener = null; public void setlistener(iurahostconnectionlistener listener) { this.listener = listener; } public abstract void sendrequest(httpurirequest request); public abstract void cancel(); }
the asynctask looks this:
private class connectiontask extends asynctask<httpurirequest, object, void> { final byte[] buffer = new byte[2048]; private bytearraybuffer receiveddatabuffer = new bytearraybuffer(524288); @override protected void doinbackground(httpurirequest... arg0) { urahosthttpconnection.taskcounter++; androidhttpclient httpclient = androidhttpclient.newinstance("ivu.realtime.app"); try { // response , notify listener httpresponse response = httpclient.execute(arg0[0]); this.publishprogress(response); // check status code ok before proceeding if (response.getstatusline().getstatuscode() == 200) { httpentity entity = response.getentity(); inputstream inputstream = entity.getcontent(); int readcount = 0; // read 1 kb of data , hand on listener while ((readcount = inputstream.read(buffer)) != -1 && !this.iscancelled()) { this.receiveddatabuffer.append(buffer, 0, readcount); if (this.receiveddatabuffer.length() >= 524288 - 2048) { this.publishprogress(receiveddatabuffer.tobytearray()); this.receiveddatabuffer.clear(); } } if (this.iscancelled()) { if (arg0[0] != null && !arg0[0].isaborted()) { arg0[0].abort(); } } } } catch (ioexception e) { // forward errors listener e.printstacktrace(); this.publishprogress(e); } { if (httpclient != null) httpclient.close(); } return null; } @override protected void onprogressupdate(object... payload) { // forward response if (payload[0] instanceof httpresponse) listener.onreceiveresponse((httpresponse) payload[0]); // forward error else if (payload[0] instanceof exception) listener.onfailwithexception((exception) payload[0]); // forward data else if (payload[0] instanceof byte[]) listener.onreceivedata((byte[]) payload[0]); } @override protected void onpostexecute(void result) { listener.onreceivedata(this.receiveddatabuffer.tobytearray()); listener.onfinishloading(); urahosthttpconnection.taskcounter--; log.d(tag, "there " + urahosthttpconnection.taskcounter + " running connectiontasks."); } }
substitute threadpoolexecutor executor have control on size of pool. if threadpoolexecutor executor exposed methods, may case default maximum pool size set high.
official doc here.
take in particular at:
setcorepoolsize(int corepoolsize) //sets core number of threads. setkeepalivetime(long time, timeunit unit) //sets time limit threads may remain idle before being terminated. setmaximumpoolsize(int maximumpoolsize) //sets maximum allowed number of threads.
there's alternative if want code less (better idea depending on how control want , how code you'll trade it).
executor taskexecutor = executors.newfixedthreadpool(x);
where x = size of pool