崩溃堆栈
1
java.lang.RuntimeException:javax.net.ssl.SSLException: Unable to create application data
2
com.android.org.conscrypt.ConscryptFileDescriptorSocket.newSsl(ConscryptFileDescriptorSocket.java:161)
3
......
4
Caused by:
5
javax.net.ssl.SSLException:Unable to create application data
6
com.android.org.conscrypt.NativeCrypto.SSL_new(Native Method)
7
com.android.org.conscrypt.SslWrapper.newInstance(SslWrapper.java:58)
8
com.android.org.conscrypt.ConscryptFileDescriptorSocket.newSsl(ConscryptFileDescriptorSocket.java:159)
9
com.android.org.conscrypt.ConscryptFileDescriptorSocket.<init>(ConscryptFileDescriptorSocket.java:152)
10
com.android.org.conscrypt.OpenSSLSocketFactoryImpl.createSocket(OpenSSLSocketFactoryImpl.java:155)
11
okhttp3.internal.connection.RealConnection.void connectTls(okhttp3.internal.connection.ConnectionSpecSelector)(RealConnection.java:369)
12
okhttp3.internal.connection.RealConnection.void establishProtocol(okhttp3.internal.connection.ConnectionSpecSelector,int,okhttp3.Call,okhttp3.EventListener)(RealConnection.java:337)
13
okhttp3.internal.connection.RealConnection.void connect(int,int,int,int,boolean,okhttp3.Call,okhttp3.EventListener)(RealConnection.java:209)
14
okhttp3.internal.connection.ExchangeFinder.okhttp3.internal.connection.RealConnection findConnection(int,int,int,int,boolean)(ExchangeFinder.java:226)
15
okhttp3.internal.connection.ExchangeFinder.okhttp3.internal.connection.RealConnection findHealthyConnection(int,int,int,int,boolean,boolean)(ExchangeFinder.java:106)
16
okhttp3.internal.connection.ExchangeFinder.okhttp3.internal.http.ExchangeCodec find(okhttp3.OkHttpClient,okhttp3.internal.http.RealInterceptorChain)(ExchangeFinder.java:74)
17
okhttp3.internal.connection.RealCall.okhttp3.internal.connection.Exchange initExchange$okhttp(okhttp3.internal.http.RealInterceptorChain)(RealCall.java:255)
18
okhttp3.internal.connection.ConnectInterceptor.okhttp3.Response intercept(okhttp3.Interceptor$Chain)(ConnectInterceptor.java:32)
19
okhttp3.internal.http.RealInterceptorChain.okhttp3.Response proceed(okhttp3.Request)(RealInterceptorChain.java:109)
20
okhttp3.internal.cache.CacheInterceptor.okhttp3.Response intercept(okhttp3.Interceptor$Chain)(CacheInterceptor.java:95)
21
okhttp3.internal.http.RealInterceptorChain.okhttp3.Response proceed(okhttp3.Request)(RealInterceptorChain.java:109)
22
okhttp3.internal.http.BridgeInterceptor.okhttp3.Response intercept(okhttp3.Interceptor$Chain)(BridgeInterceptor.java:83)
23
okhttp3.internal.http.RealInterceptorChain.okhttp3.Response proceed(okhttp3.Request)(RealInterceptorChain.java:109)
24
okhttp3.internal.http.RetryAndFollowUpInterceptor.okhttp3.Response intercept(okhttp3.Interceptor$Chain)(RetryAndFollowUpInterceptor.java:76)
25
okhttp3.internal.http.RealInterceptorChain.okhttp3.Response proceed(okhttp3.Request)(RealInterceptorChain.java:109)
26
okhttp3.logging.HttpLoggingInterceptor.okhttp3.Response intercept(okhttp3.Interceptor$Chain)(HttpLoggingInterceptor.java:219)
27
okhttp3.internal.http.RealInterceptorChain.okhttp3.Response proceed(okhttp3.Request)(RealInterceptorChain.java:109)
28
okhttp3.internal.connection.RealCall.okhttp3.Response getResponseWithInterceptorChain$okhttp()(RealCall.java:201)
29
okhttp3.internal.connection.RealCall$AsyncCall.void run()(RealCall.java:517)
30
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
31
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
32
java.lang.Thread.run(Thread.java:784)
分析
看安卓8.1的源码,ConscryptFileDescriptorSocket创建SslWrapper,所有SSL异常都被封装成了运行时异常,导致在拦截器里执行时无法catch直接崩溃:
https://android.googlesource.com/platform/external/conscrypt/+/refs/tags/android-8.1.0_r12/common/src/main/java/org/conscrypt/ConscryptFileDescriptorSocket.java
private static SslWrapper newSsl(SSLParametersImpl sslParameters,
ConscryptFileDescriptorSocket engine) {
try {
return SslWrapper.newInstance(sslParameters, engine, engine, engine);
} catch (SSLException e) {
throw new RuntimeException(e);
}
}
SslWrapper实例化涉及NativeCrypto,依赖C++代码:
https://android.googlesource.com/platform/external/conscrypt/+/refs/tags/android-8.1.0_r12/common/src/main/java/org/conscrypt/SslWrapper.java
static SslWrapper newInstance(SSLParametersImpl parameters,
SSLHandshakeCallbacks handshakeCallbacks, AliasChooser chooser,
PSKCallbacks pskCallbacks) throws SSLException {
long ctx = parameters.getSessionContext().sslCtxNativePointer;
long ssl = NativeCrypto.SSL_new(ctx);
return new SslWrapper(ssl, parameters, handshakeCallbacks, chooser, pskCallbacks);
}
新版本:
https://android.googlesource.com/platform/external/conscrypt/+/refs/tags/android-cts-9.0_r18/common/src/main/java/org/conscrypt/ConscryptFileDescriptorSocket.java
private static NativeSsl newSsl(SSLParametersImpl sslParameters,
ConscryptFileDescriptorSocket engine) throws SSLException {
return NativeSsl.newInstance(sslParameters, engine, engine, engine);
}
可用的修复方案
https://stackoverflow.com/questions/55143564/anr-and-crash-in-an-android-app-android-8-1-90-huawei-devices
方案中直接依赖了:
implementation 'org.conscrypt:conscrypt-android:2.5.2'
启动时初始化:
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O_MR1) {
Security.insertProviderAt(Conscrypt.newProvider(), 1);
Log.e("sslProvider", SSLSocketFactory.getDefault()::class.java.getName())
}
方案会引入新的so,三个架构so总共7.75m,平均一个2.5m,修复这个bug的代价是安装包总体变大。
然而这个crash对crash率贡献量较小,有点不划算。
更新
对拦截器进行包装,将运行时异常转化成IO异常。
class Android81RuntimeExceptionHandlerWrapperInterceptor private constructor(
private val interceptor: Interceptor
) : Interceptor {
companion object {
private const val TAG = "Android81RuntimeExceptionHandlerWrapperInterceptor"
fun Interceptor.wrappedIssue7792484(): Interceptor {
return Android81RuntimeExceptionHandlerWrapperInterceptor(this)
}
}
override fun intercept(chain: Interceptor.Chain): Response {
try {
return interceptor.intercept(chain)
} catch (e: RuntimeException) {
val cause = e.cause
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O_MR1 && cause is SSLException) {
HLLog.e(TAG, "Caught and converted Android 8.1 SSL RuntimeException")
throw IOException("SSL handshake failed on Android 8.1", e)
} else {
throw e
}
}
}
}

3903

被折叠的 条评论
为什么被折叠?



