2014-01-07 22 views
0

我正在用Java編寫應用程序,它需要做的一部分是序列化一些對象,以便稍後可以導入它們。當我編寫序列化代碼時,它無法正常工作。很多修修補補之後,我相信我已經把範圍縮小到只有幾個屬性,其中包括可能的最小碼觸發錯誤在此SSCEE:Java序列化產生NotSerializableException(未知原因)

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)的序列化,因爲這是主應用程序所具有的(或者至少將我指向正確的方向)?

謝謝。如果還有什麼我可以提供的幫助,請提問。

+1

您是否確實需要連載「與圖形相關的對象」? – darrengorman

+0

@milkplusvellocet - 沒有,但即使我宣佈他們短暫的,錯誤仍然存​​在 – cryptopi

+0

除非有令人信服的理由不這樣做,我會改變代碼,以便TestObject的是一個頂級類 – darrengorman

回答

2

所有的非靜態字段必須是transient或傳遞Serializable默認序列化程序才能正常工作。在你的情況下,蘋果的外觀和MacOSXPreferences,這是你直接聲明的字段引用,不可序列化。

奇怪的是,即使Swing組件都實現了Serializable,實際的運行時實現卻沒有,並且使Swing的東西Serializable被廣泛認爲是錯誤的。相反,您需要將狀態(模型)與UI(視圖/控制器)分開封裝。只序列化模型對象並讓客戶端代碼重新構建UI,然後從保存的模型中填充它。

同樣,Preferences不是Serializable,所以運行時不能使用默認序列化。你如何處理序列化偏好取決於你想要做什麼;從你的例子中不清楚。

+0

請原諒我的無知:那麼我應該改變代碼來實現你的建議(哪些字段應該聲明爲瞬態等)?我不想序列化首選項 - 我試圖序列化一個對象,該對象在類的內部類中定義,該類的首選項節點和首選項被序列化爲結果。我根本沒有興趣序列化首選項(或圖形) - 只是TestObject實例。 – cryptopi

+0

使用一個狀態對象(例如'CustomerFormModel'),這些對象的字段只是UI正在顯示/操作的普通數據,並且僅序列化該對象。然後,您的加載/保存代碼會將此對象附加到客戶表單的「JFrame」子類。 UI組件的創建與綁定到它們的業務對象完全分開。 – chrylis

+0

現在一切正常,感謝您的時間 – cryptopi

相關問題