【问题标题】:Why do I have multiple dangling OkHttp ConnectionPool threads为什么我有多个悬空的 OkHttp ConnectionPool 线程
【发布时间】:2018-11-12 22:55:54
【问题描述】:

我有一个在后台执行 HTTP 获取请求的 Android 应用。我将很快提供一些有关如何执行此操作的详细信息。我将首先重点描述这个问题。

我在调试器中观察到OkHttp ConnectionPools 在 Android Studio 的 Threads 窗口中堆积。这与我有关,因为它似乎表明资源泄漏,并且随着时间的推移,这些将无限增加(似乎)。

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

“什么可能导致每次发出 HTTP 请求时都会创建一个新池?”

首先,这是我用来执行获取请求的代码。请注意,它被简化了,但我已经使用这个确切的代码运行并看到了问题。

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 的人知道为什么会发生这种情况吗?我希望有一些见解可以帮助我发现问题。

【问题讨论】:

    标签: android multithreading okhttp resource-leak


    【解决方案1】:

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

    【讨论】:

    • 我已经调试过了,我可以看到创建池的肯定是 OkHttp。我无法调试实际的 OkHttp 源,因为它没有发货,所以我不知道“为什么”它会发生。我只知道它是,而且是 OkHttp 做的 :(
    猜你喜欢
    • 1970-01-01
    • 2019-02-23
    • 2015-11-28
    • 2015-07-09
    • 2012-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-24
    相关资源
    最近更新 更多