java Android:将可序列化对象传递给 Activity 时出现 ClassNotFoundException

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6014806/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 13:58:15  来源:igfitidea点击:

Android: ClassNotFoundException when passing serializable object to Activity

javaandroidexception

提问by pandre

I have a few crash report logs from android market similar to this:

我有一些来自 android 市场的崩溃报告日志,类似于:

Exception class: java.lang.ClassNotFoundException

Source method: PathClassLoader.findClass()

java.lang.RuntimeException: Unable to start activity ComponentInfo{my.app.package/my.app.package.MyActivity}: java.lang.RuntimeException: Parcelable encounteredClassNotFoundException reading a Serializable object (name = my.app.package.a.ae)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2833)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2854)
at android.app.ActivityThread.access00(ActivityThread.java:136)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2179)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:143)
at android.app.ActivityThread.main(ActivityThread.java:5068)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.RuntimeException: Parcelable encounteredClassNotFoundException reading a Serializable object (name = my.app.package.a.ae)
at android.os.Parcel.readSerializable(Parcel.java:1951)
at android.os.Parcel.readValue(Parcel.java:1822)
at android.os.Parcel.readMapInternal(Parcel.java:2008)
at android.os.Bundle.unparcel(Bundle.java:208)
at android.os.Bundle.getBundle(Bundle.java:1078)
at android.app.Activity.onRestoreInstanceState(Activity.java:861)
at android.app.Activity.performRestoreInstanceState(Activity.java:835)
at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1135)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2811)
... 11 more
Caused by: java.lang.ClassNotFoundException: my.app.package.a.ae
at java.lang.Class.classForName(Native Method)
at java.lang.Class.forName(Class.java:235)
at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:2590)
at java.io.ObjectInputStream.readNewClassDesc(ObjectInputStream.java:1846)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:826)
at java.io.ObjectInputStream.readNewObject(ObjectInputStream.java:2066)
at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:929)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:2285)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:2240)
at android.os.Parcel.readSerializable(Parcel.java:1945)
... 19 more
Caused by: java.lang.NoClassDefFoundError: my.app.package.a.ae
... 29 more
Caused by: java.lang.ClassNotFoundException: my.app.package.a.ae in loader dalvik.system.PathClassLoader[.]
at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:243)
at java.lang.ClassLoader.loadClass(ClassLoader.java:573)
at java.lang.ClassLoader.loadClass(ClassLoader.java:532)
... 29 more 

Please note that I am using proguard -> that's why the "missing" class name is "a.ae".
Actually, "a.ae" is the name proguard gave to the class "MyObject", which is shown below.

请注意,我正在使用 proguard -> 这就是为什么“缺少”的类名是“a.ae”。
实际上,“a.ae”是 proguard 给“MyObject”类起的名字,如下所示。

Any ideia on why this happens?

关于为什么会发生这种情况的任何想法?

I don't think it has to do with proguard, because if it was a problem caused by proguard class renaming, it should happen all times and I would be able to reproduce this issue myself.

我认为这与 proguard 无关,因为如果它是由 proguard 类重命名引起的问题,它应该一直发生,我将能够自己重现这个问题。

Does it have to do with passing a serializable object to MyActivity?
In MyActivity I have

它与将可序列化对象传递给 MyActivity 有关系吗?
在 MyActivity 我有

public void onCreate(Bundle savedInstanceState) {  
     myObj = (MyObject) getIntent().getSerializableExtra("nameOfMyObject");  
//here I am trying to read myObj's properties and app seems to crash here  

}

}



MyObject is just an entity with several types of class members, ex:
public class MyObject implements Serializable {

MyObject 只是一个具有多种类成员类型的实体,例如:
public class MyObject 实现 Serializable {

    /** Generated serialVersionUID */
    static final long serialVersionUID = -267025879233327409L;

    static final String CONSTANT1 = "xpto";

    LinkedHashMap<String, Object> components;

    ArrayList<String> prop1;

    (...)
}

I am starting MyActivity with:

我开始 MyActivity:

MyObject obj = new MyObj(stuff);
Intent intent;
intent = new Intent(CurrentActivity.this, MyActivity.class);
intent.putExtra("nameOfMyObject",  obj);
CurrentActivity.this.startActivity(intent);

Do you think it has to do with the way the object is being passed (as a serializable extra)?
In the case that I don't find any other solution I think I will "serialize" the object myself to a String and then pass the String extra. What do you think about this?

您认为这与传递对象的方式有关吗(作为可序列化的额外内容)?
在我找不到任何其他解决方案的情况下,我想我会将对象自己“序列化”为一个字符串,然后传递额外的字符串。你怎么看待这件事?

EDIT: I have tried to reproduce this issue, without success, in the emulator and in the following devices:

编辑:我试图在模拟器和以下设备中重现这个问题,但没有成功:

-Motorola Milestone 2 Android 2.2
-Samsung Galaxy Tab Android 2.2
-Vodafone 845 Android 2.1
-HTC Tatoo Android 1.6
-Xperia X10 Android 1.6
-Nexus One Android 2.2
-Google G1 Android 1.5

-Motorola Milestone 2 Android 2.2
-Samsung Galaxy Tab Android 2.2 -Vodafone
845 Android 2.1
-HTC Tatoo Android 1.6
-Xperia X10 Android 1.6
-Nexus One Android 2.2
-Google G1 Android 1.5

Any new ideas?

有什么新想法吗?

回答by pandre

Finally reached a conclusion on this issue: it was being caused by Proguard, or more specifically, because I didn't have a propper Proguard configuration.

最终对这个问题得出了一个结论:它是由 Proguard 引起的,或者更具体地说,因为我没有正确的 Proguard 配置。

It turns out Proguard was changing my Serializable's classes names, which makes Class.forName(className)fail.

事实证明 Proguard 正在更改 mySerializable的类名称,这Class.forName(className)导致失败。

I had to reconfigure my proguard.cfgfile adding the following lines:

我不得不重新配置我的proguard.cfg文件,添加以下几行:

-keep class * implements java.io.Serializable

-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    !private <fields>;
    !private <methods>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

回答by joey

You should look into implementing Parcelable. These two links should get you started: http://developer.android.com/reference/android/os/Parcel.htmlhttp://developer.android.com/reference/android/os/Parcelable.html

您应该考虑实施Parcelable. 这两个链接应该让你开始: http://developer.android.com/reference/android/os/Parcel.htmlhttp://developer.android.com/reference/android/os/Parcelable.html

回答by CaseyB

LinkedHashMapdoesn't implement Serializableso this may be causing the error. Try either implementing a small test to serialize this class or try removing the LinkedHashMapand see if the error persists.

LinkedHashMap没有实现Serializable所以这可能会导致错误。尝试实现一个小测试来序列化这个类,或者尝试删除LinkedHashMap并查看错误是否仍然存在。