我正在使用 retrofit 发送相当大的文件,并且偶尔会遇到 OOM。方法:
@POST("/psm-service/model/{model}/video")
void sendVideo(@Header("X-Facebook-Access-Token") String token,
@Header("X-FB-Id") long fbId,
@Header("Content-Disposition") String contentDisposition,
@Path("model") long modelId,
@Body TypedOutput video,
Callback<Response> callback);
和服务:
RestAdapter adapter = new RestAdapter.Builder()
.setClient(new OkClient(Certification.getClient(this)))
.setEndpoint(Api.ENDPOINT)
.setLogLevel(BuildConfig.DEBUG ? RestAdapter.LogLevel.BASIC : RestAdapter.LogLevel.NONE)
.build();
service = adapter.create(Api.ApiService.class);
客户端是一个带有自定义 SSL 的 OkHttpClient。我的 body 是一个 TypedOutput,它使用 android 内容 URI 并设置长度、mimetype 和文件名。
@Override
public void writeTo(OutputStream out) throws IOException {
Utils.copyStream(getContentResolver().openInputStream(uri), out);
}
public static void copyStream(InputStream input, OutputStream output)
throws IOException
{
byte[] buffer = new byte[1024]; // Adjust if you want
int bytesRead;
while ((bytesRead = input.read(buffer)) != -1)
{
output.write(buffer, 0, bytesRead);
}
}
据我所知,这应该以 1KB 的 block 发送我的 50 多 MB 文件。由于服务器限制,我必须传递文件大小。我试过完全关闭日志记录,但这没有帮助。
在其中一个较大的文件中,OOM 被抛入此方法。
java.lang.OutOfMemoryError: Failed to allocate a 120252388 byte allocation with 16777216 free bytes and 81MB until OOM
at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:95)
at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:146)
at java.lang.StringBuffer.append(StringBuffer.java:219)
at com.splunk.mint.network.io.OutputStreamMonitor.updateBody(OutputStreamMonitor.java:67)
at com.splunk.mint.network.io.OutputStreamMonitor.write(OutputStreamMonitor.java:58)
at okio.Okio$1.write(Okio.java:78)
at okio.AsyncTimeout$1.write(AsyncTimeout.java:155)
at okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.java:133)
at okio.RealBufferedSink.write(RealBufferedSink.java:45)
at com.squareup.okhttp.internal.http.HttpConnection$FixedLengthSink.write(HttpConnection.java:300)
at okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.java:133)
at okio.RealBufferedSink$1.write(RealBufferedSink.java:148)
at lt.segfoltas.common.util.Utils.copyStream(Utils.java:51)
at lt.segfoltas.psm_casting.net.FormUploaderService$TypedStream.writeTo(FormUploaderService.java:565)
at retrofit.client.OkClient$1.writeTo(OkClient.java:88)
at com.squareup.okhttp.Call.getResponse(Call.java:237)
at com.squareup.okhttp.Call.execute(Call.java:84)
at retrofit.client.OkClient.execute(OkClient.java:53)
at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:326)
at retrofit.RestAdapter$RestHandler.access$100(RestAdapter.java:220)
at retrofit.RestAdapter$RestHandler$2.obtainResponse(RestAdapter.java:278)
at retrofit.CallbackRunnable.run(CallbackRunnable.java:42)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at retrofit.Platform$Android$2$1.run(Platform.java:142)
at java.lang.Thread.run(Thread.java:818)
编辑:
我对我的堆栈跟踪中的 bugsense 方法持怀疑态度,所以我注释掉了 Mint.initAndStartSession
,现在我的堆甚至保持在 48MB,而之前是 200MB。虽然这解决了我的问题,但我想继续使用 bugsense。
显然 Splunk Mint 有 issues使用 OkHttp。禁用网络监控可解决此问题。
我是一名优秀的程序员,十分优秀!