Android 11+应用频繁崩溃:java.net.SocketException: Connection Reset求助
应用在Android 11+上频繁因
java.net.SocketException: Connection Reset崩溃排查 问题概述
- 应用频繁抛出java.net.SocketException: Connection Reset并崩溃,堆栈跟踪中无自研代码,怀疑是依赖库兼容性问题
- 该问题仅出现在Android 11及以上系统,使用Retrofit2进行网络请求
- 已尝试增加超时时间,但偶尔仍会出现Socket Closed异常
堆栈信息
Fatal Exception: java.net.SocketException: Connection reset at java.net.SocketInputStream.read(SocketInputStream.java:215) at java.net.SocketInputStream.read(SocketInputStream.java:144) at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.readFromSocket(ConscryptEngineSocket.java:945) at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.processDataFromSocket(ConscryptEngineSocket.java:909) at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.readUntilDataAvailable(ConscryptEngineSocket.java:824) at com.android.org.conscrypt.ConscryptEngineSocket$SSLInputStream.read(ConscryptEngineSocket.java:797) at okio.Okio$2.read(Okio.java:140) at okio.AsyncTimeout$2.read(AsyncTimeout.java:237) at okio.RealBufferedSource.read(RealBufferedSource.java:47) at okhttp3.internal.http1.Http1Codec$AbstractSource.read(Http1Codec.java:363) at okhttp3.internal.http1.Http1Codec$ChunkedSource.read(Http1Codec.java:453) at okio.RealBufferedSource.read(RealBufferedSource.java:47) at okio.ForwardingSource.read(ForwardingSource.java:35) at retrofit2.OkHttpCall$ExceptionCatchingResponseBody$1.read(OkHttpCall.java:288) at okio.RealBufferedSource$1.read(RealBufferedSource.java:439) at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:291) at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:355) at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:181) at java.io.InputStreamReader.read(InputStreamReader.java:184) at okhttp3.ResponseBody$BomAwareReader.read(ResponseBody.java:259) at com.google.gson.stream.JsonReader.fillBuffer(JsonReader.java:1289) at com.google.gson.stream.JsonReader.nextQuotedValue(JsonReader.java:1029) at com.google.gson.stream.JsonReader.nextString(JsonReader.java:814) at com.google.gson.internal.bind.TypeAdapters$15.read(TypeAdapters.java:380) at com.google.gson.internal.bind.TypeAdapters$15.read(TypeAdapters.java:368) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222) at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:41) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:82) at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:61) at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:39) at retrofit2.converter.gson.GsonResponseBodyConverter.convert(GsonResponseBodyConverter.java:27) at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:225) at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:121) at okhttp3.RealCall$AsyncCall.execute(RealCall.java:206) at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:920)
排查方向与解决方案
1. 适配Android 11+网络行为变更
Android 11对网络连接引入了更严格的限制,重点检查:
- 确认服务器TLS配置,需兼容Android 11默认启用的TLS 1.3,同时保留TLS 1.2支持
- 升级OkHttp到4.9.0及以上版本,该版本针对Android 11的网络特性做了兼容性优化
2. 调整OkHttp连接池配置
连接池中的空闲连接可能被系统或服务器主动关闭,导致复用连接时出错:
- 缩短空闲连接存活时间,避免复用已失效的连接,配置示例:
ConnectionPool connectionPool = new ConnectionPool( 5, // 最大空闲连接数 30, TimeUnit.SECONDS // 空闲连接存活时间 ); OkHttpClient client = new OkHttpClient.Builder() .connectionPool(connectionPool) .build();
3. 修复SSL/TLS兼容性问题
堆栈中出现Conscrypt相关代码,可能是TLS握手兼容性问题:
- 强制OkHttp使用TLS 1.2,规避TLS 1.3的适配问题,实现自定义SSLSocketFactory:
public class SSLSocketFactoryCompat extends SSLSocketFactory { private final SSLSocketFactory delegate; public SSLSocketFactoryCompat() { try { SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); sslContext.init(null, null, null); delegate = sslContext.getSocketFactory(); } catch (Exception e) { throw new RuntimeException(e); } } @Override public String[] getDefaultCipherSuites() { return delegate.getDefaultCipherSuites(); } @Override public String[] getSupportedCipherSuites() { return delegate.getSupportedCipherSuites(); } @Override public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { Socket socket = delegate.createSocket(s, host, port, autoClose); ((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1.2"}); return socket; } @Override public Socket createSocket(String host, int port) throws IOException { Socket socket = delegate.createSocket(host, port); ((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1.2"}); return socket; } @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { Socket socket = delegate.createSocket(host, port, localHost, localPort); ((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1.2"}); return socket; } @Override public Socket createSocket(InetAddress host, int port) throws IOException { Socket socket = delegate.createSocket(host, port); ((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1.2"}); return socket; } @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { Socket socket = delegate.createSocket(address, port, localAddress, localPort); ((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1.2"}); return socket; } } // 应用到OkHttpClient OkHttpClient client = new OkHttpClient.Builder() .sslSocketFactory(new SSLSocketFactoryCompat(), X509TrustManagerExtensions.getDefault()) .build();
4. 完善异常捕获与重试机制
确保网络请求异常被正确处理,避免崩溃:
- 在Retrofit的
onFailure回调中显式捕获SocketException,防止未捕获异常导致崩溃 - 实现重试拦截器,针对
Connection Reset和Socket Closed异常自动重试:
public class RetryInterceptor implements Interceptor { private static final int MAX_RETRIES = 3; @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); IOException exception = null; for (int i = 0; i < MAX_RETRIES; i++) { try { Response response = chain.proceed(request); if (response.isSuccessful()) { return response; } } catch (IOException e) { exception = e; if (isRetryable(e)) { continue; } break; } } throw exception != null ? exception : new IOException("Max retries exceeded"); } private boolean isRetryable(IOException e) { return e instanceof SocketException && (e.getMessage().contains("Connection reset") || e.getMessage().contains("Socket closed")); } } // 添加到OkHttpClient OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new RetryInterceptor()) .build();
内容的提问来源于stack exchange,提问作者gogita kupatadze
相关产品推荐
相关产品推荐

