Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java serialization: readFields() beyond of readObject()?

ObjectInputStream.readFields() is eligible only within private void readObject(ObjectInputStream) method.

public ObjectInputStream.GetField readFields() throws IOException, ClassNotFoundException {
  SerialCallbackContext ctx = curContext;
  if (ctx == null) {
    throw new NotActiveException("not in call to readObject");
  }
...

I'm in situation when I can't use default serialisation for reading object (i.e. ObjectInputStream.defaultReadObject()) and don't wish to implement readObject() method in all my classes. In ideal case I would like to have ownDefaultReadObject() method that will construct new object from serialized fields (e.g. by reflection).

Any ideas?

If someone would like to know more. Field names in some of my classes were renamed (e.g. by obfuscator) to a, b, c etc. Such classes were serialized with renamed fields using default Java serialization. I need to deserialise them to original classes (I know pairs of field names for each class; a=> fieldName, b=> age, c=>gender etc.).

like image 507
FoxyBOA Avatar asked Jul 31 '15 09:07

FoxyBOA


People also ask

What is the purpose of readResolve () method in serialization?

For Serializable and Externalizable classes, the readResolve method allows a class to replace/resolve the object read from the stream before it is returned to the caller. By implementing the readResolve method, a class can directly control the types and instances of its own instances being deserialized.

How many methods do you implement if a class implements serializable interface?

How many methods Serializable has? Explanation: Serializable interface does not have any method. It is also called a marker interface. 5.

What happens if the object to be serialized?

To serialize an object means to convert its state to a byte stream so way that the byte stream can be reverted back into a copy of the object. A Java object is serializable if its class or any of its superclasses implements either the java.

Which of this class contains the method for Deserializing an object?

The ObjectInputStream class contains readObject() method for deserializing an object.


1 Answers

To rename fields from an object stream, the method you need to override is ObjectInputStream.readClassDescriptor which returns an ObjectStreamClass.

Instances ObjectStreamClass fulfil one of two different roles through large different subsets of the interface. For the avoidance of doubt, this design choice should not be copied.

  • Describes the fields of a serialisable class running in the current JVM instance. Find these instance through ObjectStreamClass.lookup.
  • Describes the fields of a serialisable class as represented in a particular serialised stream. These instances are returned by the implementations of ObjectInputStream.readClassDescriptor.

In your override call super.readClassDescriptor. This will read in the data from the stream. Substitute the value from the stream with one having the new fields names, if it's a class you're interested in.

How to create you own ObjectStreamClass? Write dummy instance of the classes you are interested in to an ObjectOutputStream. You can do this as part of the built, just keeping the binary data. Read with another ObjectInputStream with readClassDescriptor overridden to stash the descriptors.

ObjectInputStream.defaultReadObject/readFields wouldn't make any sense outside of readObject (or similar) because they rely on the current deserialising object rather than an argument. There are other limitations to prevent other code calling defaultReadObject to rewrite fields that must remain constant, copied validated, security checked or similar.

like image 191
Tom Hawtin - tackline Avatar answered Sep 27 '22 20:09

Tom Hawtin - tackline