Java 序列化产生 NotSerializedException(原因未知)

标签 java serialization notserializableexception

我正在用 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),因为这是主应用程序所拥有的(或者至少为我指明了正确的方向)?

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

最佳答案

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

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

同样,Preferences 不是Serialized,因此运行时无法为其使用默认序列化。如何处理序列化首选项取决于您想要做什么;从你的例子中还不清楚。

关于Java 序列化产生 NotSerializedException(原因未知),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20961956/

相关文章:

java - Selenium Serenity 屏幕截图和电影延迟并挂起执行

java - 如何使选择时区更加人性化?

java - 这个 docker run 命令有什么作用?

c++ - 如何将哈希表存储在文件中?

java - 在另一个类中使用 DefaultComboBoxModel 时出现 NotSerializedException

java - 为什么 writeObject 抛出 java.io.NotSerializedException 以及如何修复它?

java - 如何在 Maven 中隐藏编译的间接依赖?

sqlite - 无法序列化自定义对象activeandroid

javascript - 页面刷新后保存表单状态

java - 如何修复 'NotSerializableException: java.time.format.DateTimeFormatter' 错误