Android HttpClient crashes the application using java.lang.OutOfMemoryError : pthread_create… here is a solution to the problem.
Android HttpClient crashes the application using java.lang.OutOfMemoryError : pthread_create
I recently ran into this exception that crashes the app :
java.lang.OutOfMemoryError: pthread_create (stack size 16384 bytes) failed: Try again
at java.lang.VMThread.create(VMThread.java)
at java.lang.Thread.start(Thread.java:1029)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:920)
at java.util.concurrent.ThreadPoolExecutor.processWorkerExit(ThreadPoolExecutor.java:988)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
In the crash report I can see that more than 1000 threads were created (RefQueueWorker), which explains OOM. All threads are waiting, here is the dump:
[email protected]@43b42098
at java.lang.Object.wait(Object.java)
at java.lang.Object.wait(Object.java:401)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:102)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:73)
at org.apache.http.impl.conn.tsccm.RefQueueWorker.run(RefQueueWorker.java:102)
at java.lang.Thread.run(Thread.java:841)
(...)
[email protected]@45f62f08
at java.lang.Object.wait(Object.java)
at java.lang.Object.wait(Object.java:401)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:102)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:73)
at org.apache.http.impl.conn.tsccm.RefQueueWorker.run(RefQueueWorker.java:102)
at java.lang.Thread.run(Thread.java:841)
The code to get the HttpClient is:
public static HttpClient getHttpClient(Context context)
{
HttpClient httpClient = AndroidHttpClient.newInstance("appname", context);
HttpParams params = httpClient.getParams();
params.setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
HttpConnectionParams.setConnectionTimeout(params, 5000);
HttpConnectionParams.setSoTimeout(params, 5000);
return httpClient;
}
Each request closes AndroidHttpClient in the finally block:
...
finally
{
if ((client instanceof AndroidHttpClient))
{
((AndroidHttpClient) client).close();
}
}
I can’t reproduce this crash, it only happens with one user (Nexus 5/API 4.4.2). I wonder what is the root cause of so many threads created?
Thanks
Solution
java.util.concurrent.ThreadPoolExecutor.threadFactory has the following comments:
/**
* Factory for new threads. All threads are created using this
* factory (via method addWorker). All callers must be prepared
* for addWorker to fail, which may reflect a system or user's
* policy limiting the number of threads. Even though it is not
* treated as an error, failure to create threads may result in
* new tasks being rejected or existing ones remaining stuck in
* the queue.
*
* We go further and preserve pool invariants even in the face of
* errors such as OutOfMemoryError, that might be thrown while
* trying to create threads. Such errors are rather common due to
* the need to allocate a native stack in Thread.start, and users
* will want to perform clean pool shutdown to clean up. There
* will likely be enough memory available for the cleanup code to
* complete without encountering yet another OutOfMemoryError.
*/
Therefore, you should use a custom thread factory to avoid or reduce the chance of this error.