【问题标题】:Java Serialization Produces NotSerializableException (Unknown Reason)Java序列化产生NotSerializableException(未知原因)
【发布时间】:2014-01-07 00:36:16
【问题描述】:

我正在用 Java 编写一个应用程序,它需要做的部分工作是序列化一些对象,以便以后可以导入它们。当我编写序列化代码时,它无法正常工作。经过多次修改,我相信我已经将其缩小到只有几个属性,并包含了触发此 SSCEE 错误的最少代码:

import java.io.*;
import java.util.prefs.*;
import java.util.*;
import javax.swing.*;
import java.awt.event.*;

//main class
public class SerializeFail extends JFrame implements Serializable, ActionListener {
    JMenuBar bar = new JMenuBar();
    JMenu file = new JMenu("File");
    JMenuItem item = new JMenuItem("Click to Fail");

    HashMap<String, Preferences> prefs = new HashMap<String, Preferences>();    
    public SerializeFail () {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        file.add(item);
        bar.add(file);
        item.addActionListener(this);
        prefs.put("root", Preferences.userRoot().node(this.getClass().getName()));
        setJMenuBar(bar);
        pack();
        setVisible(true);
    }

    //triggers the failure
    public void actionPerformed (ActionEvent e) {
        TestObject gr = new TestObject();
        try {
            FileOutputStream fileOutput = new FileOutputStream("testing.gradecalc");
            ObjectOutputStream objectOutput = new ObjectOutputStream(fileOutput);
            objectOutput.writeObject(gr);
            fileOutput.close();
            System.out.println("serialized");
        } catch (FileNotFoundException fileNotFound) {
            System.out.println("The file was not found");
            fileNotFound.printStackTrace();
        } catch (IOException io) {
            System.out.println("There was some type of io exception");
            System.out.println("Stack Trace");
            io.printStackTrace();
            System.out.println("Message Trace");
            io.getMessage();
            System.out.println("Cause Trace");
            io.getCause();
        }
    }


    public static void main(String[] args) {
        new SerializeFail();
    }

    class TestObject implements Serializable {
        int attribute;
        public TestObject () {
            attribute = 47;
        }
    }
}

我得到的堆栈跟踪错误是:

There was some type of io exception
Stack Trace
java.io.NotSerializableException: com.apple.laf.AquaMenuBarBorder
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1181)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1541)
    at java.io.ObjectOutputStream.defaultWriteObject(ObjectOutputStream.java:439)
    at javax.swing.JComponent.writeObject(JComponent.java:5525)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1493)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1429)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1175)
    at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1375)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1171)
    at java.io.ObjectOutputStream.access$300(ObjectOutputStream.java:162)
    at java.io.ObjectOutputStream$PutFieldImpl.writeFields(ObjectOutputStream.java:1700)
    at java.io.ObjectOutputStream.writeFields(ObjectOutputStream.java:479)
    at java.awt.Container.writeObject(Container.java:3681)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1493)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1429)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1175)
    at java.io.ObjectOutputStream.writeArray(ObjectOutputStream.java:1375)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1171)
    at java.io.ObjectOutputStream.access$300(ObjectOutputStream.java:162)
    at java.io.ObjectOutputStream$PutFieldImpl.writeFields(ObjectOutputStream.java:1700)
    at java.io.ObjectOutputStream.writeFields(ObjectOutputStream.java:479)
    at java.awt.Container.writeObject(Container.java:3681)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1493)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1429)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1175)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1541)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1506)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1429)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1175)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)
    at java.awt.AWTEventMulticaster.save(AWTEventMulticaster.java:946)
    at java.awt.Component.writeObject(Component.java:8645)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
Message Trace
Cause Trace
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1493)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1429)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1175)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1541)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1506)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1429)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1175)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)
    at SerializeFail.actionPerformed(SerializeFail.java:34)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.AbstractButton.doClick(AbstractButton.java:376)
    at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:833)
    at com.apple.laf.AquaMenuItemUI.doClick(AquaMenuItemUI.java:157)
    at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:877)
    at java.awt.Component.processMouseEvent(Component.java:6505)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
    at java.awt.Component.processEvent(Component.java:6270)
    at java.awt.Container.processEvent(Container.java:2229)
    at java.awt.Component.dispatchEventImpl(Component.java:4861)
    at java.awt.Container.dispatchEventImpl(Container.java:2287)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
    at java.awt.Container.dispatchEventImpl(Container.java:2273)
    at java.awt.Window.dispatchEventImpl(Window.java:2719)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:735)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:694)
    at java.awt.EventQueue$3.run(EventQueue.java:692)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:708)
    at java.awt.EventQueue$4.run(EventQueue.java:706)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:705)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

有趣的是,如果消除了与图形相关的对象,那么 SSCEE 是:

import java.io.*;
import java.util.prefs.*;
import java.util.*;
import javax.swing.*;
import java.awt.event.*;

//main class
public class SerializeFail implements Serializable {
    HashMap<String, Preferences> prefs = new HashMap<String, Preferences>();    
    public SerializeFail () {
        prefs.put("root", Preferences.userRoot().node(this.getClass().getName()));
        TestObject gr = new TestObject();
        try {
            FileOutputStream fileOutput = new FileOutputStream("testing.gradecalc");
            ObjectOutputStream objectOutput = new ObjectOutputStream(fileOutput);
            objectOutput.writeObject(gr);
            fileOutput.close();
            System.out.println("serialized");
        } catch (FileNotFoundException fileNotFound) {
            System.out.println("The file was not found");
            fileNotFound.printStackTrace();
        } catch (IOException io) {
            System.out.println("There was some type of io exception");
            System.out.println("Stack Trace");
            io.printStackTrace();
            System.out.println("Message Trace");
            io.getMessage();
            System.out.println("Cause Trace");
            io.getCause();
        }
    }


    public static void main(String[] args) {
        new SerializeFail();
    }

    class TestObject implements Serializable {
        int attribute;
        public TestObject () {
            attribute = 47;
        }
    }
}

那么输出(包含异常的堆栈跟踪)是:

There was some type of io exception
Stack Tracejava.io.NotSerializableException: java.util.prefs.MacOSXPreferences
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1181)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)
    at java.util.HashMap.writeObject(HashMap.java:1100)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1493)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1429)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1175)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1541)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1506)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1429)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1175)
    at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1541)
    at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1506)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1429)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1175)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)
    at SerializeFail.<init>(SerializeFail.java:16)
    at SerializeFail.main(SerializeFail.java:35)
Message Trace
Cause Trace

我环顾四周并研究了序列化,但无济于事。有人可以这样做,以便 TestObject 的实例在包含图形相关组件(第一个 SSCEE)的情况下无误地序列化,因为这是主应用程序所具有的(或至少为我指明了正确的方向)?

谢谢。如果还有什么我可以提供的可以提供帮助的,请尽管询问。

【问题讨论】:

  • 你真的需要序列化“图形相关的对象”吗?
  • @milkplusvellocet - 不,但即使我声明它们是瞬态的,错误仍然存​​在
  • 除非有令人信服的理由不这样做,否则我会更改代码,使 TestObject 成为顶级类
  • 这个答案,结合@chrylis 的建议就可以了。谢谢大家

标签: java serialization notserializableexception


【解决方案1】:

所有非静态字段都必须是 transient 或传递性 Serializable 才能使默认序列化程序正常工作。在您的情况下,您直接声明的字段引用的 Apple 外观和 MacOSXPreferences 不可序列化。

奇怪的是,尽管 Swing 组件都实现了Serializable,但实际的运行时实现却没有,而制作 Swing 的东西Serializable 被广泛认为是一个错误。相反,您需要将状态(模型)与 UI(视图/控制器)分开封装。仅序列化模型对象并让您的客户端代码重建 UI,然后从保存的模型中填充它。

同样,Preferences 不是Serializable,因此运行时不能为其使用默认序列化。您如何处理序列化首选项取决于您要执行的操作;从您的示例中不清楚。

【讨论】:

  • 请原谅我的无知:那么我应该在代码中进行哪些更改以实现您的建议(我应该声明哪些字段等)?我不是在尝试序列化首选项 - 我正在尝试序列化一个在具有首选项节点的类的内部类中定义的对象,并且首选项因此被序列化。我根本对序列化首选项(或图形)不感兴趣——只是 TestObject 实例。
  • 使用状态对象(例如,CustomerFormModel),其字段只是 UI 显示/操作的纯数据,并仅序列化该对象。然后,您的加载/保存代码将此对象附加到客户表单的 JFrame 子类。 UI 组件的创建与绑定到它们的业务对象完全分开。
  • 'Transiently Serializable' 充其量是自相矛盾的。我已经更正了。
  • @EJP 我的意思是暂时的,而不是暂时的。 Thinko,我正在重新编辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-09
  • 2014-09-09
  • 2022-06-18
  • 1970-01-01
  • 2018-03-18
  • 2013-04-09
  • 1970-01-01
相关资源
最近更新 更多