Serialization trouble shooting

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Serialization trouble shooting

Influenza
Hello Everyone,

I'm currently working on a Plugin that simplifies evaluation of microbiological images. Therefor I planned to develop a serializable object, such that I can save and load my results in an easy way.
I understand that I can only use fields that are serializable as well, but somehow I still receive a NotSerializableException:

java.io.NotSerializableException: sun.java2d.SunGraphics2D
        at java.io.ObjectOutputStream.writeObject0(Unknown Source)
        at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
        at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
        at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
        at java.io.ObjectOutputStream.writeObject0(Unknown Source)
        at java.io.ObjectOutputStream.writeArray(Unknown Source)
        at java.io.ObjectOutputStream.writeObject0(Unknown Source)
        at java.io.ObjectOutputStream.access$300(Unknown Source)
        at java.io.ObjectOutputStream$PutFieldImpl.writeFields(Unknown Source)
        at java.io.ObjectOutputStream.writeFields(Unknown Source)
        at java.awt.Container.writeObject(Unknown Source)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
        at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
        at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
        at java.io.ObjectOutputStream.writeObject0(Unknown Source)
        at java.io.ObjectOutputStream.writeObject(Unknown Source)
        at java.awt.AWTEventMulticaster.save(Unknown Source)
        at java.awt.Component.writeObject(Unknown Source)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at java.io.ObjectStreamClass.invokeWriteObject(Unknown Source)
        at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
        at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
        at java.io.ObjectOutputStream.writeObject0(Unknown Source)
        at java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
        at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
        at java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
        at java.io.ObjectOutputStream.writeObject0(Unknown Source)
        at java.io.ObjectOutputStream.writeObject(Unknown Source)
        ...


Here is my source code:


import ...;

public class EvaSer implements Serializable{
       
        /**
         *
         */
        private static final long serialVersionUID = 3873721584911475388L;
        /**
         *
         */
        /**
         *
         */
        public int nSpec;
        public int nImages;
        public List<int[][]> types;
       
        public String evalName;
        public String[] specNames;
        public String[] typeNames;
       
        public List<String> imageNames; // For every Image one List element
        public List<Roi[][]> rois; // For every Image one Roi[nSpec][]
        public List<Roi> fixpoints; // Every Image one Fixpoint
        public List<File[]> files; // Original and Evaluated Files
       
        public Roi[] ovrls; // Control Ovrls from Flourescence as Roi[nSpec]
        public Color[] specieColors; // Chosen Colors for Species Color[nSpec]
        public File dir; // Directory of "Evaluated" ...
       
        public EvaSer(){
                this.evalName="new Evaluation "+System.currentTimeMillis();
                initLists();
                initTypeArrs();
        }
        private void initTypeArrs() {
                typeNames=new String[]{""};
               
        }
        public void initLists() {
                this.imageNames= new ArrayList<String>();
                this.rois= new ArrayList<Roi[][]>();
                this.fixpoints= new ArrayList<Roi>();
                this.files= new ArrayList<File[]>(); //files[0]= origin; files[1]= evaluated;
                this.types= new ArrayList<int[][]>();
        }
        public void save(Component parent)  {
                 System.out.println(this.nSpec);
                 System.out.println(this.nImages);
                 System.out.println(this.types.toString());
                 System.out.println(this.evalName);
                 System.out.println(this.specNames.toString());
                 System.out.println(this.typeNames.toString());
                 System.out.println(this.imageNames.toString());
                 System.out.println(this.rois.toString());
                 System.out.println(this.fixpoints.toString());
                 System.out.println(this.files.toString());
                 System.out.println(this.ovrls.toString());
                 System.out.println(this.specieColors.toString());
                 System.out.println(this.dir);
                String path;
                path=this.dir.toString();
                if(this.evalName==null){
                        this.evalName=RegularFunctions.getName(parent);
                }
                path=path+this.evalName+".eva";
               
                ObjectOutputStream oos = null;
                FileOutputStream fos = null;
                try {
                        fos = new FileOutputStream(path);
                        oos = new ObjectOutputStream(fos);

                        oos.writeObject(this);
                } catch (IOException e) {
                        e.printStackTrace();
                } finally {
                        if (oos != null)
                                try {
                                        oos.close();
                                } catch (IOException e) {
                                }
                        if (fos != null)
                                try {
                                        fos.close();
                                } catch (IOException e) {
                                }
                }



        }

       
        public EvaSer load(String path) {

                ObjectInputStream ois = null;
                FileInputStream fis = null;
                Object so= new Object();
               
                try {
                        fis = new FileInputStream(path);
                        ois = new ObjectInputStream(fis);
                        Object obj = ois.readObject();
                        if (obj instanceof EvaSer) {
                                so = (EvaSer) obj;
                        }
                } catch (IOException e) {
                        e.printStackTrace();
                } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                } finally {
                        if (ois != null)
                                try {
                                        ois.close();
                                } catch (IOException e) {
                                }
                        if (fis != null)
                                try {
                                        fis.close();
                                } catch (IOException e) {
                                }
                }
                return (EvaSer) so;
        }
       
       

}


Thanks to all of you who's time I'm stealing ;)
Reply | Threaded
Open this post in threaded view
|

Re: Serialization trouble shooting

dscho
Hi Influenza,

On Sun, 11 May 2014, Influenza wrote:

> I'm currently working on a Plugin that simplifies evaluation of
> microbiological images. Therefor I planned to develop a serializable object,
> such that I can save and load my results in an easy way.

Please study what Java serialization is, exactly. I fear that the way you
are using is outside its intended usage. In particular, you will find that
trying to serialize random objects whose classes define all kinds of
fields intended for display will cause all kinds of problems that you will
only understand if you know what serialization is about.

There is a good reason, for example, why ROIs in ImageJ are saved in a
custom format rather than using Java serialization.

The same applies, most likely, to your data: you want to be specific about
what to write to disk, and avoid using Java serialization (which backfired
rather nicely in your case, too ;-)).

Ciao,
Johannes

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: Serialization trouble shooting

ctrueden
Hi,

> Please study what Java serialization is, exactly. I fear that the way
> you are using is outside its intended usage. In particular, you will
> find that trying to serialize random objects whose classes define all
> kinds of fields intended for display will cause all kinds of problems
> that you will only understand if you know what serialization is about.

Perhaps the Externalizable interface would be a better fit here:
http://stackoverflow.com/q/817853

Externalization gives you more complete control over the process. It is
initially more work but much more robust long term.

Regards,
Curtis


On Mon, May 12, 2014 at 3:39 PM, Johannes Schindelin <
[hidden email]> wrote:

> Hi Influenza,
>
> On Sun, 11 May 2014, Influenza wrote:
>
> > I'm currently working on a Plugin that simplifies evaluation of
> > microbiological images. Therefor I planned to develop a serializable
> object,
> > such that I can save and load my results in an easy way.
>
> Please study what Java serialization is, exactly. I fear that the way you
> are using is outside its intended usage. In particular, you will find that
> trying to serialize random objects whose classes define all kinds of
> fields intended for display will cause all kinds of problems that you will
> only understand if you know what serialization is about.
>
> There is a good reason, for example, why ROIs in ImageJ are saved in a
> custom format rather than using Java serialization.
>
> The same applies, most likely, to your data: you want to be specific about
> what to write to disk, and avoid using Java serialization (which backfired
> rather nicely in your case, too ;-)).
>
> Ciao,
> Johannes
>
> --
> ImageJ mailing list: http://imagej.nih.gov/ij/list.html
>

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: Serialization trouble shooting

dscho
In reply to this post by dscho
Hi steve,

On Tue, 13 May 2014, Steven Görlich wrote:

> i really thought, I'd studied serialized objects well, but it seems that I
> was wrong. I spend attention on the fields being serializable as well....
> Curiously, it used to work until a certain point, with almost all the
> fields that are implemented by now.

Sorry, my comment was misleading: I am sure that you studied the details
of the Java serialization well. However, I think that there might be a
slight misconception what Java serialization is intended for.

It is distinctly *not* intended for storage. Java serialization is
substantially too fragile for that: the binary protocol depends on the
implementation details. For example, you simply cannot deserialize Java
objects with Android that were serialized with OpenJDK, because the specs
allow explicitly to override the binary protocol by implementing the
writeObject/readObject methods. When using a class path library that
implements those methods differently (or one of both implementations does
*not* implement them), you're out of luck. A good example is the TreeMap
class if you want to learn more.

What serialization *is* intended for is to be able to page out data e.g.
when RAM becomes scarce, and to be able to page things back in later, when
needed.

To that end, Java serialization defaults to serialize all fields
recursively, no matter whether that is proper or not (it is very easy to
see that an open file handle simply cannot serialized properly).

Your case hits one of these limitations: the Roi class has a reference to
the ImageCanvas which is a *GUI* element. As such, you probably never want
to serialize it because it is bound to an *actual window*. You simply
cannot deserialize such things robustly because the window might not even
exist!

BTW please do not be mislead by the fact that ij.gui.Roi is marked
Serializable, it is not well tested (the ImageCanvas field I mentioned
above clearly would need to be marked as "transient" for example) and it
distinctly does not work, unless you drive it in a very narrow manner.
Even apart from that, it is not intended for storage.

> You mentioned that Rois are saved in a custom way?

Such a question is really asked much better on the mailing list than in a
private mail (you really do not want to treat me as a commodity private
help desk, right?). It is your lucky day that I have enough time to
answer. In any case, to maximize the effect of my answer (you are
certainly not the only one who can benefit from my expertise), I Cc:ed the
mailing list.

When you call File>Save As>Selection..., the real work is done by the
ij.io.RoiEncoder class. You might want to read up on the documentation of
that class:

        http://jenkins.imagej.net/job/ImageJ1-javadoc/javadoc/ij/io/RoiEncoder.html

Ciao,
Johannes

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html