On 19/03/15 15:21, Peter Levart wrote:
On 03/19/2015 11:35 AM, Peter Firmstone wrote:
Chris / Peter,
Perhaps you could consider passing GetFields as a parameter to a
static method (identified by an annotation) and use fieldSetter to
change the fields before they're written?
Interesting idea. I'm reluctant to add confusion by mixing the concept
of stream field values and object fields values, so I think the
FieldSetter and GetField APIs should remain independent.
Or change the fields *as* they are written. It actually doesn't matter
if the method is static.
That way it would be possible to not only avoid implementing
readObject or writeObject, but to check invariants and be final field
friendly.
Just a thought.
Peter.
So you mean something like this or a variant of it. Instead of
readObject() instance method, a static method with an additional
FieldAccess parameter:
@ReadObject
private static void altReadObject(ObjectInputStream in, FieldAccess
fieldAccess) throws IOException, ClassNotFoundException {
// the same as in readObject, but doesn't have direct access to
instance state, so everything must go through FieldAccess API?
}
That's interesting. When operating with FieldSetter API or when calling
ObjectInputStream methods, one actually doesn't need an instance
context, since it is hidden behind the ObjectInputStream/FieldAccess
objects, so the @ReadObject method could be static, which would prevent
undesirable direct access to fields (finals in particular).
If this is primarily about checking invariants of stream field values, I
am working through a proposal for a static validator method and better
failure atomicity, and hope to have something to share soon.
Though, I think this is an orthogonal issue. Maybe FieldSetter can help
here, I'm not sure.
What is being proposed by the FieldSetter is a very simple low-level API
that addresses a long standing issue. Regardless of other changes to
Serialization, I think this proposal, as it stands, is good.
One thing you couldn't do this way is to check the invariants that
involve superclass' state that has already been deserialized.
This is a difficult problem.
But if you don't need that, this could be an alrernative readObject()
method. Very easy to implement, actually.
-Chris.
Regards, Peter
------------------------------
Message: 5
Date: Wed, 18 Mar 2015 11:06:56 +0000
From: Chris Hegarty<chris.hega...@oracle.com>
To: Alan Bateman<alan.bate...@oracle.com>, Peter Levart
<peter.lev...@gmail.com>
Cc: Core-Libs-Dev Libs<core-libs-dev@openjdk.java.net>
Subject: Re: RFR [9] 8071472: Add field access to support setting
final fields in readObject
Message-ID:<55095c50.3010...@oracle.com>
Content-Type: text/plain; charset=windows-1252; format=flowed
On 17/03/15 13:42, Alan Bateman wrote:
On 17/03/2015 12:21, Peter Levart wrote:
Hi Alan,
I agree that not calling defaultReadObject() from readObject() and
having a final field is potentially a bug. But need not be in case
some other means of setting final fields was used (Unsafe or
reflection). Some readObject() implementations in base module that
Chris changed to use new API fall into this category. We can't track
those usages, so to keep backwards compatibility, this checking has to
be opt-in. Is there a more elegant way to opt-in? A
@CheckFinalsAssignment annotation on the readObject() method?
I'm not sure that an annotation is right here. Instead then it might
work as a method on FieldSetter to enable strict checking.
Peter suggested a method on FieldSetter to enable strict checking before
too, and at the time I pushed back. After this discussion, I've come
full circle, and maybe this opt-in style method is a reasonable
compromise. Something like:
/**
* Checks that all final instance fields, declared by the class where
* the {@code readObject} callback is being invoked, have been set.
*
*<p> This method is intended to be called as a final step after all
* final instance fields have been set.
*
* @throws InvalidObjectException if one, or more, final instance
* fields have not been set
*/
void checkAllFinalsSet() throws InvalidObjectException;
...and the user code would look similar to this, from java.io.File:
s.fieldSetter().set("path", p)
.set("prefixLength", pLen)
.checkAllFinalsSet();
-Chris.
End of core-libs-dev Digest, Vol 95, Issue 54
*********************************************