4G/LTE上的Android HttpOOM客户端(HTC Thunderbolt)
我从用户那里得到了一些关于在Verizon的4G/LTE上使用我的应用程序时崩溃的报告 查看堆栈跟踪,看起来Android的HttpClient.execute()实现抛出了一个OOM。这仅在4G/LTE设备上发生,特别是HTC Thunderbolt,并且仅在4G/LTE上发生。WiFi、3G、UMTS都可以。在Sprint的WiMax 4G上也可以正常工作 两个问题:4G/LTE上的Android HttpOOM客户端(HTC Thunderbolt),android,httpclient,4g,htc-android,htc-thunderbolt,Android,Httpclient,4g,Htc Android,Htc Thunderbolt,我从用户那里得到了一些关于在Verizon的4G/LTE上使用我的应用程序时崩溃的报告 查看堆栈跟踪,看起来Android的HttpClient.execute()实现抛出了一个OOM。这仅在4G/LTE设备上发生,特别是HTC Thunderbolt,并且仅在4G/LTE上发生。WiFi、3G、UMTS都可以。在Sprint的WiMax 4G上也可以正常工作 两个问题: 要引起Android开发者的注意,最好的方法是什么?还有比报告更好的选择吗 有什么办法可以解决这个问题吗?我自己没有4G设
- 要引起Android开发者的注意,最好的方法是什么?还有比报告更好的选择吗
- 有什么办法可以解决这个问题吗?我自己没有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 );
...
HttpParams params=this.getHttpParams();//返回参数
ClientConnectionManager cm=新的ThreadSafeClientConnManager(参数,this.getHttpSchemeRegistry());
DefaultHttpClient httpClient=新的DefaultHttpClient(cm,参数);
HttpResponse响应=null;
请求=新的HttpGet(url);
试一试{
response=httpClient.execute(请求);//
查看堆栈跟踪,看起来Android的HttpClient.execute()实现抛出了一个OOM
您在问题上的堆栈跟踪没有指出这一点。当然,您没有提供问题的整个堆栈跟踪
要引起Android开发者的注意,最好的方法是什么?还有比报告更好的选择吗
这是一个纯粹的安卓bug的可能性很小,尽管不是零
以下是一些其他可能性,没有特定顺序:
execute()
问题在于HTC对Android的Thunderbolt做了一些修改,可能只有在LTE网络上才生效
这个问题不知何故是由Verizon LTE网络本身造成的(例如,他们的一些代理发回了导致HttpClient连接的古怪信息)
有什么办法可以解决这个问题吗
首先,我会使用现有的工具(例如,转储HPROF和使用EclipseMat进行检查)来确认您一般不会出现Thunderbolt/LTE组合似乎会遇到的内存泄漏
接下来,我建议你想出一些方法来一致地重现错误。这可能是你现有的应用程序,需要遵循一系列步骤,也可能是一个专用的应用程序(例如,记录触发OOM的URL,然后创建一个只执行HttpClient请求的小应用程序).我希望任何地方都有雷电,但看起来不像。我会试探一下,看看能否在这方面得到一些帮助
就解决这个问题而言,作为一种权宜之计,你可以通过android.os.Build
数据检测到你在Thunderbolt上运行,或者通过ConnectivityManager
检测到你在LTE上运行(我猜LTE会被列为WiMAX,但这只是一个猜测),并警告用户该组合存在的问题
除此之外,您还可以尝试稍微提高HttpClient的使用率,看看是否有效果,例如:
- 如果您只支持API级别8或更高,您可以给
AndroidHttpClient
一次机会作为替代品
- 禁用多线程访问(一般或特定于Thunderbolt)并摆脱ThreadSafeClientConnManager
很抱歉,我这里没有“魔弹”的答案
更新
现在我有了完整的堆栈跟踪,查看源代码是…有启发性的,有些
问题似乎是:
HttpConnectionParams.getSocketBufferSize(params);
正在返回触发OOM的2MB左右的值。这是一个非常大的缓冲区,特别是对于Dalvik GC引擎,它可能会变得支离破碎(是的,这个词又出现了)
params
这是HttpParams
。您似乎是通过getHttpParams()
自己创建的。例如,AndroidHttpClient
将其设置为8192:
HttpConnectionParams.setSocketBufferSize(params, 8192);
如果您自己设置套接字缓冲区大小,请尝试减小它。如果没有,请尝试将其设置为8192,看看是否有帮助。以下是修复方法:
同时,URLConnection是免疫的,这是唯一一个有这个问题的HttpClient
如果您是一名想要测试此类故障的开发人员,您可以使用“adb shell setprop”设置,例如,“net.tcp.buffersize.wifi”,这样当您的设备在wifi上时,最大读/写套接字缓冲区大小将是巨大的。类似以下内容将是一个真正的压力测试:
adb shell setprop net.tcp.buffersize.wifi 4096,80999999,80999999,4096,80999999,80999999
正是这种配置更改导致了HttpClient错误。我不知道Thunderbolt上的确切值是多少,但使用该设备的人可以使用“adb shell getprop | grep buffersize”来找到它。也许这会有所帮助:
// Set the timeout in milliseconds until a connection is established.
int timeoutConnection = 5000;
// Set the default socket timeout (SO_TIMEOUT)
// in milliseconds which is the timeout for waiting for data.
int timeoutSocket = 4000;
// set timeout parameters for HttpClient
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
HttpConnectionParams.setSocketBufferSize(httpParameters, 8192);//setting setSocketBufferSize
DefaultHttpClient httpClient = new DefaultHttpClient();
httpClient.setParams(httpParameters);
@Psychik:我根据进一步的研究更新了答案,它本身就是根据你修改的堆栈跟踪更新的。@Psychik:“顺便说一句,你能告诉我你在哪里找到这段代码吗?”--使用谷歌代码搜索()。在搜索栏中输入类名,在Package字段中输入android.git.kernel.org
。这对于解决此类问题非常有效。好消息是,所有行号都与回购协议中的最新内容匹配,因此没有任何猜测。我只是从实际的崩溃点开始反向工作,试图找出缓冲区大小来自@Psychik:“看看为什么我可能在其他手机/连接类型上看不到”——好吧,这是奇怪的部分。假设