我在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事物完全相同数量的实例。