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

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.).

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.

Related

How do I implement a getter where the caller can't edit the returned object?

I want to make a getter that doesn't allow the caller to edit the returned object.
Using a List as an example (though I would like the answer to apply to any other type as well), this is the usual approach for returning and for editing an attribute:
class MyClass {
private List<String> strings;
// to get the whole object
public List<String> getStrings() {
return this.strings;
}
// to alter the object
public void addString(String newStr) {
this.strings.add(newStr);
}
//...
}
However, this doesn't prevent that some other class from doing this
myClassInstance.getStrings().add("that's a dumb implementation, bro");
and that would be kind of rude since I created addString() for that specific purpose.
I would rather if other classes would only use the getStrings() method for reading, because there might be a similar case where I don't want to implement the addString() method. In that situation, other classes are able to edit strings anyway through the getter, but I still want to be able to edit the object privately in the C class.
I know this wouldn't be a problem if the attribute was a primitive type since those are saved directly in the instance, but objects are references to memory, so any class that's able to get its hands on those references can edit it if the object type allows that.
Can I just trust that other classes won't try to edit my object through the getter?
There's the option of cloning it (some classes may override the clone() method), but is this a good use for clone()? What are the best practices of cloning an object?
Is it worth it to create a custom class (called ReadOnlyList, for this example) that is only writeable in the constructor (like this), then copy my strings to a new ReadOnlyList, and return that?
Also, should objects provide a method that returns a non-writeable clone of the object to solve this?
You can have getStrings return an unmodifiable list.
public List<String> getStrings() {
return Collections.unmodifiableList(this.strings);
}
https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#unmodifiableList(java.util.List)
Can I just trust that other classes won't try to edit my object through the getter?
No.
There's the option of cloning it (some classes may override the clone() method), but is this a good use for clone()? What are the best practices of cloning an object?
The oracle docs provide a proposed strategy:
Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods. (https://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html)
Is it worth it to create a custom class (called ReadOnlyList, for this example) that is only writeable in the constructor (like this), then copy my strings to a new ReadOnlyList, and return that?
In this case not (see Micky Loo's answer). However in a more special case yes (if you have to guarantee immutableness and can not copy the object).
Also, should objects provide a method that returns a non-writable clone of the object to solve this?
You can not create a const return value in Java. see: Const return values in Java

New objects: new operator vs serialization

As I understood from what I've read there are basically two ways to create completely new objects in Java: 1) by using new operator and 2) by means of serialization (for deep copying, for example). All other object manipulations (like assigning, for instance) deal with references to existing objects. But what is the difference between the two above mentioned ways in terms of inner logic? It seems that one difference is that serialization somehow doesn't use constructor methods. Am I right? Are there other differences?
By 'inner logic' I mean how the compiler (or whoever deals with it) creates object step-by-step, what algorithm it uses, what methods are used for that and so on. More like what Margaret Bloom was writing about in her answer but in more detail.
FURTHER CONFUSION CLARIFICATION:
So do I get it right that during deserialization the copy of the object:
class Class1 {
static ARRAY_LENGTH = 10;
public class1() {
int[] anArray = new int[ARRAY_LENGTH];
anArray[0] = 5;
...
anArray[9] = -2;
}
}
will include a copy of the array created elsehow (how? since no constructor has been called)? And furthermore, though the original array (before serialization) has been created by using static field (which is lost during serialization) its deserialized copy will nevetheless be identical to the original array?
Serialization and the new operator are completely different things, though they both result in a reference to a newly allocated object.
You can find detailed information about the new operator in chapter 15.9.4 Run-Time Evaluation of Class Instance Creation Expressions of the Java Language Specification.
At run time, evaluation of a class instance creation expression is as follows.
[...]
Next, space is allocated for the new class instance.
[...]
The new object contains new instances of all the fields declared in the specified
class type and all its superclasses.
[...]
Next, the actual arguments to the constructor are evaluated, left-to-right. [...]
Next, the selected constructor of the specified class type is invoked. This results in
invoking at least one constructor for each superclass of the class type.
The value of a class instance creation expression is a reference to the newly created
object of the specified class. Every time the expression is evaluated, a fresh object
is created.
Editing mine
So long story short, new allocates space for a new object (specifically space for its fields), initialize its fields with their default values and invokes the chosen constructor.
Java Serialization is another matter entirely.
The ability to store and retrieve JavaTM objects is essential to building all but the most transient applications. The key to storing and retrieving objects in a serialized form is representing the state of objects sufficient to reconstruct the object(s).
Emphasis mine
Which means that serialization was designed to allow the programmer to save objects states into a persistent medium (abstracted into stream within Java) and read them back.
As such, deserializiation does not invoke constructors since the object state is restored automatically by reading it out the stream. You can override the default behavior though.
Reading an object from the ObjectInputStream is analogous to creating a new object. Just as a new object's constructors are invoked in the order from the superclass to the subclass, an object being read from a stream is deserialized from superclass to subclass. The readObject or readObjectNoData method is called instead of the constructor for each Serializable subclass during deserialization.
Emphasis mine
Said that, I would like to stress out how using new and serialization are totally unrelated things from a conceptual point of view.
In the first case you are creating your own new object, in the latter you are reading a previously saved object (possibly by someone else).
Even though they can be thought as similar for their final result, you should have, in your mind, a really clear distinction between the twos.
New operator is use to create object in memory whereas serialization is the concept belongs to data persistence and it could also be used for creating a new object in memory.
If an object implements java.io.Serializable it will be marked as Serializable Object and data in object could be converted to byte stream (serialize) and we could use this byte stream data to create a new object in memory (desrialize). Java supports 2 objects for serialize and deserialize, they are ObjectInputStream and ObjectOutputStream
Disagree with deserializiation does not invoke constructors:
In fact, Deserializiation just does not invoke the constructors defined in the class body. As depends on java.reflect, it of course need to invoke constructors to produce a Object from a Class. It just invoke the custom constructors created by sun.reflect.ReflectionFactory.newConstructorForSerialization(Class<?> var1, Constructor var2).

Best design approach for creating Immutable Class

I am reading about the specific guidelines that needs to be followed while creating Immutable Class in Effective Java.
I read that In Immutable class method should not allowed to be overridden otherwise overridden method may change the behaviour of method. Following are the design approaches available in java to solve this problem :-
We can mark class final but as per my understanding, it has a one disadvantage that it makes the class inextensible.
Secondly is to make individual methods final but I can not get other disadvantage besides that we need to individually mark each method as final in order to prevent overridding.
As per book,better approach is to make the constructor private or package-private and provide public static factory method for creating object.
My question is: Even if we include private or default constructor in the class, it cannot be extended anymore in same package (in other package in case of package-private constructor), it has a same problem which the first one had. How is it considered as the better approach than the previous ones?
An immutable object should not be extensible. Why?
Because extending it will allow either direct access to fields (if they are protected which would allow writing methods that change them), or adding state which may be mutable.
Imagine we wrote a class FlexiblyRoundableDouble that extends Double, which has an additional field roundingMode that lets us choose a "rounding mode". You could write a setter for this field, and now your object is mutable.
You can argue that if all the methods are set as final, you cannot change the original behavior of the object. The only methods that could access your roundingMode field are new methods that are not polymorphically available if you assign your object to a Double variable. But when a class's contract says that it's immutable, you make decisions based on that. For example, if you write a clone() method or copy constructor for a class that has Double fields, you know that you don't need to deep-copy the Double fields, as they do not change their state, and can therefore be safely shared between the two clones.
Also, you can write methods that return the internal object without fearing that the caller will then change that object. If the object was mutable, you'd have to make a "defensive copy" of it. But if it's immutable, it's safe to return a reference to the actual internal object.
However, what happens if someone assigned a FlexiblyRoundableDouble to one of your Double fields? That object would be mutable. The clone() would assume it isn't, it will be shared between two objects, perhaps even returned by a method. The caller would then be able to cast it back as a FlexiblyRoundableDouble, change the field... and it will affect other objects that use that same instance.
Therefore, immutable objects should be final.
All this has nothing to do with the constructor issue. Objects can be safely immutable with public constructors (as demonstrated by String, Double, Integer and other standard Java immutables). The static factory method is simply a way utilizing the fact that the object is immutable, and several other objects can hold references to it safely, to create fewer objects with the same value.
Providing a static factory method gives you room to implement the Flyweight Pattern.
They're stating that you should hide the possibility of creating a new object using a constructor, and should rather make a call to a method which checks if an object with similar state exists in the "object pool" (a map filled with objects waiting to be re-used). Not re-using immutable objects is a waste of memory; this is why String literals are encouraged, and new String() is shunned (unless needed).
class ImmutableType {
private static final Map<Definition, ImmutableType> POOL = new HashMap<>();
private final Definition definition;
private ImmutableType(Definition def) {
definition = def;
}
public static ImmutableType get(Definition def) {
if(POOL.contains(def))
return POOL.get(def);
else {
ImmutableType obj = new ImmutableType(def);
POOL.put(def, obj);
return obj;
}
}
}
Definition stores the state of the ImmutableType. If a type with the same definition already exists in the pool, then re-use it. Otherwise, create it, add it to the pool then return it as the value.
As for the statement about marking the class final, immutable types should not be extensible in the first place (to avoid possibly modifying behavior). Marking every method final is just crazy for immutable classes.

making a class immutable in java

To make a class immutable what I can do is:
1)Make class final
2)do not provide setters
3)mark all variables as final
But if my class has another object of some other class then , somone can change value of that object
class MyClass{
final int a;
final OtherClass other
MyClass(int a ,OtherClass other){
this.a = a;
this.other = other;
}
int getA(){
return a;
}
OtherClass getOther(){
return other;
}
public static void main(String ags[]){
MyClass m = new Myclass(1,new OtherClass);
Other o = m.getOther();
o.setSomething(xyz) ; //This is the problem ,How to prevent this?
}
}
A) Make the OtherClass immutable as well
or
B) Don't allow direct access to the OtherClass object, instead providing only getters to act as a proxy.
Edit to add: You could make a deep copy of OtherClass and return a copy rather than the original, but that generally isn't the type of behavior you would expect in Java.
Immutability is best considered from the perspective of the API user. So your object API needs to satisfy the following two conditions:
No way for an external user to change the value of the object
A guarantee that any time the user reads or makes use of the object's value in the future, it will get the same result
Important note: It is in fact OK to have mutable data inside an immutable object as long as it behaves as an immutable object from the perspective of the API user. Consider java.lang.String for example: although it is generally considered as the definitive immutable class, it does in fact have a mutable internal field for caching the hashCode (not many people know this!).
So to address your question, if you wish to contain another (mutable) object inside an immutable object then you typically need to do one or more of the following:
Guarantee that nobody else can change the value of the mutable object. Typically this means ensuring that no-one else can have a reference to the mutable object, so this is only usually possible if you create the object yourself rather than accept a reference from outside.
Take a defensive deep copy of the mutable object, and don't hand out references to the new copy. Only allow operations that read the new copy in the public API. If you need to hand out a reference to this object, then you need to take another defensive copy (to avoid handing out a reference to the internal copy).
Use an immutable wrapper for the mutable object. Something like Collections.unmodifiableList. This is useful if you want to hand out a reference to the internal mutable object but don't want to run the risk of it being modified.
All of these solutions are a bit hacky - a better solution overall is to avoid the use of mutable objects within immutable objects. In the long run it's asking for trouble because sooner or later a mutable reference will leak out and you will have an extremely hard to find bug. You are better moving towards a full hierarchy of immutable objects (the approach taken by languages like Scala and Clojure)
I assume OtherClass (by the way you say Other once) is meant to be a class you don't control, or which has to have a setter.
If you can't remove getOther, change it to getOtherView and return a read-only view of other. There will be wrappers for all the get methods, but no set ones.
Return deep clones from your getters. You may find this to be no easy task.
All the objects referenced in the immutable class should be immutable, or at least be encapsulated as private and making sure that they are not modified (not inside the methods of your class and definitely not from the outside). For instance, if you have this situation:
public class MyImmutable {
private MutableClass mutableObject;
}
... You can not provide the getMutableObject() method, because doing so will open the door for outside modifications, like this:
myImmutable.getMutableObject().setSomeAttribute(newValue);
As a special case of the above, all collections and/or maps should be made immutable, with the ummodifiableXXX() methods in the Collections class.
you cannot (reasonably) stop that in java. if you don't have control over the other class, there are ways to effectively get immutable behavior, but it can be very expensive in practice. basically, you must always return a copy of that class in any public method return values. (the jdk actually has this problem with the TimeZone class).
But If my class has another object of some other class then , somone
can change value of that object...
Java objects are not primitive. If you mark a primitive as final, then its value cannot be changed once it is assigned. However, object contents cannot be final, only object references can be final. So you cannot make an object in this way.
One solution might be abandoning all setter/mutator methods those could change the particular fields of the object and encapsulating them in a way that you can only access them, not change them.
It is possible to create the immutable class in java by following ways
1.Don't Provide setter methods.
2.Make all fields are as final and private.
3.Make Class as final.

Java serialization: readObject() vs. readResolve()

The book Effective Java and other sources provide a pretty good explanation on how and when to use the readObject() method when working with serializable Java classes. The readResolve() method, on the other hand, remains a bit of a mystery. Basically all documents I found either mention only one of the two or mention both only individually.
Questions that remain unanswered are:
What is the difference between the two methods?
When should which method be implemented?
How should readResolve() be used, especially in terms of returning what?
I hope you can shed some light on this matter.
readResolve is used for replacing the object read from the stream. The only use I've ever seen for this is enforcing singletons; when an object is read, replace it with the singleton instance. This ensures that nobody can create another instance by serializing and deserializing the singleton.
Item 90, Effective Java, 3rd Ed covers readResolve and writeReplace for serial proxies - their main use. The examples do not write out readObject and writeObject methods because they are using default serialisation to read and write fields.
readResolve is called after readObject has returned (conversely writeReplace is called before writeObject and probably on a different object). The object the method returns replaces this object returned to the user of ObjectInputStream.readObject and any further back references to the object in the stream. Both readResolve and writeReplace may return objects of the same or different types. Returning the same type is useful in some cases where fields must be final and either backward compatibility is required or values must copied and/or validated.
Use of readResolve does not enforce the singleton property.
readResolve can be used to change the data that is serialized through readObject method. For e.g. xstream API uses this feature to initialize some attributes that were not in the XML to be deserialized.
http://x-stream.github.io/faq.html#Serialization
readObject() is an existing method in ObjectInputStream class.
At the time of deserialization readObject() method internally checks whether the object that is being deserialized has readResolve() method implemented. If readResolve() method exists then it will be invoked
A sample readResolve() implementation would look like this
protected Object readResolve() {
return INSTANCE:
}
So, the intent of writing readResolve() method is to ensure that the same object that lives in JVM is returned instead of creating new object during deserialization.
readResolve is for when you may need to return an existing object, e.g. because you're checking for duplicate inputs that should be merged, or (e.g. in eventually-consistent distributed systems) because it's an update that may arrive before you're aware of any older versions.
readResolve() will ensure the singleton contract while serialization.
Please refer
As already answered, readResolve is an private method used in ObjectInputStream while deserializing an object. This is called just before actual instance is returned. In case of Singleton, here we can force return already existing singleton instance reference instead of deserialized instance reference.
Similary we have writeReplace for ObjectOutputStream.
Example for readResolve:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class SingletonWithSerializable implements Serializable {
private static final long serialVersionUID = 1L;
public static final SingletonWithSerializable INSTANCE = new SingletonWithSerializable();
private SingletonWithSerializable() {
if (INSTANCE != null)
throw new RuntimeException("Singleton instance already exists!");
}
private Object readResolve() {
return INSTANCE;
}
public void leaveTheBuilding() {
System.out.println("SingletonWithPublicFinalField.leaveTheBuilding() called...");
}
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
SingletonWithSerializable instance = SingletonWithSerializable.INSTANCE;
System.out.println("Before serialization: " + instance);
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("file1.ser"))) {
out.writeObject(instance);
}
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("file1.ser"))) {
SingletonWithSerializable readObject = (SingletonWithSerializable) in.readObject();
System.out.println("After deserialization: " + readObject);
}
}
}
Output:
Before serialization: com.ej.item3.SingletonWithSerializable#7852e922
After deserialization: com.ej.item3.SingletonWithSerializable#7852e922
When serialization is used to convert an object so that it can be saved in file, we can trigger a method, readResolve(). The method is private and is kept in the same class whose object is being retrieved while deserialization.
It ensures that after the deserialization, what object is returned is the same as was serialised. That is, instanceSer.hashCode() == instanceDeSer.hashCode()
readResolve() method is not a static method. After in.readObject() is called while deserialisation it just makes sure that the returned object is the same as the one which was serialized as below while out.writeObject(instanceSer)
..
ObjectOutput out = new ObjectOutputStream(new FileOutputStream("file1.ser"));
out.writeObject(instanceSer);
out.close();
In this way, it also helps in singleton design pattern implementation, because every time same instance is returned.
public static ABCSingleton getInstance(){
return ABCSingleton.instance; //instance is static
}
I know this question is really old and has an accepted answer, but as it pops up very high in google search I thought I'd weigh in because no provided answer covers the three cases I consider important - in my mind the primary use for these methods. Of course, all assume that there is actually a need for custom serialization format.
Take, for example collection classes. Default serialization of a linked list or a BST would result in a huge loss of space with very little performance gain comparing to just serializing the elements in order. This is even more true if a collection is a projection or a view - keeps a reference to a larger structure than it exposes by its public API.
If the serialized object has immutable fields which need custom serialization, original solution of writeObject/readObject is insufficient, as the deserialized object is created before reading the part of the stream written in writeObject. Take this minimal implementation of a linked list:
public class List<E> extends Serializable {
public final E head;
public final List<E> tail;
public List(E head, List<E> tail) {
if (head==null)
throw new IllegalArgumentException("null as a list element");
this.head = head;
this.tail = tail;
}
//methods follow...
}
This structure can be serialized by recursively writing the head field of every link, followed by a null value. Deserializing such a format becomes however impossible: readObject can't change the values of member fields (now fixed to null). Here come
the writeReplace/readResolve pair:
private Object writeReplace() {
return new Serializable() {
private transient List<E> contents = List.this;
private void writeObject(ObjectOutputStream oos) {
List<E> list = contents;
while (list!=null) {
oos.writeObject(list.head);
list = list.tail;
}
oos.writeObject(null);
}
private void readObject(ObjectInputStream ois) {
List<E> tail = null;
E head = ois.readObject();
if (head!=null) {
readObject(ois); //read the tail and assign it to this.contents
this.contents = new List<>(head, this.contents)
}
}
private Object readResolve() {
return this.contents;
}
}
}
I am sorry if the above example doesn't compile (or work), but hopefully it is sufficient to illustrate my point. If you think this is a very far fetched example please remember that many functional languages run on the JVM and this approach becomes essential in their case.
We may want to actually deserialize an object of a different class than we wrote to the ObjectOutputStream. This would be the case with views such as a java.util.List list implementation which exposes a slice from a longer ArrayList. Obviously, serializing the whole backing list is a bad idea and we should only write the elements from the viewed slice. Why stop at it however and have a useless level of indirection after deserialization? We could simply read the elements from the stream into an ArrayList and return it directly instead of wrapping it in our view class.
Alternatively, having a similar delegate class dedicated to serialization may be a design choice. A good example would be reusing our serialization code. For example, if we have a builder class (similar to the StringBuilder for String), we can write a serialization delegate which serializes any collection by writing an empty builder to the stream, followed by collection size and elements returned by the colection's iterator. Deserialization would involve reading the builder, appending all subsequently read elements, and returning the result of final build() from the delegates readResolve. In that case we would need to implement the serialization only in the root class of the collection hierarchy, and no additional code would be needed from current or future implementations, provided they implement abstract iterator() and builder() method (the latter for recreating the collection of the same type - which would be a very useful feature in itself). Another example would be having a class hierarchy which code we don't fully control - our base class(es) from a third party library could have any number of private fields we know nothing about and which may change from one version to another, breaking our serialized objects. In that case it would be safer to write the data and rebuild the object manually on deserialization.
The readResolve Method
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. The method is defined as follows:
ANY-ACCESS-MODIFIER Object readResolve()
throws ObjectStreamException;
The readResolve method is called when ObjectInputStream has read an object from the stream and is preparing to return it to the caller. ObjectInputStream checks whether the class of the object defines the readResolve method. If the method is defined, the readResolve method is called to allow the object in the stream to designate the object to be returned. The object returned should be of a type that is compatible with all uses. If it is not compatible, a ClassCastException will be thrown when the type mismatch is discovered.
For example, a Symbol class could be created for which only a single instance of each symbol binding existed within a virtual machine. The readResolve method would be implemented to determine if that symbol was already defined and substitute the preexisting equivalent Symbol object to maintain the identity constraint. In this way the uniqueness of Symbol objects can be maintained across serialization.

Categories