76

I want to create a class that, for example, extends HttpServlet? My compiler warns me that my class should have a serialVersionUID. If I know that this object will never be serialized, should I define it or add an annotation to suppress those warnings?

What would you do and why?

Steven Bluen
  • 141
  • 2
  • 11
Okami
  • 877
  • 1
  • 9
  • 11

12 Answers12

30

I don't know Java best practices, but it occurs to me that if you are claiming that serialization will never happen, you could add a writeObject method which throws. Then suppress the warning, safe in the knowledge that it cannot possibly apply to you.

Otherwise someone might in future serialize your object through the parent class, and end up with a default serialized form where:

  • the form isn't compatible between different versions of your code.
  • you've suppressed the warning that this is the case.

Adding an ID sounds like a bodge, since what you really want to do is not serialize. Expecting callers not to serialize your object means that you expect them to "know" when their HttpServlet is of your class. That breach of polymorphism is on your head for having a Serializable object which must not be serialized, and the least you can do is make sure unwary callers know about it.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • 1
    I think it's a lot of overhead but in a professional environment this seems quite necessary. – Okami Sep 28 '08 at 21:52
  • Just want to second the motions that you make sure you prohibit serialization (ie with an exception) if you aren't going to support it. – cynicalman Sep 28 '08 at 23:33
  • 2
    I would not go through the trouble of preventing serialization from ever happening. Just don't declare a SVUID, which means that each compile a unique one will be generated; making serialization unreliable but not breaking applications which depend on it, inadvertently. – Justin May 14 '10 at 03:38
  • AFAIK default UID is generated from the object graph, not by compile. Someone else says the same thing below and I'm sure it says that in Effective Java. – orbfish Oct 17 '11 at 17:00
  • 3
    @Justin Unreliable is not a word i would want mentioned in the same sentence as my app. – Stefan Nov 01 '12 at 20:17
21

If you do not plan to serialize instances, add a SuppressWarning.

A generated serial ID can be a bit dangerous. It suggests that you intentionally gave it a serial number and that it is save to serialize and deserialize. It's easy to forget to update the serial number in a newer version of your application where your class is changed. Deserialization will fail if the class fields have been changed. Having a SuppressWarning at least tells the reader of your code that you did not intend to serialize this class.

Benno Richters
  • 15,378
  • 14
  • 42
  • 45
15

I refuse to be terrorized by Eclipse into adding clutter to my code!

I just configure Eclipse to not generate warnings on missing serialVersionUID.

ykaganovich
  • 14,736
  • 8
  • 59
  • 96
  • 4
    I think that add @suppressWarning and throw exception when you do not support serialization is the best approach in a professional evironment. Your IDE to remembers you of serialization may be important in much cases. – The Student Mar 06 '10 at 23:21
  • 1
    I agree with Tom, most of the time it is annoying and unnecessary, but it SOMETIMES is useful and important. If you still use that approach for your project, I suggest you configure your Project to do so and not Eclipse itself (which will apply it to each and every project). Using @suppressWarning will get rid of the annoying occurences, but the "necessary" ones will not be muted. – dominicbri7 Jun 30 '11 at 14:28
14

Thanks @ Steve Jessop for his answer on this. It was 5 lines of code... hardly a hassle.

I added @SuppressWarnings("serial") just above the class in question.

I also added this method:

private void writeObject(ObjectOutputStream oos) throws IOException {
   throw new IOException("This class is NOT serializable.");
}

Hopefully that's what Steve meant :)

peterh
  • 11,875
  • 18
  • 85
  • 108
Mike
  • 171
  • 1
  • 2
6

Even if you know this object will be serialized there is no need to generate serialVersionUID because java will automatically generate it for you and will automatically keep track of changes so your serialization will always work just fine. You should generate it only if you know what you are doing (backward serialization compatibility, manual change tracking etc.)

So I would say suppressing the warning is the best and safest solution in most cases.

serg
  • 109,619
  • 77
  • 317
  • 330
  • 2
    if you want to serialize something, you should always provide an explicit version value (1, 2, 3, ...). This allows you to tell Java serialization when compatibility is broken. For example, if all you're doing is adding fields, it can still read old .ser files with the same version. – Scott Stanchfield Sep 29 '08 at 19:46
  • 3
    @Scott you don't always need to provide an explicit version value even when you are serializing. It depends on the serialization scope and the consequences of failing to deserialize. If you will only ever deserialize objects that were serialized by the same version of the code (like saving instance state on Android) then the auto-generated ID is fine. Also, if your serialized objects are merely a cache that you can reconstruct if serialization fails then that's also ok. A manual ID adds a lot of development overhead as you need to properly need to deal with version skew in deserialization. – Laurence Gonsalves Feb 17 '11 at 17:13
4

It is good to generate SVUID to every class implementing serializable. The reason is simple. You never know when it will be serialized by you or by some 3rd party. There can be configured a lot of services which will serialize servlets. For every IDE exists plugin which generates one or just use template and set svuid = 1L.

Rastislav Komara
  • 1,711
  • 8
  • 17
  • I'm not so sure about that.. If you add the SVUID it´s good to see what are you letting serialize. It can cause security problems if a client can get a password field by serializing your whole program. – The Student Mar 06 '10 at 23:26
  • Generating SVUID in Serializable classes has nothing to do with serializable fields. Of course, you should pay attention to which fields are serialized. – Rastislav Komara Mar 10 '10 at 13:34
  • 2
    If you generate a SVUID of 1 for example, then change the layout of your class that now means you must maintain SVUID (and update to 2). Most people won't maintain this. This is unnecessary if you don't intend the class to be serialized. – Justin May 14 '10 at 03:36
  • 1
    "SVUID to every class implementing serializable" If class is serializable there is always someone in the world who wants to serialize it. In general, my target was not to solve people's laziness. – Rastislav Komara May 19 '10 at 12:39
3

That warning drives me crazy, because every time you subclass a Swing class, you know you're never going to serialize it, but there is that stupid warning. But yeah, I let Eclipse generate one.

Paul Tomblin
  • 179,021
  • 58
  • 319
  • 408
2

Let Eclipse generate an ID. Quick and easy. Warnings are not to be ignored. Also saves you lots of trouble should you ever come to the point where the object /has/ to be serialized.

xmjx
  • 1,163
  • 1
  • 7
  • 18
  • 3
    I disagree. The ID in this case is useless clutter. This warning should, in my opinion, be suppressed. – skaffman Sep 28 '08 at 20:53
  • 11
    Warnings are a prompt asking you to make an informed decision, not instructions that are to be blindly followed. – McDowell Sep 29 '08 at 10:23
  • 1
    @McDowell The Serialization JavaDoc says it's strongly recommended. I mean, sure, you can just say the Sun/Oracle guys are nuts and you have a better idea of what's going on in Java than them. But the comment on the original question ("servlets might be serialized") indicates that sometimes (only sometimes) developers assume to know what happens but actually don't. See "select() isn't broken". – xmjx Aug 03 '12 at 12:27
  • 1
    I'm not sure it will save me from trouble. If I change the class and never change the generated ID, I am explicitly telling the compiler/JVM that old classes are still compatible. If I just let the runtime calculate and ID, it at least has some chance to detect incompatibilities that a human couldn't see. – marcus Jan 16 '13 at 18:13
  • @marcus: You are absolutely right. If you set an ID (whether just `1L` or some generated one) **hardcoded** in the class, you are basically taking the burden of updating that ID each time there are compatibility changes if you want things to work as they should. They are basically like a library version, but on the class level. Specifying an ID and then never changing it is much more harmful then just not specifying it. (let alone throwing an exception in `writeObject` which will turn out to be a maintenance nightmare I am predicting). – Stijn de Witt Mar 16 '17 at 12:54
2

If you leave out a serialVersionUID java will generate one for the class at compile time (it changes with every compilation).

When deserializing objects the serialVersionUID of the deserialized object is compared to that of the class in the jvm. If they are different they are considered incompatible and an Exception is thrown. This can happen for instance after upgrading your program and deserializing old classes.

I always use 1L for serialversionUID. It doesn't hurt (compared to the default generated) and it still leaves the option of breaking compatibility later by incrementing the id.

Glever
  • 105
  • 2
  • 8
    A serial version UID member is not added to classes at compile-time. If it is missing, it is computed from the member signatures of the class at runtime. It only changes when the signatures change, not necessarily with every compilation. – erickson Sep 29 '08 at 17:37
  • That it throws when the version number changes is a good thing. That is precisely why you should not implement it when you have no intention of serializing things, as it will alert you that this is in fact being done, and you need to change your classes to support it. – oligofren Mar 11 '21 at 12:13
2

It depends.

If you use different compilers to compile your source code multiple times, your compiled code could have different serializationIds that will break the serialization. Then you need to stick to a constant serializationId explicitly in your code. It must be static and final and per class (not inheritable).

However, if you always compile your code with a specific compiler and always deploy your code in one shot to all of your VMs, you probably need strict version checking and want to make sure that anytime there is only one version of you code running, in that case, you should just suppress the warning. So in case a VM is not deployed successfully and is running old version of your code, you probably expect an exception during serialization rather than quirk deserialized objects. This happens to be my case, we used to have a very very large cluster and we need strict version checking to find out any deployment issue.

Anyway, probably you should avoid serialization whenever possible since the default serialization is very slow compared to protocol buffers or thrift and does not support cross-language interoperability.

Daniel
  • 21
  • 1
1

If you know your applications never serializes things, suppress the warning application-wide. This can be done using javac command line arguments:

javac -Xlint -Xlint:-serial *******

This way you will have all warnings except "serial". IDE-s and build tools like Maven/SBT/Gradle work fine with that.

VasiliNovikov
  • 9,681
  • 4
  • 44
  • 62
1

Please follow this link to get detailed explanation: http://technologiquepanorama.wordpress.com/2009/02/13/what-is-use-of-serialversiouid/

Michael Myers
  • 188,989
  • 46
  • 291
  • 292
harshit
  • 7,925
  • 23
  • 70
  • 97