Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / December 2005

Tip: Looking for answers? Try searching our database.

Question re serializable

Thread view: 
Rhino - 11 Dec 2005 19:00 GMT
I'm trying to resolve some compiler warnings that I've simply ignored for
quite a long time. Many of them are pretty obvious but I've come across a
few that aren't clear to me at all. One of these involves Serializable.

I have several occurrences of warnings of this type: "The serializable class
Foo does not declare a final serialVersionUID field of type long."

I've got dozens of messages of this kind and the classes that get the
warning message extend a variety of different classes, including JFrame,
JDialog, JApplet, but also classes that have nothing to do with GUIs, like
some homegrown Exception classes.

Can someone explain what this message is about: what it means, why I get it,
and how I can prevent it?

I've read the article about Serializable in the API but most of it goes
right over my head. I'm particularly foggy on which value I'm supposed to
use in the serialVersionUID constant if I choose to code one, which is
apparently highly-recommended.

I'm also unclear on what Bad Things are going to happen if I don't change my
code to prevent this warning.

I'd appreciate it if anyone can clarify this for me.
Signature

Rhino

Thomas Hawtin - 11 Dec 2005 20:12 GMT
> I'm trying to resolve some compiler warnings that I've simply ignored for
> quite a long time. Many of them are pretty obvious but I've come across a
[quoted text clipped - 7 lines]
> JDialog, JApplet, but also classes that have nothing to do with GUIs, like
> some homegrown Exception classes.

You can get rid of most of these simply by not extending these mostly
concrete classes (okay, difficult for JApplet, but you can limit the
number of subclasses, Throwable is quite useful too...).

> Can someone explain what this message is about: what it means, why I get it,
> and how I can prevent it?

When an object is serialised, the class information includes this UID.
If you choose not to provide one, then a value is derived using some
function applied to the public attributes of the class. The message just
mean that that function will need to be applied to you class if an
instance is serialised. You can supply one by adding a field:

   private static final long serialVersionUID = ...some long number...L;

> I've read the article about Serializable in the API but most of it goes
> right over my head. I'm particularly foggy on which value I'm supposed to
> use in the serialVersionUID constant if I choose to code one, which is
> apparently highly-recommended.

You can choose anything. Preferably it should not duplicate the number
of another class. One way of creating it is to run serialver on the
class, and that gives the number which would be assigned anyway. If the
way the class is serialised changes, then so should the serialVersionUID.

> I'm also unclear on what Bad Things are going to happen if I don't change my
> code to prevent this warning.

The Bad Thing is that a change in public attributes of a class may
change the generated UID, and therefore prevent new code loading older
serialised data, or vice versa.

The Bad Thing that may happen if you do supply one is that you really do
change the serialised format, but not the UID. Hence a complete mess
when it comes to deserialisation.

It is a pain if you want a custom exception, say, and have no intention
of going anywhere near serialization. I guess you could get a revision
control system to embed a version number in the constant.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Rhino - 11 Dec 2005 20:35 GMT
>> I'm trying to resolve some compiler warnings that I've simply ignored for
>> quite a long time. Many of them are pretty obvious but I've come across a
[quoted text clipped - 11 lines]
> concrete classes (okay, difficult for JApplet, but you can limit the
> number of subclasses, Throwable is quite useful too...).

Sorry, I don't follow you. If I want to have the benefit of all the existing
code with JFrame and its parents, how do I get them without subclassing
JFrame?

Also, are you suggesting that in cases where I extend a given Exception, I
extend Throwable instead?

>> Can someone explain what this message is about: what it means, why I get
>> it, and how I can prevent it?
[quoted text clipped - 6 lines]
>
>    private static final long serialVersionUID = ...some long number...L;

Why is it better for me to specify my own serialVersionUID than let the
function be applied for me? Obviously, I get a bit more control but I'm not
sure what that buys me in this case?

>> I've read the article about Serializable in the API but most of it goes
>> right over my head. I'm particularly foggy on which value I'm supposed to
[quoted text clipped - 5 lines]
> and that gives the number which would be assigned anyway. If the way the
> class is serialised changes, then so should the serialVersionUID.

What is 'serialver' and how/when do I run it, i.e. is it something I need to
do when I compose the code?

What do you mean by "if the way the class is serialized changes"? What are
the different ways a class can be serialized? Why would the way it is
serialized at one point in time change in the future?

>> I'm also unclear on what Bad Things are going to happen if I don't change
>> my code to prevent this warning.
>
> The Bad Thing is that a change in public attributes of a class may change
> the generated UID, and therefore prevent new code loading older serialised
> data, or vice versa.

"Older serialized data"? Could you please explain this scenario to me? I
would have thought that I was always going to be reading _current_ data, not
"older" data. Older data suggests non-current data, something that was
stored in a file or database perhaps, but has become superseded, like a
former salary.

> The Bad Thing that may happen if you do supply one is that you really do
> change the serialised format, but not the UID. Hence a complete mess when
> it comes to deserialisation.

How would I change the serialised format? Is that something I'd do
consciously? If so, why would I do it? Or does it have the potential to
change on me without any conscious intent on my part, say due to a compiler
change?

> It is a pain if you want a custom exception, say, and have no intention of
> going anywhere near serialization. I guess you could get a revision
> control system to embed a version number in the constant.

As you can probably see from my questions, I'm really quite lost. Perhaps I
need to get a few concepts explained to me before I will understand this
discussion. Can you recommend a place to get those concepts, whatever they
are?

I'm afraid my OO theory is not particularly strong and that may be getting
in the way here....

Rhino
Thomas Hawtin - 11 Dec 2005 21:49 GMT
> Sorry, I don't follow you. If I want to have the benefit of all the existing
> code with JFrame and its parents, how do I get them without subclassing
> JFrame?

    JFrame frame = new JFrame();

Sorted.

> Also, are you suggesting that in cases where I extend a given Exception, I
> extend Throwable instead?

No! I used Throwable, as Throwable is the base class of Exception that
implements Serializable.

> Why is it better for me to specify my own serialVersionUID than let the
> function be applied for me? Obviously, I get a bit more control but I'm not
> sure what that buys me in this case?

Just in case the class changes slightly, say an extra method. Then the
UID changes and serialisation interoperability fails.

> What is 'serialver' and how/when do I run it, i.e. is it something I need to
> do when I compose the code?

It's a program in the JDK.

> What do you mean by "if the way the class is serialized changes"? What are
> the different ways a class can be serialized? Why would the way it is
> serialized at one point in time change in the future?

A class can store serialised data as it likes. For instance, you can
store a huge number as an array of bytes. Then you might want to change
to using an array of int. Without code to detect which is which,
deserialising the wrong form will fail. In general you might just get
corrupt data and no exception.

> "Older serialized data"? Could you please explain this scenario to me? I
> would have thought that I was always going to be reading _current_ data, not
> "older" data. Older data suggests non-current data, something that was
> stored in a file or database perhaps, but has become superseded, like a
> former salary.

Data serialised by older classes.

> How would I change the serialised format? Is that something I'd do
> consciously? If so, why would I do it? Or does it have the potential to
> change on me without any conscious intent on my part, say due to a compiler
> change?

Just changing the name of a field would do it.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Rhino - 12 Dec 2005 00:03 GMT
>> Sorry, I don't follow you. If I want to have the benefit of all the
>> existing code with JFrame and its parents, how do I get them without
[quoted text clipped - 46 lines]
>
> Just changing the name of a field would do it.

I really appreciate your attempt to clarify this issue for me but I'm just
not following you. I'm sure it's my fault, not yours.

I read the article Roedy cited but I still don't see the big picture with
regards to serialization. Maybe Roedy can clear this up for me.... (See my
followup to Roedy if you like.)

Rhino
Mike Schilling - 12 Dec 2005 00:48 GMT
> When an object is serialised, the class information includes this UID. If
> you choose not to provide one, then a value is derived using some function
[quoted text clipped - 3 lines]
>
>    private static final long serialVersionUID = ...some long number...L;

> You can choose anything. Preferably it should not duplicate the number of
> another class.

Why does this matter?  So far as I know, there's no chance that a class's
serialVersionUID will be used for a class with a different fully-qualified
name.  In fact, when I use serializeable classes (which is rarely) I set
serialVersionUID to 1 originally, and increment it if I ever break
compatibility.
Thomas Hawtin - 12 Dec 2005 02:44 GMT
>>You can choose anything. Preferably it should not duplicate the number of
>>another class.
[quoted text clipped - 4 lines]
> serialVersionUID to 1 originally, and increment it if I ever break
> compatibility.

I believe it is permitted for the deserialised instance to have a
different class name to the one in the stream. The SUIDs must match (and
if it is a mistake then they really shouldn't).

Different serialVersionUIDs may be able to detect renaming issues better.

An implementation may get better performance looking up on SUID before
class name, although clearly not with classes under your scheme.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Mike Schilling - 12 Dec 2005 02:53 GMT
>>>You can choose anything. Preferably it should not duplicate the number of
>>>another class.
[quoted text clipped - 8 lines]
> different class name to the one in the stream. The SUIDs must match (and
> if it is a mistake then they really shouldn't).

I'd never heard of this, and can't find it in
http://java.sun.com/j2se/1.5.0/docs/guide/serialization/spec/serialTOC.html.
Can you point to a description of it?
Thomas Hawtin - 12 Dec 2005 03:47 GMT
>>I believe it is permitted for the deserialised instance to have a
>>different class name to the one in the stream. The SUIDs must match (and
[quoted text clipped - 3 lines]
> http://java.sun.com/j2se/1.5.0/docs/guide/serialization/spec/serialTOC.html.
> Can you point to a description of it?

http://download.java.net/jdk6/docs/api/java/io/ObjectInputStream.html#resolveCla
ss(java.io.ObjectStreamClass
)

You might consider subclassing ObjectInputStream cheating.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Mike Schilling - 12 Dec 2005 05:10 GMT
>>>I believe it is permitted for the deserialised instance to have a
>>>different class name to the one in the stream. The SUIDs must match (and
[quoted text clipped - 7 lines]
>
> You might consider subclassing ObjectInputStream cheating.

I consider it the sign of a far braver man than I :-)

Though the javadoc here says "Load the local class equivalent of the
specified stream class description. Subclasses may implement this method to
allow classes to be fetched from an alternate source."  It also calls this
the obverse of ObjectOutputStream.annotateClass(), which says

Subclasses may implement this method to allow class data to be stored in the
stream. By default this method does nothing. The corresponding method in
ObjectInputStream is resolveClass. This method is called exactly once for
each unique class in the stream. The class name and signature will have
already been written to the stream. This method may make free use of the
ObjectOutputStream to save any representation of the class it deems suitable
(for example, the bytes of the class file). The resolveClass method in the
corresponding subclass of ObjectInputStream must read and use any data or
objects written by annotateClass.

So my guess is that this is intended to find the correct version of the
named class rather than to substitute a class of a different name.
Roedy Green - 11 Dec 2005 20:35 GMT
On Sun, 11 Dec 2005 14:00:53 -0500, "Rhino"
<no.offline.contact.please@nospam.com> wrote, quoted or indirectly
quoted someone who said :

> "The serializable class
>Foo does not declare a final serialVersionUID field of type long."

see http://mindprod.com/jgloss/serialization.html#SERIALVERSIONUID

Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Rhino - 11 Dec 2005 23:58 GMT
> On Sun, 11 Dec 2005 14:00:53 -0500, "Rhino"
> <no.offline.contact.please@nospam.com> wrote, quoted or indirectly
[quoted text clipped - 4 lines]
>
> see http://mindprod.com/jgloss/serialization.html#SERIALVERSIONUID

Okay, I read through this article and got somewhat more of a grasp on how
serialization works.

I'm still not clear why I need to get into all of this rigamarole though.

I've got many classes that are based on serializable classes like JFrame but
I don't have any desire whatever to send my classes over sockets or write
them to the file system. Obviously, the source code and compile class will
need to be on the file system but I don't see why my runtime instances of
these classes will need to be sent over sockets or written to the file
system. So what's my best strategy for dealing with serializability? I'm
strongly tempted to disable the compiler warnings for this kind of warning
but I suppose I'd still rather modify the code so that the warnings go away
altogether. What is my best plan for accomplishing that?

Rhino
Mike Schilling - 12 Dec 2005 01:16 GMT
>> On Sun, 11 Dec 2005 14:00:53 -0500, "Rhino"
>> <no.offline.contact.please@nospam.com> wrote, quoted or indirectly
[quoted text clipped - 20 lines]
> that the warnings go away altogether. What is my best plan for
> accomplishing that?

Since serializability is indicated by implementing Serializeable, your
classes are serializeable whether you like it or not, hence the warning.  In
your shoes, I would probably have the following two conventions for all such
classes:

1. Set serialVersionUID  to -1.
2. Implement private void writeObject(ObjectOutputStream out) and private
void readObject(ObjectInputStream in) to throw exceptions e.g. "class not
serializeable".

The second comes from my dislike of leaving booby-traps for the unwary.
Since you're not designing your classes to be serializeable, make sure no
one tries to use them that way.
Roedy Green - 12 Dec 2005 01:45 GMT
On Sun, 11 Dec 2005 18:58:02 -0500, "Rhino"
<no.offline.contact.please@nospam.com> wrote, quoted or indirectly
quoted someone who said :

>I've got many classes that are based on serializable classes like JFrame but
>I don't have any desire whatever to send my classes over sockets or write
>them to the file system.

Why did you make them serializable then? That's what the
Serialializable interface is for.  If you are extending Serializable
classes, the author wanted those classes to be Serializable so that
could be used to save state or with RMI.

Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Mike Schilling - 12 Dec 2005 02:03 GMT
> On Sun, 11 Dec 2005 18:58:02 -0500, "Rhino"
> <no.offline.contact.please@nospam.com> wrote, quoted or indirectly
[quoted text clipped - 6 lines]
>
> Why did you make them serializable then?

If you extend a Serializeable class you have no choice.
Thomas Hawtin - 12 Dec 2005 02:50 GMT
> On Sun, 11 Dec 2005 18:58:02 -0500, "Rhino"
> <no.offline.contact.please@nospam.com> wrote, quoted or indirectly
[quoted text clipped - 8 lines]
> classes, the author wanted those classes to be Serializable so that
> could be used to save state or with RMI.

java.awt.Component implements java.io.Serializable...

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

J. Verdrengh - 12 Dec 2005 12:40 GMT
> Can someone explain what this message is about: what it means, why I get
> it, and how I can prevent it?

An instance of a serializable class can be serialized: this means that its
state can be saved to a stream.
When you save an instance of a serializable class Test, you can reload the
instance into memory at a later point in time. The field serialVersionUID is
used to verify whether the class Test hasn't changed since you saved the
instance.

You can generate a number for a .class file: try
"$JAVA$/bin/serialver.exe -show" where $JAVA$ is your java-path.

Then put the generated value in the corresponding .java file like this:
private final long serialVersionUID = generatedValue;

Whenever you change some instance fields of the class, the generated value
will change (and you are supposed to adapt the value of serialVersionUID).
This way, when you try to load an old stream into an instance of the new
(adapted) class, an Exception will be thrown because serialVersionUID of the
saved stream doesn't match serialVersionUID of the adapted class.

Question to the community: why doesn't Java automatically save some
hashvalue when streaming an instance of a serializable class instead of
relying on a 'manual' value like serialVersionUID?
Mike Schilling - 12 Dec 2005 15:40 GMT
> Question to the community: why doesn't Java automatically save some
> hashvalue when streaming an instance of a serializable class instead of
> relying on a 'manual' value like serialVersionUID?

That is, in fact, the default behavior.  But you, the developer, might
consider two versions of the class compatible even though their hash would
differ, e.g.

"I added two fields, but they're null by default anyway, so I can still
deserialize older versions safely."


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.