在大型机身上对OOM进行改造

时间:2015-07-22 10:42:39

标签: android retrofit okhttp

我使用改造发送相当大的文件,偶尔会有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。我的身体是一个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的块发送我的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。

1 个答案:

答案 0 :(得分:2)

显然,Splunk Mint与OkHttp有issues。禁用网络监控可以解决问题。