2014-01-07 6 views
0

Я пишу приложение в Java, и часть того, что ему нужно сделать, это сериализовать некоторые объекты, чтобы их можно было импортировать позже. Когда я написал код сериализации, он работал неправильно. После долгих мастерить, я считаю, что я сузили его только несколько атрибутов, и включал в себя минимально возможный код, чтобы вызвать ошибку в этом SSCEE:Java Serialization Produces 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 для работы сериализатора по умолчанию. В вашем случае Apple look-and-feel и MacOSXPreferences, на которые ссылаются поля, которые вы декларируете напрямую, не являются сериализуемыми.

Как ни странно, несмотря на то, что компоненты Swing все реализуют Serializable, фактических реализаций исполнения нет, и создание материалов Swing Serializable считается распространенным явлением. Вместо этого вам нужно инкапсулировать состояние (модель) отдельно от пользовательского интерфейса (view/controller). Сериализуйте только объект модели, и ваш клиентский код перестраивает пользовательский интерфейс, а затем заполняет его из сохраненной модели.

Аналогичным образом Preferences не является Serializable, поэтому среда выполнения не может использовать сериализацию по умолчанию для нее. Как вы справляетесь с сериализацией предпочтений, зависит от того, что вы пытаетесь сделать; это не ясно из вашего примера.

+0

прошу простить мое невежество: так что я должен изменить в коде для реализации вашего предложения (какие поля я должен объявить временными и т. Д.)? Я не пытаюсь сериализовать Preferences - я пытаюсь сериализовать объект, который определяется во внутреннем классе класса, у которого есть узел предпочтений, и в результате получается сериализация. Я не заинтересован в сериализации предпочтений (или графики) вообще - просто экземпляр TestObject. – cryptopi

+0

Используйте объект состояния (например, 'CustomerFormModel'), поля которого представляют собой только простые данные, которые пользовательский интерфейс отображает/обрабатывает, и сериализуйте только этот объект. Затем ваш код загрузки/сохранения добавит этот объект в подкласс JFrame для формы клиента. Создание компонентов пользовательского интерфейса полностью отделено от бизнес-объекта, связанного с ними. – chrylis

+0

Все работает сейчас, спасибо за ваше время – cryptopi