I am trying to load data from Java object streams from another application. Since I do not have access to the source code of that application, I used jdeserialize to extract the class definitions from the object streams. In general this works fine. Unfortunately, some (older) streams seem to have been serialized using classes with different serial version IDs. Otherwise the classes are identical to the ones I already have (as extracted by jdeserialize). This is the error I get when deserializing the older streams:
java.io.InvalidClassException: tls.other.app.package.SomeClass; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2
When I change the serial version IDs in the existing classes I can deserialize the older streams, but of course the new ones are not working anymore. I want to deserialize both versions of the Java object streams with the same application.
I tried different things - without success so far:
I created two packages with the same classes, just different serial version IDs. I created my own ObjectInputStream, overwriting readClassDescriptor(). The I try to read the stream using the first package. When that fails with the error message above I read the stream again changing the package / class name inside of readClassDescriptor():
@Override protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException { ObjectStreamClass resultClassDescriptor = super.readClassDescriptor(); String className = resultClassDescriptor.getName(); if(_alternatePackage && className.startsWith("tls.other.app.package")) { Class<?> localClass; className = className.replace("tls.other.app.package", "tls.other.app.package2"); try { localClass = Class.forName(className); } catch (ClassNotFoundException e) { logger.error("No local class for " + resultClassDescriptor.getName(), e); return resultClassDescriptor; } resultClassDescriptor = ObjectStreamClass.lookup(localClass); } return resultClassDescriptor; }If I try to load the old streams I get the following error message:
java.io.StreamCorruptedException: invalid type code: 00
I tried to make the serial version ID dynamic doing something like this:
private static final long serialVersionUID = JavaObjectStreamReader.getSerialVersionUID(IDBSClasses.PropertyValueDTO);Of coursem the serialVersionUID is static and only initialized once. Therefore, I tried to use different ClassLoaders to reload the class after the first deserialization fails. That did not work either.
Is there any way to deserialize the old and the new streams in the same application?
serialVersionUID. Despite its name, it is not a version number. It should be left constant forever, and other means used to version classes, many of which are already built-in to Java Object Serialization.java.io.StreamCorruptedException: invalid type code: 00with an approach as you’ve shown. But note that letting this problem aside, your approach is unnecessarily complicated. When you replace the stream’s descriptor returned bysuper.readClassDescriptor()with a local version acquired byObjectStreamClass.lookup(…), you already bypassed the version check because the local descriptor will always have the right id (matching the local class it was generated from), regardless of the class. So you don’t need different versions of the classes.readResolve()andwriteReplace()methods provide even more ways not to disturb theserialVersionUID.,