Explicit Serialization API and Security
peter.firmstone at zeus.net.au
Tue Jan 13 00:51:09 UTC 2015
----- Original message -----
> On 10/01/15 07:00, Peter Firmstone wrote:
> > Again, thank you all for engaging in discussion of this very difficult
> > topic.
> > While we can't presently check intra object dependencies during
> > deserialization with readObject(), the examples I provide can do this.
> I have replied to Davids mail with a small change to GetField ( added
> superTypeFields() ) to return the deserialized supertypes fields. This
> gives subtypes the ability to check values of the supertypes persistent
Unfortunately this breaks encapsulation, a class is then locked into
using that serial form as public api forever.
> As with your original proposal, it is limited to the persistent state as
> read off the stream, and not the transient state, but I think it gets us
> most of the way there.
> In your original proposal, it looks quite cumbersome to hook up the
> static validator method in the constructor hierarchy ( as it is to do
> this with standard constructors too ). It also relies on the fact that
> the subtype has to create an instance of the supertype. I just wonder if
> we can push on the alternative static validator proposal to come up with
> something a but more attractive ( maybe not! ).
Before proposing the constructor, I had considered a static validator
method, with the following limitations:
* A static method invariant check, while simple, cannot accommodate
intra object invariants in class inheritance hierarchies without
breaking encapsulation and allowing child classes to examine stream
* When we break encapsulation, complexity of implementing Serializable
safely increases; how to evolve serial form without breaking
* An Object under construction, usually copies mutable parameters
before checking invariants, how can we guarantee that these objects
are not shared and haven't mutated between the time the invariants
are checked and when fields are set by reflection after
I'd also considered a static factory method:
* It offers maximum flexibility for evolution; it can return objects
of any class it likes.
* Lacks the ability to recreate inherited private state, without
* Issues establishing intra object dependencies in inheritance
Advantages that led me to propose the use of a constructor:
* If existing constructors throw an exception when invariants
haven't been satisfied, best practise dictates they must
do so prior to calling Object's super class constructor to avoid
finalizer attacks; static validation methods should already exist,
if not the class should be refactored anyway, whether it implements
Serializable or not.
* Improved code reuse; invariant validation code is shared with
* Ability to satisfy complex intra object invariants in class
inheritance heirarchies without breaking encapsulation.
* Although it appears complex at first glance, once learnt,
it's easily proven, preserves encapsulation and is easy to
implement and test.
* No serial form lock in, encapsulation has not been broken.
Only the implementing class knows and uses the field names and types
It just seems like the best compromise, it's not perfect, is has less flaws.
> Have you seen the changes I proposing for failure atomicity, preliminary
> .. and I think we can go further than this, creating the containing
> object lazily, if there are no readObjectXXX methods in the hierarchy.
Yes, but need some more time to absorb it, before commenting.
More information about the core-libs-dev