How to generate serialVersionUID programmatically in Java?

I am working on a project that generates Java files. I would like to be able to add an additional serialVersionUID , as it would be using serialver .

Is there a way to do this when I generate the Java code, or do I need to ask the tool user to provide the UID manually? To be clear, I do not want to do this automatically through Eclipse or the serialver tool, but for this it can be done through Java .

+7
java serialization serialversionuid
source share
5 answers

There is a version of the original serialver tool available from OpenJDK . All this comes to this call:

 ObjectStreamClass c = ObjectStreamClass.lookup(MyClass.class); long serialID = c.getSerialVersionUID(); System.out.println(serialID); 

In JDK 6, at least it returns the same number with the serialver tool.

+7
source share

From ObjectStreamClass :

 /** * Computes the default serial version UID value for the given class. */ private static long computeDefaultSUID(Class<?> cl) { if (!Serializable.class.isAssignableFrom(cl) || Proxy.isProxyClass(cl)) { return 0L; } try { ByteArrayOutputStream bout = new ByteArrayOutputStream(); DataOutputStream dout = new DataOutputStream(bout); dout.writeUTF(cl.getName()); int classMods = cl.getModifiers() & (Modifier.PUBLIC | Modifier.FINAL | Modifier.INTERFACE | Modifier.ABSTRACT); /* * compensate for javac bug in which ABSTRACT bit was set for an * interface only if the interface declared methods */ Method[] methods = cl.getDeclaredMethods(); if ((classMods & Modifier.INTERFACE) != 0) { classMods = (methods.length > 0) ? (classMods | Modifier.ABSTRACT) : (classMods & ~Modifier.ABSTRACT); } dout.writeInt(classMods); if (!cl.isArray()) { /* * compensate for change in 1.2FCS in which * Class.getInterfaces() was modified to return Cloneable and * Serializable for array classes. */ Class<?>[] interfaces = cl.getInterfaces(); String[] ifaceNames = new String[interfaces.length]; for (int i = 0; i < interfaces.length; i++) { ifaceNames[i] = interfaces[i].getName(); } Arrays.sort(ifaceNames); for (int i = 0; i < ifaceNames.length; i++) { dout.writeUTF(ifaceNames[i]); } } Field[] fields = cl.getDeclaredFields(); MemberSignature[] fieldSigs = new MemberSignature[fields.length]; for (int i = 0; i < fields.length; i++) { fieldSigs[i] = new MemberSignature(fields[i]); } Arrays.sort(fieldSigs, new Comparator<MemberSignature>() { public int compare(MemberSignature ms1, MemberSignature ms2) { return ms1.name.compareTo(ms2.name); } }); for (int i = 0; i < fieldSigs.length; i++) { MemberSignature sig = fieldSigs[i]; int mods = sig.member.getModifiers() & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.STATIC | Modifier.FINAL | Modifier.VOLATILE | Modifier.TRANSIENT); if (((mods & Modifier.PRIVATE) == 0) || ((mods & (Modifier.STATIC | Modifier.TRANSIENT)) == 0)) { dout.writeUTF(sig.name); dout.writeInt(mods); dout.writeUTF(sig.signature); } } if (hasStaticInitializer(cl)) { dout.writeUTF("<clinit>"); dout.writeInt(Modifier.STATIC); dout.writeUTF("()V"); } Constructor[] cons = cl.getDeclaredConstructors(); MemberSignature[] consSigs = new MemberSignature[cons.length]; for (int i = 0; i < cons.length; i++) { consSigs[i] = new MemberSignature(cons[i]); } Arrays.sort(consSigs, new Comparator<MemberSignature>() { public int compare(MemberSignature ms1, MemberSignature ms2) { return ms1.signature.compareTo(ms2.signature); } }); for (int i = 0; i < consSigs.length; i++) { MemberSignature sig = consSigs[i]; int mods = sig.member.getModifiers() & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.STATIC | Modifier.FINAL | Modifier.SYNCHRONIZED | Modifier.NATIVE | Modifier.ABSTRACT | Modifier.STRICT); if ((mods & Modifier.PRIVATE) == 0) { dout.writeUTF("<init>"); dout.writeInt(mods); dout.writeUTF(sig.signature.replace('/', '.')); } } MemberSignature[] methSigs = new MemberSignature[methods.length]; for (int i = 0; i < methods.length; i++) { methSigs[i] = new MemberSignature(methods[i]); } Arrays.sort(methSigs, new Comparator<MemberSignature>() { public int compare(MemberSignature ms1, MemberSignature ms2) { int comp = ms1.name.compareTo(ms2.name); if (comp == 0) { comp = ms1.signature.compareTo(ms2.signature); } return comp; } }); for (int i = 0; i < methSigs.length; i++) { MemberSignature sig = methSigs[i]; int mods = sig.member.getModifiers() & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED | Modifier.STATIC | Modifier.FINAL | Modifier.SYNCHRONIZED | Modifier.NATIVE | Modifier.ABSTRACT | Modifier.STRICT); if ((mods & Modifier.PRIVATE) == 0) { dout.writeUTF(sig.name); dout.writeInt(mods); dout.writeUTF(sig.signature.replace('/', '.')); } } dout.flush(); MessageDigest md = MessageDigest.getInstance("SHA"); byte[] hashBytes = md.digest(bout.toByteArray()); long hash = 0; for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) { hash = (hash << 8) | (hashBytes[i] & 0xFF); } return hash; } catch (IOException ex) { throw new InternalError(); } catch (NoSuchAlgorithmException ex) { throw new SecurityException(ex.getMessage()); } } 
+3
source share

Try the hash code of the class name of the generated class.

There may be collisions because the hash code is not unique, but these collisions are statistically unlikely.

Here's the documentation on how serialVersionUID values ​​are generated. This is much more complicated than I would have guessed.

Due to its complexity, I would either enter the user identifier myself or simply use a simple hash of the full class name.

+2
source share

If your tool generates new code, you do not need to compute it like serialver does. Just use 1 or -1 or whatever.

+2
source share

This is an old thread, but I think serialVersionUID is still one of the hot topics.

When I started writing Java codes, it was too difficult to find and assign a unique value to the serlialVersionUID variable for me. After a while, a simple date format (yyyy-MM-ddTHH: mm: ss) gave me an idea: why don't I generate a value from the current date and time?

So, I started to generate (of course, manually) the values ​​in accordance with the current date and time.

Suppose the current date and time is 01/09/2015 11:00. I would assign the value 201601091100L to serialVersionUID.

I hope this idea helps you further improve your projects.

+1
source share

All Articles