这两天一直被一个bug困扰,首先介绍一下这个bug:使用ksoap2通过webservice获取数据,在解析数据的时候会导致android系统不断
增大内存栈的大小,直到Out of Memory。
bug环境:由于项目需要通过webservice 来获取数据,虽然可以自己写一个xml解析器,但是有第三方的解析jar包干嘛不用呢,而且发
现ksoap2是一个专门针对android定制的xml 解析器,使用的人还不少,于是就决定使用这个了。在使用的过程中发现,在进行数据解
析的时候会出现一个无法捕捉的异常,然后会导致android系统不断增大内存栈的大小,直到Out of Memory。我使用的ksoap2的包为
ksoap2-3.2.0。
之前一直在关注 Out of Memory这个问题,我以为这个无法捕捉的异常就是Out of Memory导致的,后来通过日志以及debug等调试手
段定位到了具体哪一行出了问题,由于前面有几行相同的代码却没有出现问题,所以就没有进行深入分析了。还是关注在Out of
Memory这个问题上面。
下面贴一段调用ksoap2 api获取webservice数据的代码
public static InsuranceInfo queryInsuranceInfo(String id,String report_num){
String method_name = "getInsuranceBillInfo";
if(id!=null && report_num!=null){
SoapObject object = new SoapObject(nameSpace, method_name);
object.addProperty("id", id);
object.addProperty("registNo",report_num);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = false;
envelope.implicitTypes = true;
envelope.setOutputSoapObject(object);
HttpTransportSE se = new HttpTransportSE(Url);
se.debug = true;
try {
se.call(null, envelope);
if(envelope.getResponse()!=null){
InsuranceInfo insurance = new InsuranceInfo();
SoapObject sObject = (SoapObject) envelope.bodyIn;
SoapObject soReturn = (SoapObject)sObject.getProperty("return");
insurance.setInsurance_people_name(soReturn.getProperty("insurer").toString());
SoapObject so = (SoapObject)soReturn.getProperty("prplcitemcar");
int count = so.getPropertyCount();
for (int i = 0; i < count; i++) {
String str = so.getProperty(i).toString();
switch(i){
case 0:
insurance.setCar_real_value(str);
break;
case 1:
insurance.setCar_modle(str);
break;
case 4:
insurance.setCar_num(str);
break;
case 5:
insurance.setCar_sell_price(str);
break;
case 7:
insurance.setInsurance_type(str);
break;
case 2:
insurance.setRegister_time(str);
break;
case 8:
insurance.setUse(str);
break;
case 6:
insurance.setCar_real_value(str);
break;
default:
break;
}
}
return insurance;
}
} catch (HttpResponseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (XmlPullParserException e){
e.printStackTrace();
}
}
return null;
}
第23行的代码和第27行的代码几乎相同,就是调用的方式不同而已,但是这个bug确是在27行出现的,后来通过调试发现23行代
码所获取的数据不为空,但是27行返回的数据为空,也就是将一个空对象强制转化为String类型时会出现无法捕捉的异常,进而
导致应用内存栈不断增大,从而导致Out of Memory,这就是这个bug的形成原因,但是为什么没有报空指针异常,我在相同的
AsynTask中调用一个为空的对象的toString()方法却出现了空指针异常。
后来另一个写法:SoapObject msg = (SoapObject)so.getProperty(i),so.getProperty(i)返回的是一个Object对象,这行代码中
的Object其实是一个String字符串,我将其强制转换成SoapObject对象时,也会重新上述情况,其实他应该报类型转换异常,但
是却出现了一个未捕捉的异常,从而导致Out of Memory。
所以如果在ksoap2解析数据时出现解析错误,系统不会出现相应的错误日志,而是出现thread exiting with uncaught exception
从而导致应用出现内存溢出。