OkHttp 3.11.0下StrictMode资源未释放异常的原因及修复
分析与修复StrictMode资源泄漏异常
嘿,我来帮你拆解这个StrictMode异常的问题~
问题根源分析
从异常栈可以看到,核心问题是**Inflater资源没有被调用end()方法释放**,这个Inflater来自OkHttp的GzipSource——也就是处理gzip压缩响应时创建的资源。
虽然你的SetJsonContentTypeHeaderInterceptor看起来只是添加请求头,但结合你使用的OkHttp 3.11.0版本,加上StrictMode的严格检测,问题的触发点可以归纳为:
- OkHttp 3.11.0本身存在一些资源释放的小问题,在处理gzip响应时,极端场景下会出现
GzipSource未被正确关闭,导致关联的Inflater资源泄漏。 - 你的拦截器中使用的
!!强制非空操作是多余的(OkHttp的chain.proceed()正常情况下绝不会返回null,失败会直接抛出IOException),虽然这不是直接诱因,但可能隐藏潜在的异常场景。 - 如果你的应用中存在未正确消费/关闭Response Body的场景(比如手动调用OkHttp Call时忘记关闭Body),也会触发这个StrictMode警告。
修复方案
针对这个问题,按优先级给你几个解决办法:
1. 移除拦截器中的多余!!,简化代码
首先把拦截器里的!!去掉,因为它完全没必要,还可能引入不必要的空指针风险。修改后的代码更简洁安全:
import okhttp3.Interceptor internal class SetJsonContentTypeHeaderInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): okhttp3.Response { val modifiedRequest = chain.request() .newBuilder() .header("Content-Type", "application/json") .header("Accept", "application/json") .build() return chain.proceed(modifiedRequest) } }
2. 升级OkHttp到较新的稳定版本
OkHttp 3.11.0是2018年的老版本,后续的3.x版本(比如3.14.9)以及4.x系列修复了大量资源泄漏相关的问题。建议你升级到兼容Retrofit 2.4.0的最新稳定OkHttp版本(Retrofit 2.4.0适配OkHttp 3.10+,所以升级到3.14.9完全没问题)。
3. 确保Response Body被正确关闭
如果你的代码中有手动处理OkHttp Response的场景,一定要确保Body被正确关闭。在Kotlin中可以使用use函数自动关闭资源:
val response = chain.proceed(modifiedRequest) response.body()?.use { body -> // 在这里处理Body的内容,use函数会自动帮你关闭Body } return response
如果是用Retrofit的接口调用,通常Retrofit会自动帮你处理Body的关闭,这一步可以忽略。
4. (可选)调整StrictMode检测策略(不推荐优先使用)
如果这个警告只是日志输出,不影响应用功能,可以暂时放宽StrictMode的处罚策略,比如只打印日志不触发崩溃:
StrictMode.setVmPolicy(StrictMode.VmPolicy.Builder() .detectLeakedClosableObjects() .penaltyLog() // 仅打印日志,不抛出异常 .build())
不过这只是治标不治本,还是建议优先采用前面的修复方案。
内容的提问来源于stack exchange,提问作者Alexey Timokhin
相关产品推荐
相关产品推荐

