Android HttpClient引起应用程序崩溃,显示java.lang.OutOfMemoryError: pthread_create。

4
我最近遇到了这个异常导致应用崩溃:
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)

在崩溃报告中,我能看到超过1000个线程(RefQueueWorker)被创建,这解释了OOM。所有的线程都在等待,以下是转储内容:
RefQueueWorker@org.apache.http.impl.conn.tsccm.ConnPoolByRoute@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)

(...)

RefQueueWorker@org.apache.http.impl.conn.tsccm.ConnPoolByRoute@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)

获取 HttpClient 使用的代码为:
  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;
  }

每个请求都要在 finally 块中关闭 AndroidHttpClient :

...
finally
{
  if ((client instanceof AndroidHttpClient))
  {
    ((AndroidHttpClient) client).close();
  }
}

我无法重现这个崩溃,它只发生在一个用户身上(Nexus 5 / API 4.4.2)。我想知道这么多线程被创建的根本原因是什么?

谢谢。


为什么在完成 HTTP 通信后不使用 AndroidHttpClient.close() 呢?顺便说一下,这个方法的 Java 文档中写道:释放与此客户端相关联的资源。您必须调用此方法,否则会泄漏大量资源(套接字和内存)。 - anfy2002us
实际上,我在每个HTTP请求后关闭客户端。帖子已更新。谢谢。 - ebtokyo
1个回答

0

java.util.concurrent.ThreadPoolExecutor.threadFactory 有以下注释:

/**
 * 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.
 */

所以,您应该使用自定义的线程工厂来避免或减少此错误的发生机率。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接