android 5.0以下系统Intent传递序列化对象的bug


    项目中使用插件框架,当插件在Intent中传递Serializable对象时,在android 5.0以下系统上会出现

E/InstrumentationHacker(25176): Parcelable encounteredClassNotFoundException reading a Serializable object (name = com.qihoo.browser.imageplugin.bean.HomeListBean)

E/InstrumentationHacker(25176): java.lang.RuntimeException: Parcelable encounteredClassNotFoundException reading a Serializable object (name = com.qihoo.browser.imageplugin.bean.HomeListBean)

E/InstrumentationHacker(25176): 	at android.os.Parcel.readSerializable(Parcel.java:2251)

E/InstrumentationHacker(25176): 	at android.os.Parcel.readValue(Parcel.java:2096)

E/InstrumentationHacker(25176): 	at android.os.Parcel.readListInternal(Parcel.java:2375)

E/InstrumentationHacker(25176): 	at android.os.Parcel.readArrayList(Parcel.java:1735)

E/InstrumentationHacker(25176): 	at android.os.Parcel.readValue(Parcel.java:2066)

E/InstrumentationHacker(25176): 	at android.os.Parcel.readArrayMapInternal(Parcel.java:2346)

E/InstrumentationHacker(25176): 	at android.os.Bundle.unparcel(Bundle.java:249)

E/InstrumentationHacker(25176): 	at android.os.Bundle.keySet(Bundle.java:345)

E/InstrumentationHacker(25176): 	at com.qihoo.plugin.core.PluginManager.unwrapIntent(PluginManager.java:1753)

原因是序列化对象的类是存放在插件的dex中的,因此反序列化要使用插件的ClassLoader才行,该错误是Intent在进行反序列化时,使用的宿主默认的ClassLoader导致出现找不到类的异常。

而实际上在使用该Intent前,已经将插件ClassLoader设置到Intent中了,理论上来说,不应该有问题。

activity.getIntent().setExtrasClassLoader(plugin.getCl());

这里使用android 4.4.2_r2 源码分析:

跟踪异常堆栈和系统源码,找到

/frameworks/base/core/java/android/os/Parcel.java

跟踪readValue()方法,定位到读取序列化对象的代码

2059
2060        case VAL_BYTE:
2061            return readByte();
2062
2063        case VAL_SERIALIZABLE:
2064            return readSerializable();
2065
2066        case VAL_PARCELABLEARRAY:
2067            return readParcelableArray(loader);
2068
2069        case VAL_SPARSEARRAY:
2070            return readSparseArray(loader);

可以发现,readSerializable()没有将loader传入进去,loader是通过setExtrasClassLoader()设置的插件ClassLoader,而readSerializable()中,直接使用默认的ClassLoader来进行反序列化,代码如下:

2200    public final Serializable readSerializable() {
2201        String name = readString();
2202        if (name == null) {
2203            // For some reason we were unable to read the name of the Serializable (either there
2204            // is nothing left in the Parcel to read, or the next value wasn't a String), so
2205            // return null, which indicates that the name wasn't found in the parcel.
2206            return null;
2207        }
2208
2209        byte[] serializedData = createByteArray();
2210        ByteArrayInputStream bais = new ByteArrayInputStream(serializedData);
2211        try {
2212            ObjectInputStream ois = new ObjectInputStream(bais);
2213            return (Serializable) ois.readObject();
2214        } catch (IOException ioe) {
2215            throw new RuntimeException("Parcelable encountered " +
2216                "IOException reading a Serializable object (name = " + name +
2217                ")", ioe);
2218        } catch (ClassNotFoundException cnfe) {
2219            throw new RuntimeException("Parcelable encountered" +
2220                "ClassNotFoundException reading a Serializable object (name = "
2221                + name + ")", cnfe);
2222        }
2223    }

也就是说,我们通过setExtrasClassLoader()方法设置的ClassLoader对Serializable对象来说,是没有作用的。

同样的,从

2066        case VAL_PARCELABLEARRAY:
2067            return readParcelableArray(loader);
可以看出,

setExtrasClassLoader()对Parcelable对象是有作用的。


从android 5.0.0_r2源码同样的位置:

/frameworks/base/core/java/android/os/Parcel.java

2193        case VAL_BYTE:
2194            return readByte();
2195
2196        case VAL_SERIALIZABLE:
2197            return readSerializable(loader);
2198
2199        case VAL_PARCELABLEARRAY:
2200            return readParcelableArray(loader);
2201
2202        case VAL_SPARSEARRAY:
2203            return readSparseArray(loader);
 
 
 

可以发现,已经对这个问题进行了处理。

结论:

android 5.0系统以下,Intent存在一个序列化bug,通过setExtrasClassLoader()方法设置的ClassLoader对象,对Serializable对象无效,当Intent进行反序列化时,使用的依旧为默认的ClassLoader对象,如果反序列化的类在默认的ClassLoader中不存在,则会出现找不到类的异常。5.0以上系统已经修复该bug。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值