Inspection Gadgets - RFE

In the "Serializable class without serialVersionUID" have an intention action to add such an ID to the class.

I know Eclipse has such a plugin, and its a great help.
I noticed a plugin for IDEA, but this has never worked (for me).

Having it right there on the warning/intention options would be great.

Nick

26 comments


Automatically creating a serialVersionUID field is easy, the problem is what value to give it. My personal preference (which I've seen listed as a "best practice" in a couple of places), is to set the value of serialVersionUID to 1. That way no matter how the class changes, serialization can still be made to work, through clever implementations of readObject() and writeObject(). OTOH, this doesn't seem to be universal, and so I've been loathe to automate it.

(As an aside, InspectionGadgets RFE's should be issued via the Tracker. That way JetBrains knows about them, and they are less likely to get forgotten by me.)

--Dave Griffith

0

Dave Griffith wrote:

Automatically creating a serialVersionUID field is easy, the problem is what value to give it. My personal preference (which I've seen listed as a "best practice" in a couple of places), is to set the value of serialVersionUID to 1. That way no matter how the class changes, serialization can still be made to work, through clever implementations of readObject() and writeObject(). OTOH, this doesn't seem to be universal, and so I've been loathe to automate it.


The Alt-Insert option to add a serialVersionUID field (plugin I think)
appears to use the serialver tool or equivalent to extract the
automatically calculated value from the .class file.

This allows one to retain backwards compatibility with released versions
of the project.

Ciao,
Gordon

--
Gordon Tyler (Software Developer)
Quest Software <http://www.quest.com/>
260 King Street East, Toronto, Ontario M5A 4L5, Canada
Voice: (416) 933-5046 | Fax: (416) 933-5001

0

This plugin always crashed for me - do you have it working on 4.5.2?

0

I just checked the sources. The SerialVersionUID plugin does make an out-of-process call to serialver.exe. Among other horribleness, this presumably means there are issues with the plugin on Mac and Linux. If someone can give me a good all-Java solution, I'll happily add it to IG. Preliminary googling indicates that there are no good libraries for this, that it's tougher that it looks, and that I frankly don't have the time to do this right myself.

--Dave Griffith

0

Ill try and dig out the source for the Eclipse serial UID

0

Dave Griffith wrote:

I just checked the sources. The SerialVersionUID plugin does make an out-of-process call to serialver.exe. Among other horribleness, this presumably means there are issues with the plugin on Mac and Linux. If someone can give me a good all-Java solution, I'll happily add it to IG. Preliminary googling indicates that there are no good libraries for this, that it's tougher that it looks, and that I frankly don't have the time to do this right myself.

--Dave Griffith

I have a new version that uses the ObjectStreamClass but I've had
problems with Classloader that I haven't been able to figure out. It
works for me when I'm testing it but as soon as I try it on my "real"
project it pukes. Can't find the class I'm working on. The source is
available at: https://intellij-idea-plugins.dev.java.net/

0

Brad wrote:

Dave Griffith wrote:

>> I just checked the sources. The SerialVersionUID plugin does make an
>> out-of-process call to serialver.exe. Among other horribleness, this
>> presumably means there are issues with the plugin on Mac and Linux.
>> If someone can give me a good all-Java solution, I'll happily add it
>> to IG. Preliminary googling indicates that there are no good
>> libraries for this, that it's tougher that it looks, and that I
>> frankly don't have the time to do this right myself.
>>
>> --Dave Griffith


I have a new version that uses the ObjectStreamClass but I've had
problems with Classloader that I haven't been able to figure out. It
works for me when I'm testing it but as soon as I try it on my "real"
project it pukes. Can't find the class I'm working on. The source is
available at: https://intellij-idea-plugins.dev.java.net/

I should clarify. The "new" code doesn't use the serialver tool and
therefore doesn't make an out-of-process call and should work on any
platform but... like I said, I've had issues with Classloading

0

Dave Griffith wrote:

I just checked the sources. The SerialVersionUID plugin does make an
out-of-process call to serialver.exe. Among other horribleness, this


Afaik, the serialver tool is simply a command-line wrapper for
sun.tools.serialver.SerialVer (in tools.jar). Not the prettiest option,
but perhaps less horrible then an oop call? You can rely on the
tools.jar being there in the idea-native jre.

Besides, 'simple monsters' should be used to horribleness, right? ;)

CU,
Edwin

0

Edwin van Ouwerkerk Moria wrote:

Dave Griffith wrote:

>> I just checked the sources. The SerialVersionUID plugin does make an
>> out-of-process call to serialver.exe. Among other horribleness, this


Afaik, the serialver tool is simply a command-line wrapper for
sun.tools.serialver.SerialVer (in tools.jar). Not the prettiest option,
but perhaps less horrible then an oop call? You can rely on the
tools.jar being there in the idea-native jre.

Besides, 'simple monsters' should be used to horribleness, right? ;)

CU,
Edwin

Apparently nobody reads my posts. You don't need to rely on tools.jar.
The ObjectStreamClass has a method to create the uid. All you need to do
is pass it the Class of the object you want the uid for.

0

Is there any benefit (from a serialization) standpoint to a class having:

serialVersionUID = 9782673681281L;

vs.

serialVersionUID = 1L;

0

Right, but that's not good enough for writing an inspection quick fix, because the class that you're creating the UID for may not be compiled. All I've got is a parse tree, not a compiled and loadable class. What I needed is an implementation of the algorithm, in a form I can pound into working with IDEA's PSI parse tree. However, now that I've been pointed to ObjectStreamClass and it's computeDefaultSUID() method, I can adapt the algorithm there. Thanks everyone.

--Dave Griffith

0


If someone had previously been serializing objects but not supplying a serialVersionUID for the class, you'll need something like the first one if you wish to change the class but still be able to read only serialized versions. For newly created classes, the second version is perfectly fine. For the whimsical, I've seen declarations like

private static long serialVersionUID = 0xFeedDeadBeefD00D;

which serve the same purpose.

--Dave Griffith

0

Dave Griffith wrote:

Right, but that's not good enough for writing an inspection quick fix, because the class that you're creating the UID for may not be compiled. All I've got is a parse tree, not a compiled and loadable class. What I needed is an implementation of the algorithm, in a form I can pound into working with IDEA's PSI parse tree. However, now that I've been pointed to ObjectStreamClass and it's computeDefaultSUID() method, I can adapt the algorithm there. Thanks everyone.

--Dave Griffith

That's the problem I had. I didn't have the compiled class so I had to
"require" that they compile the class before running the plugin, then
try to load the class with a custom Classloder(which didn't work half
the time). Never thought of using the algorithm from ObjectStreamClass.
But, you should be aware that the method for computing the UID has
changed since 1.3. I'm not exactly sure what the difference is(I would
assume the output's the same) but there is no computeDefaultSUID()
method in 1.3.1_03.

0


A serializable class doesnt have a UID specified, so when the object is serialized, an ID is generated on the fly based on methods, parameters, other stuff.
If you make a change to the class, even internal, then a new UID will be generated, hence rendering the clients unusable.

We just need an ID, no?

If Class A has UID = 1 and completely-unrelated Class B has UID = 1 is this an issue?
Do the UIDs have to be unique across classes?
What if they are not?

NIck

0


UIDs are class-specific. If you just mark all your classes as serialVersionUID=1 before you every serialize them, you'll have no problems.

0

Nick Pratt wrote:

A serializable class doesnt have a UID specified, so when the object is serialized, an ID is generated on the fly based on methods, parameters, other stuff.
If you make a change to the class, even internal, then a new UID will be generated, hence rendering the clients unusable.

We just need an ID, no?

If Class A has UID = 1 and completely-unrelated Class B has UID = 1 is this an issue?
Do the UIDs have to be unique across classes?
What if they are not?

NIck

A serializable class doesn't need a UID specified. If it's not supplied
it will be generated (as you say) but it CAN be specified. And yes, if
you make a change to a class that is serializable and doesn't have the
UID specified then the new class will be unusable in the sense that it
won't be compatible with 'old' versions of the class. That is precisely
what the UID is for.

Dave's point earlier was that if you had a Serializable class that
didn't supply the UID and you made changes to that class but still
wanted it to be "compatible" you would need the UIDs to be the same for
both versions and so you would need to 'generate' one using the 'old'
class (because that's what would have been generated 'on the fly'). But
for new classes (i.e. - one's that have never been serailized), using 1L
or any other number is fine as long as you remember to change it if you
have incompatible versions.

No, UIDs don't have to be unique across classes.

0

So why not just simply stick UID=1 as the intention action, and not worry about ObjectStreams and OOP calls?

Nick

0

Nick Pratt wrote:

So why not just simply stick UID=1 as the intention action, and not worry about ObjectStreams and OOP calls?

Nick

You could do that but...
1. It's not the 'standard' practice. See Effective Java or The
Java Programming Language Second Edition
2. Some people will want to know if a class has changed enough to change
the UID.

0

Nick Pratt wrote:

So why not just simply stick UID=1 as the intention action, and not worry about ObjectStreams and OOP calls?

Nick

Maybe it should be an option/setting?

0

Bloch only states that you should give it a random number, or "its also fine to pick a number out of thin air".

The easiest solution as I see it is:

private static final long serialVersionUID = 1L;

{:-)

0

Nick Pratt wrote:

Bloch only states that you should give it a random number, or "its also fine to pick a number out of thin air".

The easiest solution as I see it is:

private static final long serialVersionUID = 1L;

{:-)


The full quote is: "Common practice dictates that you generate the value
by running the serialver utility on the class, but it's also fine to
pick a number out of thin air."

I agree, just using 1L easiest solution. But, it's not always the
desired nor correct solution.

I think we've ran this thread into the ground now. Dave will come up
with something good no matter what we think:)

0

The main point is: Give it a number. What number you pick doesnt matter. There is no "correctness" here - any number is correct.

Why add additional complexity (and work) if 1L is the equivalent of 987293847234L from a serialization/versioning standpoint.

NIck

0

Nick Pratt wrote:

The main point is: Give it a number. What number you pick doesnt matter. There is no "correctness" here - any number is correct.

Why add additional complexity (and work) if 1L is the equivalent of 987293847234L from a serialization/versioning standpoint.

NIck

No, you missed the point. There are times when you want/need the
generated number. If not then there's no point in having a plugin to
insert it. Just use a Live Template.

0

If you read your object with ObjectInputStream, the serial version is also
read. You really want the same serial ver for all the objects you read in?
You're gonna end up with a possible InvalidClassException. This will
especially be the case if you have 2 classes with the same name in different
packages.

If it was as simple as doing 1L, then why did Sun go through major pain to
build this?

Every version of the JDK will generate a different serial version for your
class (at least from what I've seen).

What is your dang reason for really wanting to control that number in the
first place? I lost track in this thread.

Lastly, to solve the issue properly I think, what one would have to really
do is create the proper hash for the class, which would consist of the class
name, superinterfaces and members... Anyone up for it? :)

R

0

Every version of the JDK will generate a different
serial version for your
class (at least from what I've seen).


Every (Sun) JVM generates the same serialVersionUID as far as I know. The number is only different when the class has changed in a significant way. It can happen that different accessor methods are generated if a different compiler is used, which changes the serialVersioinUID, but I haven't seen it happen in any of my projects.

Lastly, to solve the issue properly I think, what one
would have to really
do is create the proper hash for the class, which
would consist of the class
name, superinterfaces and members... Anyone up for
it? :)


Creating a hash that matches the specification is not that difficult. I would be up for it, but I have a feeling that Dave has already implemented it himself. Very useful too, as it should be possible to create a serialVersionUID using the source file only. No need to compile first.

Bas

0



On 11/1/04 4:04 AM, in article
6564137.1099299890384.JavaMail.itn@is.intellij.net, "Bas Leijdekkers"
<no_mail@jetbrains.com> wrote:

>> Every version of the JDK will generate a different
>> serial version for your
>> class (at least from what I've seen).


Every (Sun) JVM generates the same serialVersionUID as far as I know. The
number is only different when the class has changed in a significant way. It
can happen that different accessor methods are generated if a different
compiler is used, which changes the serialVersioinUID, but I haven't seen it
happen in any of my projects.


I have conflicting sources of info, so I don't know what the right answer to
this is anymore... Kinda lame.

>> Lastly, to solve the issue properly I think, what one
>> would have to really
>> do is create the proper hash for the class, which
>> would consist of the class
>> name, superinterfaces and members... Anyone up for
>> it? :)


Creating a hash that matches the specification is not that difficult. I would
be up for it, but I have a feeling that Dave has already implemented it
himself. Very useful too, as it should be possible to create a
serialVersionUID using the source file only. No need to compile first.


Indeed.

R

0

Please sign in to leave a comment.