AIDL当Parcelable序列化的数据类通信时报“Class not found when unmarshalling“找不到该类时的解决方案
1. 报错栈 :cusText这个类找不到
2 16:01:29.796 1044 5718 E Parcel : Class not found when unmarshalling: com.cus.sdk.cusText
08-02 16:01:29.796 1044 5718 E Parcel : java.lang.ClassNotFoundException: com.cus.sdk.cusText
08-02 16:01:29.796 1044 5718 E Parcel : at java.lang.Class.classForName(Native Method)
08-02 16:01:29.796 1044 5718 E Parcel : at java.lang.Class.forName(Class.java:454)
2. 解决方案
Message m = getMessage();
Bundle data = m.getData();if (data != null) {// 关键:设置与xxx相同的类加载器// 确保使用类本身的类加载器,而不是当前上下文的data.setClassLoader(cusText.class.getClassLoader());
}
3. 解决原理:
这是因为类加载器(ClassLoader)决定了Java虚拟机如何查找和加载类,在跨进程/组件通信场景中,类加载器的不匹配是导致ClassNotFoundException
的常见原因。
为什么需要手动设置类加载器?
Android应用中存在多个类加载器,不同的类加载器负责加载不同来源的类(如系统类、应用自身类、动态加载的插件类等)。默认情况下:
Bundle
在反序列化时会使用当前上下文的类加载器(通常是当前Activity/Service的类加载器)。- 如果
cusText
类是由另一个类加载器加载的(例如:该类来自独立的库模块
、跨进程传递的类
、或动态加载的dex
),当前上下文的类加载器可能“不认识”这个类,就会报cusText
找不到。
为什么cusText.class.getClassLoader()
能解决问题?
cusText.class.getClassLoader()
获取的是实际加载cusText
类的类加载器。通过data.setClassLoader(...)
强制Bundle
使用这个类加载器来反序列化:
- 确保了“加载类的加载器”和“反序列化时的类加载器”是同一个,系统能正确找到类的定义。
- 避免了“当前上下文类加载器”找不到该类的问题(比如跨进程场景中,接收方和发送方的类加载器不同)。
举个形象的例子:
假设:
cusText
类是由“库加载器(jar包)”加载的(来自一个独立的Android Library)。- 当前Activity的类加载器是“应用加载器”,它只认识应用自身的类,不认识“库加载器”加载的类。
此时:
- 不设置类加载器:
Bundle
用“应用加载器”找cusText
,找不到→报错。 - 设置
cusText
的类加载器:Bundle
用“库加载器”找,顺利找到→反序列化成功。
这就是为什么手动指定类加载器后,ClassNotFoundException
会被解决——本质是让系统用“正确的钥匙(类加载器)”打开“正确的门(找到类)”。