RFR [9] 8071472: Add field access to support setting final fields in readObject
Chris Hegarty
chris.hegarty at oracle.com
Thu Mar 5 13:46:27 UTC 2015
Hi,
Peter Levart and I have been working on an API to support setting of final fields during custom deserialization. Dealing with final fields during deserialization is a pain point only partially addressed in JSR 133 ( in Java 5 ). What we are proposing is a simple API solution to resolve this.
Current limitations ( primary motivation for the new API ):
* defaultReadObject can set final fields, but it is somewhat limiting.
The fields must have a value in the deserialized stream. This is
not flexible when evolving a classes representation, or when
dealing with transient final fields.
* Setting final fields in readObject using reflection requires
java.lang.reflect.ReflectPermission("suppressAccessChecks").
Granting this permission, when only required to set final fields
during custom deserialization, is dangerous. Information
(possibly confidential) and methods normally unavailable may
be accessible to malicious code.
* It is not possible to grant 'suppressAccessChecks' for particular
classes or objects, or restrict the ability to set final fields through
reflection for the period of the readObject callback, and just for
the object being reconstructed.
* Using reflection to set final fields can have a performance cost,
as the reflective implementation may issue a barrier for each
field set.
Outline of the new API:
* New interface ObjectInputStream.FieldAccess with overloaded
set(name, value) methods. Similar in some respects to Get/PutField,
but with j.l.r.Field semantics.
* The FieldAccess instance is retrieved from ObjectInputStream.fields(),
which can only be called during a readObject callback. Similar to
readFields() (returns GetField).
* FieldAccess, once retrieved, ensures that all final fields are set,
and set only once.
* No behaviour changes to existing code. Unless fields() is called
existing code is unaffected.
* Can be used with either GetFields, or defaultReadObject.
Specification:
http://cr.openjdk.java.net/~chegar/8071472/00/specdiff/
Example:
class Stamp implements Serializable {
private transient final long millis;
Stamp() { millis = System.currentTimeMillis(); }
public long stamp() { return millis; }
private void readObject(java.io.ObjectInputStream in) throws Exception {
in.fields().set("millis", System.currentTimeMillis());
}
}
We have a fully working implementation, tests, etc, in the sandbox:
hg clone http://hg.openjdk.java.net/jdk9/sandbox sandbox
cd sandbox
sh get_source.sh
sh common/bin/hgforest.sh update -r serial-exp-branch
Webrev for convenience:
http://cr.openjdk.java.net/~chegar/8071472/00/webrev/
Feedback welcome.
-Chris.
More information about the core-libs-dev
mailing list