我在SprintBoot2中使用OkHttp3

这是OkHttp3的配置和OkHttp3的用法,几乎是从OkHttp3 WebSite的主页复制的。

public class OkHttp3AutoConfiguration {

    @Bean
    public X509TrustManager x509TrustManager() {
        return new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s)
                throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s)
                throws CertificateException {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };
    }

    @Bean
    public SSLSocketFactory sslSocketFactory() {
        try {
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, new TrustManager[]{x509TrustManager()}, new SecureRandom());
            return sslContext.getSocketFactory();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            log.error("error!", e);
        }
        return null;
    }


    @Bean
//    @ConditionalOnMissingBean(OkHttpClient.class)
    public OkHttpClient okHttpClient(OkHttp3Properties properties) {
        OkHttpClient.Builder builder =
            new OkHttpClient.Builder()
                .sslSocketFactory(sslSocketFactory(), x509TrustManager())
                .retryOnConnectionFailure(false)
                .connectionPool(pool(properties))
                .connectTimeout(properties.getConnectTimeout(), TimeUnit.SECONDS)
                .readTimeout(properties.getReadTimeout(), TimeUnit.SECONDS)
                .writeTimeout(properties.getWriteTimeout(), TimeUnit.SECONDS)
                .hostnameVerifier((hostname, session) -> true);
        return builder.build();
    }

    @Bean
    public ConnectionPool pool(OkHttp3Properties properties) {
        return new ConnectionPool(properties.getMaxIdle(), properties.getKeepAlive(),
            TimeUnit.SECONDS);
    }
}


通话

Call call = okHttpClient
                .newCall(
                    new Request.Builder().url(url).build());
    call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    log.error("call error!", e);
                    call.cancel();
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
    //                response.body().string();
                    response.close();
                }
            });


运行jmap -histo:live

这是JVM的实例,我们可以看到它们主要是OkHttp3实例。

/work # jmap -histo:live 6 | head -n 50

 num     #instances         #bytes  class name
----------------------------------------------
   1:       2709181       65020344  java.lang.String
   2:        371561       57565680  [C
   3:        205744       13302760  [Ljava.lang.Object;
   4:         33011       11362152  [B
   5:        103308        6644392  [Ljava.lang.String;
   6:         94919        6074816  okhttp3.internal.connection.Transmitter
   7:         94919        5315464  okhttp3.internal.connection.Transmitter$1
   8:        200635        4815240  java.util.ArrayList
   9:        190231        4565544  java.util.Collections$UnmodifiableRandomAccessList
  10:         94954        4557792  okhttp3.HttpUrl
  11:         94952        3798080  okhttp3.Request
  12:         94919        3037408  okhttp3.RealCall
  13:         94919        3037408  okhttp3.RealCall$AsyncCall
  14:         94982        1519712  okhttp3.Headers
  15:         94919        1518704  com.dechong.adnetwork.click.web.TestController$1
  16:          8293         920544  java.lang.Class
  17:          7018         786016  sun.security.ssl.SSLSessionImpl
  18:         22948         734336  java.util.concurrent.ConcurrentHashMap$Node
  19:          5594         651024  [I
  20:         13171         526840  java.util.LinkedHashMap$Entry
  21:          2407         479984  [Ljava.util.HashMap$Node;
  22:          7130         464824  [Ljava.util.Hashtable$Entry;
  23:          7118         398608  sun.security.util.MemoryCache$SoftCacheEntry


okhttp3的实例增长很快,GC无法释放它,最后JVM将OOM!

我该如何解决这个问题?

最佳答案

TestController是否保留对OkHttp调用的引用?令人惊讶的是,您拥有与此和OkHttp事物完全相同数量的实例。

10-06 16:10