为什么我有多个悬空的OkHttp ConnectionPool线程

时间:2018-06-03 12:33:16

标签: android multithreading okhttp resource-leak

我有一个Android应用,它在后台执行HTTP get请求。我将简要介绍一下如何执行此操作。我将首先关注这个问题。

我在调试器中发现OkHttp ConnectionPool正在Android Studio的Threads窗口中堆叠。这与我有关,因为它似乎表明资源泄漏,随着时间的推移,这些将无限期地增加(似乎)。

我的主要问题是我不知道为什么会发生这种情况。我几乎可以肯定这是我的错,但我并不知道如何寻找。所以我的一般问题是:

"每次发出HTTP请求时可能导致创建新池的原因是什么?"

首先,这是我用来执行get请求的代码。请注意,它已经过简化,但我已使用此确切代码运行并查看问题。

private TestResult test() {
    final long startTime = SystemClock.elapsedRealtime();
    final String server = "connectivitycheck.gstatic.com";

    URL url;
    try {
        url = new URL("http", SOME_PATH);
    } catch (MalformedURLException e) {
        // We shouldn't get here since the url is well known
        return new TestResult(
                "failed to generate url " + e,
                SystemClock.elapsedRealtime() - startTime
        );
    }

    HttpURLConnection urlConnection = null;
    int httpResponseCode;
    try {
        urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.setInstanceFollowRedirects(false);
        urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
        urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
        urlConnection.setUseCaches(false);
        InputStream is = urlConnection.getInputStream();
        httpResponseCode = urlConnection.getResponseCode();
        is.close();
    } catch (IOException e) {
        return new TestResult(
                e,
                SystemClock.elapsedRealtime() - startTime
        );
    } finally {
        if (urlConnection != null)
            urlConnection.disconnect();
    }
    if (httpResponseCode != HttpURLConnection.HTTP_NO_CONTENT) {
        return new TestResult(
                "invalid error code, expected 204 but got " + httpResponseCode,
                SystemClock.elapsedRealtime() - startTime
        );
    }

    return new TestResult(
            SystemClock.elapsedRealtime() - startTime
    );
}

所以, 时此代码运行...?

首先让我说我已尝试在我的应用程序上运行此代码(在一个单独的线程中 - 因为主要的android线程上不允许HTTP)。当我这样做,一切都很好。我可以发出多个请求,但从不会看到多个池。

我运行代码并查看问题的情况如下:

  • 我有一个背景Service
  • 在该服务中,我开始新的Thread
  • 在该主题中,我创建了一个ExecutorService

    ExecutorService executorService = Executors.newCachedThreadPool();
    CompletionService<FutureResult> completionService = new ExecutorCompletionService<>(executorService);
    
  • 使用ExecutorService我提交了一个可调用的任务,该任务运行我的test方法(上图)。

请注意,这可能听起来很复杂,但所有这一切都有其目的。首先,除了运行ExecutorService方法之外,test将执行许多其他任务。

我已经很好地查看挂起的引用,这些引用可能会使底层的HTTP资源保持活跃但我无法看到任何内容。

知道OkHttp的人是否知道为什么会这样?我希望有一些见解可以帮助我发现问题。

1 个答案:

答案 0 :(得分:0)

最简单的方法是在ConnectionPool构造函数中设置断点并运行您的应用程序。这将显示谁在创造它。我的猜测是它是一个不相关的类,如崩溃记者或分析库。