5

Thread私のアプリは、GC がピックアップしてクリアできない多くのインスタンスを蓄積しています。このメモリ リークは、長期的にはアプリをクラッシュさせます。

それらがどこから来たのかは100%わかりませんが、次のコードが問題のコードである可能性があるとはっきりと感じています。

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);
    }
}

このコードにより、複数の HTTP 接続を並行して実行することができ、デフォルトでは相互にブロックされませんAsyncTask Executor(これは単一のスレッド化されたキューです)。

AsyncTasks が実際にメソッドに到達しており、onPostExecute()永遠に実行されないことを確認しました。いくつかのメモリ ダンプを調べた後、 s の完了Thread後にラッピング オブジェクトの実行が停止しないのではないかと思われます。AsyncTask

上記のコードがまだメモリリークの原因である可能性はありますか、それとも他の場所を探し始める必要がありますか?

どんな助けでも大歓迎です。

編集:sendRequest一度しか呼び出されないことに注意してください。上記のサンプルにないコードの他の部分は、それを確認します。

編集 2:スーパークラスは次のようになります。

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();
}

AsyncTask は次のようになります。

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 {
            // Get response and 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 one kB of data and hand it over to the 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 any errors to listener
            e.printStackTrace();
            this.publishProgress(e);
        } finally {
            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 are " + UraHostHttpConnection.taskCounter + " running ConnectionTasks.");
    }
}
4

1 に答える 1