okhttp上传文件出现OOM

okhttp是一个比较优秀的库,使用非常广泛,相信大家都比较熟悉。在最近的使用中却发现了一个OOM的情况,在上传比较大的图片或视频时会发生,日志如下

Caused by: java.lang.OutOfMemoryerror: Failed to alocate a 267201798 byte alcation with 8388608 free bytes and 233MB until OOM
at java.lang.StringFactory.newStringFromBytes(StringFactory.java:79)
at java.lang.StringFactory.newStringFromBytes(StringFactory,java:207)
at okio.Buffer.readString(Buffer.java:713)
at okio.Buffer.readString(Buffer.java:696)
at okhtpp3.logging.HttpLoggingInterceptor.intercept(HttpLoggingInterceptor.java:200)
…………

看日志是okhttp日志库的锅。HttpLoggingInterceptor是okhttp提供的一个日志库,代码比较简单,原理也是使用了拦截器来打印请求头请求体以及请求结果。来看一下出现OOM的地方

…………    
if (isPlaintext(buffer)) {
    logger.log(buffer.readString(charset));
    logger.log("--> END " + request.method()
        + " (" + requestBody.contentLength() + "-byte body)");
} else {
    logger.log("--> END " + request.method() + " (binary "
    + requestBody.contentLength() + "-byte body omitted)");
}
…………

如果打印基本是body而且有请求体就会打印请求体,其中isPlaintext用来判断是否可以打印body内容,然后使用Okio的Buffer来构建一个String并打印,当body太大时,需要构建内存会非常大,导致了OOM的发生。isPlaintext没有判断body是否包含文件信息(文件内容打印也没有意义),而且没有判断buffer是否过长 。

可以使用只打印HEADER来避免这种情况:

interceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);

或者复制一遍日志来修改代码,只打印一定长度的日志。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值