RFR [9] 8071472: Add field access to support setting final fields in readObject
Chris Hegarty
chris.hegarty at oracle.com
Thu Mar 19 15:49:16 UTC 2015
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.hegarty at oracle.com>
>>> To: Alan Bateman<Alan.Bateman at oracle.com>, Peter Levart
>>> <peter.levart at gmail.com>
>>> Cc: Core-Libs-Dev Libs<core-libs-dev at openjdk.java.net>
>>> Subject: Re: RFR [9] 8071472: Add field access to support setting
>>> final fields in readObject
>>> Message-ID:<55095C50.3010605 at 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
>>> *********************************************
>>
>
More information about the core-libs-dev
mailing list