0

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

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

4

1 回答 1

2

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

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

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

于 2014-01-07T00:42:38.320 回答