返回介绍

6.3 序列化相关的异常

发布于 2024-08-17 23:46:12 字数 3567 浏览 0 评论 0 收藏 0

Android中的序列化分两种,一种是原始的Serializable,另一种是Android为了提升性能而量身打造的Parcelable。接下来将介绍序列化不当导致的异常。

6.3.1 实体对象不支持序列化

异常中的关键字:

Parcelable encountered IOException writing serializable object(name=xxx)……

发生频率:★★★

看下面这个实体类,它看上去是支持序列化的:

public class UserInfo implements Serializable {
  private static final long serialVersionUID = 1L;
  private String username;
  private CreditCard creditCard; 
  public UserInfo(){
  }

看其中的CreditCard实体,它的定义如下:

public class CreditCard {
  public String cardNO;

也就是说,CreditCard类不支持序列化。那么,当UserInfo对象中CreditCard属性的值为空时,没有任何问题;而一旦CreditCard属性值不为空,那么UserInfo在序列化的时候,就会因为这个属性不能序列化而崩溃。

提示  JSONObject和JSONArray不支持序列化

对于JSONObject和JSONArray这样的类型,也是不支持序列化的,所以实体中一旦有这样的属性,必然崩溃。

6.3.2 序列化时未指定ClassLoader

异常中的关键字:

BadParcelableException:ClassNotFoundException when unmarshalling……

发生频率:★★

在使用Parcelable机制的时候,会遇到上述异常信息。

比如说下面这个序列号类MyParcelable,有个自定义类型ClassA的属性a:

public class MyParcelable implements Parcelable {
  private String mStr;
  private ClassA a;   
  …


.. // 省略若干语句



  private MyParcelable(Parcel in) {
    mStr = in.readString();
    a = in.readParcelable(null);
  }
}

崩溃出在最后一句上,对a的反序列化上:

a = in.readParcelable(null);

当把它改为下面这样,就不会再崩溃了:

a=in.readParcelable(ClassA.class.getClassLoader());

提示  ClassLoader的概念

当ClassLoader为空时,系统会采取默认的ClassLoader。

Android有两种不同的ClassLoader:framework ClassLoader和apk ClassLoader,其中framework ClassLoader知道怎么加载Android系统内部的类;apk ClassLoader知道怎么加载我们自己写的类,也知道怎么加载Android系统内部的类。

在App刚启动时,默认ClassLoader是apk ClassLoader,但在系统内存不足应用被系统回收会再次启动,这个默认ClassLoader会变为framework ClassLoader,所以对于我们自己的类会报ClassNotFoundException。

6.3.3 反序列化时发现类找不到:被ProGuard混淆导致的崩溃

异常中的关键字:

Parcelable encountered ClassNotFoundException reading a Serializable object……

发生频率:★★

在反序列化的时候,发现有个类找不到。一般而言,这样的崩溃,在开发调试期间就会暴露出来。但为什么开发期间没事发到线上就出问题了呢?StackOverfiow上有个哥们契而不舍的花了2年时间查这个问题,最后发现是ProGuard导致的。

ProGuard对于Class.forName(className)中的class是无能为力的,它会将这个class混淆得面目全非,于是在反序列化这个类的时候却发现找不到这个类了,自然就会抛出这种异常信息了。相应的解决方案就是,在ProGuard文件中keep这个类。 [1]

6.3.4 反序列化时发现类找不到:传入畸形数据

异常中的关键字:

Parcelable encountered ClassNotFoundException reading a Serializable object(name=某个类名称)

发生频率:★★

这是一个最近发现的安全漏洞。

由于在App中使用了getSerializableExtra()的API,App开发人员没有对传入的数据做异常判断,别有企图的人可以通过传入畸形数据,导致本地拒绝服务。

例如传入简单类型,比如Integer,就会抛出类型转换异常ClassCastException。

而当传入自定义的可序列化对象时,就会抛出上述带有ClassNotFoundException的异常信息了。 [2]

6.3.5 反序列化时出错

异常中的关键字:

Could not read input channel file descriptors from parcel……

发生频率:★★★

出现这个异常,一般是因为Intent传递的数据太大了,貌似大于1MB就会崩溃。

此外,网上也有人说是因为FileDescripter太多而且没有关闭,或looper太多没有退出导致的,我没有验证过,仅供参考。

[1] 详细信息请参见http://stackoverf iow.com/questions/6014806/android-classnotfoundexception-when-passing-serializable-object-to-activity。

[2] 这个安全漏洞由360近期发现,参见http://blogs.360.cn/360mobile/2015/01/06/android-app通用型拒绝服务漏洞分析报告/。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文