这两天一直被一个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
从而导致应用出现内存溢出。