psy*_*tik 21 android httpclient htc-thunderbolt 4g htc-android
当我尝试在Verizon的4G/LTE上使用我的应用程序时,我收到了一些崩溃用户的报告.
查看堆栈跟踪,看起来Android的HttpClient.execute()实现正在抛出一个OOM.这仅发生在4G/LTE设备上,特别是HTC Thunderbolt,并且仅在4G/LTE上.WiFi,3G,UMTS都可以.也适用于Sprint的WiMax 4G工作正常.
两个问题:
什么是引起Android开发者注意的最佳方式?除了在http://code.google.com/p/android/issues上报告之外,还有哪些更好的选择?
关于如何解决这个问题的任何想法?我自己没有4G设备,我无法在模拟器中实现这一点,所以我需要在这里做一些有根据的猜测.我可以尝试在我的代码中捕获OOM并尝试清理并强制GC,但我不确定这是不是一个好主意.评论或其他建议?
这是我的代码正在做的事情:
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 );
...
Run Code Online (Sandbox Code Playgroud)
这是崩溃的堆栈跟踪:
E/dalvikvm-heap(11639):2055696字节分配的内存不足.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.AbstractPooledC onnAdapter.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) ):内存不足:堆大小= 24171KB,分配= 23142KB,位图大小= 59KB,限制= 21884KB E/dalvikvm(11639):额外信息:占用空间= 24327KB,允许占用空间= 24519KB,修剪= 348KB W/dalvikvm(11639) ):threadid = 9:线程退出未捕获的异常(group = 0x40025b38)
Com*_*are 26
查看堆栈跟踪,看起来Android的HttpClient.execute()实现正在抛出一个OOM.
您在问题上的堆栈跟踪没有表明这一点.当然,您没有提供有关该问题的整个堆栈跟踪.
什么是引起Android开发者注意的最佳方式?除了在http://code.google.com/p/android/issues上报告之外,还有哪些更好的选择?
这是一个纯粹的Android bug的几率很小,但不是零.
以下是其他一些可能性,没有特别的顺序:
execute()本身没有问题,但是你只是内存耗尽,而你遇到的堆栈跟踪只是表明这execute()会给你的堆压力.
问题在于HTC为Android制作了一些针对Thunderbolt的修改,可能只在LTE网络上生效.
这个问题在某种程度上是由Verizon LTE网络本身造成的(例如,他们的一些代理发回了导致HttpClient有一个conniption的螺旋信息).
关于如何解决这个问题的任何想法?
首先,我使用现有工具(例如,转储HPROF并使用Eclipse MAT进行检查)来确认您通常没有内存泄漏,因为Thunderbolt/LTE组合似乎正在绊倒.
接下来,我建议您想出一些方法来始终如一地重现错误.这可能是您现有的应用程序,需要遵循一系列步骤,或者它可以是专用应用程序(例如,记录触发OOM的URL,然后创建一个只执行HttpClient请求的小应用程序).我希望DeviceAnywhere有一个Thunderbolt,但它看起来不像.我会把一些触角拿出来,看看我是否能在这方面得到一些帮助.
在解决这个问题方面,作为权宜之计,你可以通过android.os.Build数据检测到你在Thunderbolt上运行,也许你正在通过LTE进行运营ConnectivityManager(我猜测LTE将列为WiMAX,但这只是猜测),并警告用户该组合的问题.
除此之外,您可以尝试稍微改变您的HttpClient使用情况,看看它是否有效,例如:
AndroidHttpClient其作为替代品ThreadSafeClientConnManager对不起,我这里没有"魔弹"答案.
UPDATE
现在我已经拥有完整的堆栈跟踪,查看源代码是......有点亮.
问题似乎是:
HttpConnectionParams.getSocketBufferSize(params);
Run Code Online (Sandbox Code Playgroud)
正在返回触发OOM的2MB左右的值.这是一个非常大的缓冲区,特别是对于Dalvik GC引擎而言,它可能会变得支离破碎(是的,再次出现这个词).
params这是HttpParams.你似乎是通过自己创造的getHttpParams().例如,AndroidHttpClient将其设置为8192:
HttpConnectionParams.setSocketBufferSize(params, 8192);
Run Code Online (Sandbox Code Playgroud)
如果您自己设置套接字缓冲区大小,请尝试减少它.如果没有,请尝试将其设置为8192并查看是否有帮助.
| 归档时间: |
|
| 查看次数: |
4640 次 |
| 最近记录: |