Android的HttpClient的OOM在4G / LTE(HTC霹雳) [英] Android HttpClient OOM on 4G/LTE (HTC Thunderbolt)

查看:179
本文介绍了Android的HttpClient的OOM在4G / LTE(HTC霹雳)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经得到了从崩溃的一些用户报告时尝试使用我的应用程序在Verizon的4G / LTE。

看着堆栈跟踪,它看起来像Android的HttpClient.execute()实现抛出OOM。这种情况只有在4G / LTE设备,具体地说宏达霹雳,只有当在4G / LTE。 WIFI,3G,UMTS都OK。也能正常工作在Sprint的WiMax 4G东西能正常工作。

两个问题:

  • 什么是获得Android的开发者对此的注意力的最好方法是什么?任何比 HTTP报告更好的选择://$c$c.google.com/p/android/issues

  • 我如何能解决这个任何想法?我没有一个4G的设备自己,我不能让这种情况发生在仿真器,所以我需要在这里做出一些推测。我可以尝试捕捉OOM在我的code和尝试清理和力GC,但我不知道这是一个好主意。意见或其他建议?

下面就是我的code的做的:

 的HttpParams PARAMS = this.getHttpParams(); //返回PARAMS
    ClientConnectionManager厘米=新ThreadSafeClientConnManager(参数,可以this.getHttpSchemeRegistry());
    DefaultHttpClient的HttpClient =新DefaultHttpClient(厘米,则params);

    HTT presponse响应= NULL;
    要求=新HTTPGET(URL);

    尝试 {

        响应= httpClient.execute(要求); //<  -  OOM对4G / LTE。 OK,否则
        。INT状态code = response.getStatusLine()的getStatus code();
        Log.i(读取器,执行返回的HTTP状态+状态code);

    ...
 

下面是崩溃的堆栈跟踪:

  

E / dalvikvm堆(11639):内存不足   在2055696字节分配。   I / dalvikvm(11639):线程16PRIO = 5   TID = 9 RUNNABLE I / dalvikvm(11639):|   组=主SCOUNT = 0 dsCount = 0 S = N   OBJ = 0x48563070自我= 0x3c4340   I / dalvikvm(11639):| sysTid = 11682   漂亮= 0 sched的= 0/0 CGRP =默认   处理= 3948760 I / dalvikvm(11639):|   schedstat =(208709711 74005130 214)

     

I / dalvikvm(11639):在   org.apache.http.impl.io.AbstractSessionInputBuffer.init(AbstractSessionInputBuffer.java:~79)   I / dalvikvm(11639):在   org.apache.http.impl.io.SocketInputBuffer(SocketInputBuffer.java:93)   I / dalvikvm(11639):在   org.apache.http.impl.SocketHttpClientConnection.createSessionInputBuffer(SocketHttpClientConnection.java:83)   I / dalvikvm(11639):在   org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer(DefaultClientConnection.java:170)   I / dalvikvm(11639):在   org.apache.http.impl.SocketHttpClientConnection.bind(SocketHttpClientConnection.java:106)   I / dalvikvm(11639):在   org.apache.http.impl.conn.DefaultClientConnection.openCompleted(DefaultClientConnection.java:129)   I / dalvikvm(11639):在   org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:173)   I / dalvikvm(11639):在   org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)   I / dalvikvm(11639):在   org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)   I / dalvikvm(11639):在   org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:348)   I / dalvikvm(11639):在   org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)   I / dalvikvm(11639):在   org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)   I / dalvikvm(11639):在   org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)   I / dalvikvm(11639):在   com.myapplication.Fetcher.trySourceFetch(Fetcher.java:205)   I / dalvikvm(11639):在   com.myapplication.Fetcher.run(Fe​​tcher.java:298)   I / dalvikvm(11639):在   java.lang.Thread.run(Thread.java:1102)   I / dalvikvm(11639):E / dalvikvm(11639):   超出内存:堆大小= 24171KB,   分配= 23142KB,位图大小= 59KB,   极限= 21884KB E / dalvikvm(11639):额外   信息:足迹= 24327KB,允许   足迹= 24519KB,裁剪= 348KB   W / dalvikvm(11639):主题ID = 9:螺纹   与未捕获的异常退出   (组= 0x40025b38)

解决方案
  

看着堆栈跟踪,它看起来像Android的HttpClient.execute()实现抛出OOM。

这不是由堆栈跟踪你必须在这个问题上表示。当然,你没有提供有关该问题的整个堆栈跟踪。

  

什么是获得Android的开发者对此的注意力的最好方法是什么?任何比 HTTP报告更好的选择://$c$c.google.com/p/android/issues

这是一个纯粹的Andr​​oid的bug

的几率很小,但不为零。

下面是一些其他的可能性,在没有特定的顺序:

  1. 有没有问题,执行()本身,但你只是运行内存,堆栈跟踪你所遇到的只是展示该执行()就是讲你的堆。

  2. 现在的问题是在一些修改,宏达电发到Android的迅雷,可能只能采取在LTE网络上的效果。

  3. 这个问题以某种方式通过Veri​​zon的LTE网络本身造成的(例如,他们的传回,是造成怪僻信息,一些代理的HttpClient有一个歇斯底里)。

  

我如何能解决这个任何想法?

首先,我会使用现有的工具(例如,倾倒HPROF和与Eclipse MAT检查),以确认您没有在一般的内存泄漏,该迅雷/ LTE的组合完全是给绊倒。

接下来,我建议你想出一些方法来始终如一地重现错误。这可能是你用一系列步骤现有的应用程序来跟踪,也可以是一个专用的应用程序(例如,登录触发OOM的URL,然后创建一个小的应用程序,只是这是否HttpClient的要求)。我希望的DeviceAnywhere有一个霹雳,但它看起来并不像它。我会把一些试探一下,看看我是否能得到在这一方面有所帮助。

在它周围的工作,作为权宜之计而言,则可以检测到你使用的是迅雷通过 android.os.Build 数据运行,也许你通过 ConnectivityManager (我猜LTE将列出作为WiMAX的,但是这只是一个猜测),并警告有关问题与该组合的用户。再在LTE

除此之外,你可以尝试改变你的HttpClient使用了一下,看它是否有效果,如:

  • 如果你只支持API级别8或更高版本,你可以给 AndroidHttpClient 射击作为简易替换
  • 禁用多线程访问(一般或迅雷专用),并摆脱了 ThreadSafeClientConnManager

我很抱歉,我没有灵丹妙药的答案,你在这里。


更新

现在,我有完整的堆栈跟踪,翻翻源$ C ​​$ c为...启发,一些。

这个问题似乎是:

  HttpConnectionParams.getSocketBufferSize(PARAMS);
 

将返回该2MB左右的值,触发了OOM。这是一个非常大的缓冲,特别是对于Dalvik的GC引擎,它可以得到支离破碎(是的,有这个词再次)。

PARAMS 这里是的HttpParams 。你似乎旨在通过那些自己getHttpParams()。例如, AndroidHttpClient 设置,为8192:

  HttpConnectionParams.setSocketBufferSize(PARAMS,8192);
 

如果您自行设置的套接字缓冲区大小,尽量减少它。如果没有,尝试将它设置为8192,看看有没有什么帮助。

I have gotten some reports from users of crashes when try use my application on Verizon's 4G/LTE.

Looking at the stack trace, it looks like Android's HttpClient.execute() implementation is throwing an OOM. This happens only on 4G/LTE devices, specifically HTC Thunderbolt, and only when on 4G/LTE. WiFi, 3G, UMTS are OK. Also works fine on Sprint's WiMax 4G stuff works fine.

Two questions:

  • What's the best way to get the attention of Android devs about this? Any better options than reporting on http://code.google.com/p/android/issues?

  • Any ideas on how I can work around this? I don't have a 4G device myself and I can't get this happen in the emulator so I need to make some educated guesses here. I can try to catch the OOM in my code and attempt to cleanup and force GC, but I'm not sure if that's a good idea. Comments or other suggestions?

Here's what my code's doing:

    HttpParams params = this.getHttpParams(); // returns params
    ClientConnectionManager cm = new ThreadSafeClientConnManager(params, this.getHttpSchemeRegistry() );
    DefaultHttpClient httpClient = new DefaultHttpClient( cm, params );

    HttpResponse response = null;
    request = new HttpGet( url );

    try {

        response = httpClient.execute(request); // <-- OOM on 4G/LTE. OK otherwise
        int statusCode = response.getStatusLine().getStatusCode();
        Log.i("fetcher", "execute returned, http status " + statusCode );

    ...

Here's the crashing stack trace:

E/dalvikvm-heap(11639): Out of memory on a 2055696-byte allocation. I/dalvikvm(11639): "Thread-16" prio=5 tid=9 RUNNABLE I/dalvikvm(11639): | group="main" sCount=0 dsCount=0 s=N obj=0x48563070 self=0x3c4340 I/dalvikvm(11639): | sysTid=11682 nice=0 sched=0/0 cgrp=default handle=3948760 I/dalvikvm(11639): | schedstat=( 208709711 74005130 214 )

I/dalvikvm(11639): at org.apache.http.impl.io.AbstractSessionInputBuffer.init(AbstractSessionInputBuffer.java:~79) I/dalvikvm(11639): at org.apache.http.impl.io.SocketInputBuffer.(SocketInputBuffer.java:93) I/dalvikvm(11639): at org.apache.http.impl.SocketHttpClientConnection.createSessionInputBuffer(SocketHttpClientConnection.java:83) I/dalvikvm(11639): at org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer(DefaultClientConnection.java:170) I/dalvikvm(11639): at org.apache.http.impl.SocketHttpClientConnection.bind(SocketHttpClientConnection.java:106) I/dalvikvm(11639): at org.apache.http.impl.conn.DefaultClientConnection.openCompleted(DefaultClientConnection.java:129) I/dalvikvm(11639): at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:173) I/dalvikvm(11639): at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) I/dalvikvm(11639): at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) I/dalvikvm(11639): at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:348) I/dalvikvm(11639): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) I/dalvikvm(11639): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) I/dalvikvm(11639): at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465) I/dalvikvm(11639): at com.myapplication.Fetcher.trySourceFetch(Fetcher.java:205) I/dalvikvm(11639): at com.myapplication.Fetcher.run(Fetcher.java:298) I/dalvikvm(11639): at java.lang.Thread.run(Thread.java:1102) I/dalvikvm(11639): E/dalvikvm(11639): Out of memory: Heap Size=24171KB, Allocated=23142KB, Bitmap Size=59KB, Limit=21884KB E/dalvikvm(11639): Extra info: Footprint=24327KB, Allowed Footprint=24519KB, Trimmed=348KB W/dalvikvm(11639): threadid=9: thread exiting with uncaught exception (group=0x40025b38)

解决方案

Looking at the stack trace, it looks like Android's HttpClient.execute() implementation is throwing an OOM.

That is not indicated by the stack trace you have on the issue. Of course, you didn't provide the whole stack trace on the issue.

What's the best way to get the attention of Android devs about this? Any better options than reporting on http://code.google.com/p/android/issues?

The odds of this being a pure Android bug are small, though not zero.

Here are some other possibilities, in no particular order:

  1. There is no problem with execute() per se, but that you are simply running out of memory, and the stack traces you have encountered are simply demonstrating that execute() is stressing your heap.

  2. The problem is in some modifications that HTC made to Android for the Thunderbolt, possibly only taking effect when on the LTE network.

  3. The problem is somehow caused by the Verizon LTE network itself (e.g., some proxy of theirs sending back screwball information that is causing HttpClient to have a conniption).

Any ideas on how I can work around this?

First, I'd use existing tools (e.g., dumping HPROF and examining with Eclipse MAT) to confirm that you don't have a memory leak in general that the Thunderbolt/LTE combo just seems to be tripping over.

Next, I recommend that you come up with some way to consistently reproduce the error. That could be your existing app with a series of steps to follow, or it could be a dedicated app (e.g., log the URL that triggers the OOM, then create a tiny app that just does that HttpClient request). I wish DeviceAnywhere had a Thunderbolt, but it doesn't look like it. I'll put some feelers out and see if I can get some help on that front.

In terms of working around it, as a stopgap, you can detect that you're running on a Thunderbolt via android.os.Build data, and perhaps that you're on LTE via ConnectivityManager (I'm guessing LTE would list as WiMAX, but that's just a guess), and warn users about the problems with that combo.

Beyond that, you can try changing up your HttpClient usage a bit and see if it has an effect, such as:

  • If you are only supporting API Level 8 or higher, you could give AndroidHttpClient a shot as a drop-in replacement
  • Disable multi-threaded access (in general or Thunderbolt-specific) and get rid of the ThreadSafeClientConnManager

I'm sorry that I don't have a "magic bullet" answer for you here.


UPDATE

Now that I have the full stack trace, looking through the source code is...illuminating, somewhat.

The problem appears to be that:

HttpConnectionParams.getSocketBufferSize(params);

is returning that 2MB or so value that is triggering the OOM. That's an awfully big buffer, particularly for the Dalvik GC engine, which can get fragmented (yes, there's that word again).

params here is the HttpParams. You seem to be creating those yourself via getHttpParams(). For example, AndroidHttpClient sets that to 8192:

HttpConnectionParams.setSocketBufferSize(params, 8192);

If you are setting the socket buffer size yourself, try reducing it. If not, try setting it to 8192 and see if that helps.

这篇关于Android的HttpClient的OOM在4G / LTE(HTC霹雳)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆