Okhttp: Crashes on OutOfMemoryError, while there are 257 "OkHttp ConnectionPool" threads

Created on 11 Sep 2016  路  4Comments  路  Source: square/okhttp

We've recently migrated our app to OkHttp, and we've now getting several crashes for out-of-memory related errors.
Looking at the crashes we see hundreds of threads running at:
okhttp3.ConnectionPool$1.run (ConnectionPool.java:66)

The stack of the crash itself is:

Fatal Exception: java.lang.OutOfMemoryError: Could not allocate JNI Env
at java.lang.Thread.nativeCreate(Thread.java)
at java.lang.Thread.start(Thread.java:1063)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:921)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1339)
at okhttp3.ConnectionPool.put(ConnectionPool.java:135)
at okhttp3.OkHttpClient$1.put(OkHttpClient.java:149)
at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:188)
at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:129)
at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:98)
at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:109)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:124)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:170)
at okhttp3.RealCall.execute(RealCall.java:60)
at MyActivity.myFunction(MyActivity.java:853)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)

Shouldn't there be a limit on how many threads can OkHttp create?

Most helpful comment

All 4 comments

Thanks for the quick reply.
We were under the impression that builder() will return an existing instance, we'll get that fixed, thanks! 馃憤

@marmor7 Do you mean to say if we use builder() like following inside a method and call that method multiple times, each time a new instance of the client will be created and each instance will holds its own connection pool and thread pools?

public void doOpen() {
     // ..... 
     OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder()
                // turn off timeouts (github.com/socketio/engine.io-client-java/issues/32)
                .connectTimeout(0, TimeUnit.MILLISECONDS)
                .readTimeout(0, TimeUnit.MILLISECONDS)
                .writeTimeout(0, TimeUnit.MILLISECONDS);
    // ...
    final OkHttpClient client = clientBuilder.build();
    // ...
}

Reference: Websocket.java for engine.io-client-java project.

@shobhitpuri yes, that's exactly what we did, and had ton of memory issues.

From the docs:

OkHttp performs best when you create a single OkHttpClient instance and reuse it for all of your HTTP calls. This is because each client holds its own connection pool and thread pools. Reusing connections and threads reduces latency and saves memory. Conversely, creating a client for each request wastes resources on idle pools.

Instead, we now have a single OkHttpClient that we build once, and is used by all methods.

Was this page helpful?
0 / 5 - 0 ratings