You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jcs-users@jakarta.apache.org by Travis Savo <ts...@IFILM.com> on 2004/05/23 00:15:42 UTC

RE: Why the caching API should use Serializable rather than Objec t

While I absolutely agree with the principle of defensive coding, the use of
protected and private keywords to denote fields in a class which are not
meant to be touched by clients of the class, the invariant pattern in
general (constructor only with no public setter being the most common way to
implement this... java.lang.String is an excellent example), and the
potential for Bad Things(tm) to happen when the invariant pattern is not
observed religiously when dealing with Sets and Maps, I'm not following the
Object vs. Serializable argument being made here.

A Serializable object is not inherently an invariant. Serializable's only
contract is that ALL fields, public or otherwise, must be either primitives,
Serializable themselves, or 'transient'.

The original reasoning (and this is merely conjecture on my part so don't
take this as law) for using Serializable as the interface was that any cache
which did anything more than store references in memory would use this
interface, and the contract supplied by it to ensure that an object could be
captured in a deconstructable form for the purpose of moving 'outside the
VM' with it... whatever that form may take (Byte stream, XML document, etc.)

The reasoning for removing this dependency was that all caches don't need it
(specifically memory based caches) and that those who did need it would
enforce this dependency themselves.

The need for the invariant still exists, but to the best of my
understanding, the Serializable interface NEVER provided that contract.

I'm sure I'm missing something (obvious or otherwise), so could you please
elaborate on your reasoning?

Thank you!

-Travis Savo <ts...@ifilm.com>


-----Original Message-----
From: Hanson Char [mailto:hanson_char@yahoo.com]
Sent: Saturday, May 22, 2004 5:39 AM
To: 'Turbine JCS Users List'
Subject: Why the caching API should use Serializable rather than Object


Quoted from Item 24 of Effective Java by Joshua Bloch:

"You must program defensively with the assumption that clients of your class
will do their best to destroy its invariants."

"...if you are considering using a client-provided object reference as an
element in an internal Set instance or as a key in an internal Map instance,
you should be aware that the invariants of the set or map would be destroyed
if the object were modified after it were inserted."

This principle/rule is generally violated in JCS for the use of Object in
the method signature.

Hanson


---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-jcs-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-jcs-user-help@jakarta.apache.org

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-jcs-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-jcs-user-help@jakarta.apache.org


RE: Why the caching API should use Serializable rather than Object

Posted by Hanson Char <ha...@yahoo.com>.
I think you are going in the right direction.  Item 37 is also worth reading
on performance optimization.

For the key, maybe the API be simplified to only allow String, so it becomes
immutable and pratically it's easy for any client to specify a string
representation of a key which also serves as an insanity check of exactly
what the client is try to do.  Yet if this is the case, it's almost the same
as requiring the more flexible Serializable (or in generics term <K extends
Serializable>) for the key, as String is Serializable and if the client
chose to use String as the key the caching system can detect and safely skip
the copy.

For the data part, it's the same old suggestion.

Hanson

-----Original Message-----
From: Aaron Smuts [mailto:aasmuts@wisc.edu]
Sent: Monday, 24 May 2004 2:43 AM
To: 'Turbine JCS Users List'
Subject: RE: Why the caching API should use Serializable rather than
Object


I've been thinking about Bloch's item 24.  (I haven't finished the book yet,
but so far it is definitely one of the best books on Java I've seen.  Thanks
for the recommendation.)  One big worry is with mutable keys.  If someone
uses a mutable object as a key and monkey with it after putting it in the
cache, then we could have a temporary problem.   However, I'm not sure that
the cache should make defensive copies of objects, given the performance
problems that might result.    Right now there should be a contract between
users of the cache and JCS that objects put into the cache will not be
modified, only copies of such objects, which should then be put into the
cache if any modification results.    As it is, the cache does not guard
against user error.  I can get an item and then using the reference, change
everything in the retrieved object.  Subsequent gets will then get my
changes.  If someone changes an object in order to do an update to the db,
and the update fails, then the cache has changes that are not reflected in
the underlying datastore.  All changes should be made on copies. . . .
Nevertheless, since puts are asynchronous, we might be able to implement
some kind of defensive copying.  I don't have a good solution right now.
What do you suggest?  Aaron

> -----Original Message----- > From: Hanson Char
[mailto:hanson_char@yahoo.com] > Sent: Sunday, May 23, 2004 12:42 AM > To:
'Turbine JCS Users List' > Subject: RE: Why the caching API should use
Serializable rather than > Object >  > It's an old reasoning.  Any mutable
object put into a cache is a time- > bomb. > Not only is it not thread-safe
for clients using the cache, they also can > "destroy" the invariants of the
map used in the caching system, > inadvertantly by clients who have
references to the mutable objects. >  > The only way to avoid such problem
is to defensively make copies of > objects > mutable (ie non-string,
non-integer, etc) before saving to and/or > retrieving > from the cache. >
> The Cloneable interface is a failure (again according to Effective Java by
> Joshua Bloch) so it's out of consideration.  To my knowledge, the >
Serializable interface is left as the only means to allow the caching >
system > to ever possibly make such defensive copies.  The Serializable
interface > certainly comes with it's own cost and cannot be taken
light-heartedly, > but > the alternative is a violation of Item 24. >  >
Hanson >  > -----Original Message----- > From: Travis Savo
[mailto:tsavo@IFILM.com] > Sent: Sunday, 23 May 2004 8:16 AM > To: 'Turbine
JCS Users List' > Subject: RE: Why the caching API should use Serializable
rather than > Object >  >  > While I absolutely agree with the principle of
defensive coding, the use > of > protected and private keywords to denote
fields in a class which are not > meant to be touched by clients of the
class, the invariant pattern in > general (constructor only with no public
setter being the most common way > to > implement this... java.lang.String
is an excellent example), and the > potential for Bad Things(tm) to happen
when the invariant pattern is not > observed religiously when dealing with
Sets and Maps, I'm not following > the > Object vs. Serializable argument
being made here.  A Serializable object > is > not inherently an invariant.
Serializable's only contract is that ALL > fields, public or otherwise, must
be either primitives, Serializable > themselves, or 'transient'.  The
original reasoning (and this is merely > conjecture on my part so don't take
this as law) for using Serializable as > the interface was that any cache
which did anything more than store > references in memory would use this
interface, and the contract supplied > by > it to ensure that an object
could be captured in a deconstructable form > for > the purpose of moving
'outside the VM' with it... whatever that form may > take (Byte stream, XML
document, etc.)  The reasoning for removing this > dependency was that all
caches don't need it (specifically memory based > caches) and that those who
did need it would enforce this dependency > themselves.  The need for the
invariant still exists, but to the best of > my > understanding, the
Serializable interface NEVER provided that contract. > I'm > sure I'm
missing something (obvious or otherwise), so could you please > elaborate on
your reasoning?  Thank you!  -Travis Savo <ts...@ifilm.com> >
 > -----Original Message----- From: Hanson Char >
[mailto:hanson_char@yahoo.com] > Sent: Saturday, May 22, 2004 5:39 AM To:
'Turbine JCS Users List' Subject: > Why the caching API should use
Serializable rather than Object Quoted > from > Item 24 of Effective Java by
Joshua Bloch:  "You must program defensively > with the assumption that
clients of your class will do their best to > destroy > its invariants."
"...if you are considering using a client-provided > object > reference as
an element in an internal Set instance or as a key in an > internal Map
instance, you should be aware that the invariants of the set > or > map
would be destroyed if the object were modified after it were > inserted." >
This principle/rule is generally violated in JCS for the use of Object in >
the method signature. >
anson ------------------------------------------------------------------
> -- > - To unsubscribe, e-mail:
turbine-jcs-user-unsubscribe@jakarta.apache.org > For additional commands,
e-mail: >
urbine-jcs-user-help@jakarta.apache.org ---------------------------------
> -- > ---------------------------------- To unsubscribe, e-mail: >
turbine-jcs-user-unsubscribe@jakarta.apache.org For additional commands, >
e-mail: turbine-jcs-user-help@jakarta.apache.org >  >
 > --------------------------------------------------------------------- >
To unsubscribe, e-mail: turbine-jcs-user-unsubscribe@jakarta.apache.org >
For additional commands, e-mail:
rbine-jcs-user-help@jakarta.apache.org   -----------------------------------
---------------------------------- To unsubscribe, e-mail:
turbine-jcs-user-unsubscribe@jakarta.apache.org For additional commands,
e-mail: turbine-jcs-user-help@jakarta.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-jcs-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-jcs-user-help@jakarta.apache.org


RE: Why the caching API should use Serializable rather than Object

Posted by Aaron Smuts <aa...@wisc.edu>.
I've been thinking about Bloch's item 24.  (I haven't finished the book
yet, but so far it is definitely one of the best books on Java I've
seen.  Thanks for the recommendation.)

One big worry is with mutable keys.  If someone uses a mutable object as
a key and monkey with it after putting it in the cache, then we could
have a temporary problem. 

However, I'm not sure that the cache should make defensive copies of
objects, given the performance problems that might result.  

Right now there should be a contract between users of the cache and JCS
that objects put into the cache will not be modified, only copies of
such objects, which should then be put into the cache if any
modification results.  

As it is, the cache does not guard against user error.  I can get an
item and then using the reference, change everything in the retrieved
object.  Subsequent gets will then get my changes.  If someone changes
an object in order to do an update to the db, and the update fails, then
the cache has changes that are not reflected in the underlying
datastore.  All changes should be made on copies. . . .

Nevertheless, since puts are asynchronous, we might be able to implement
some kind of defensive copying.  I don't have a good solution right now.
What do you suggest?

Aaron


> -----Original Message-----
> From: Hanson Char [mailto:hanson_char@yahoo.com]
> Sent: Sunday, May 23, 2004 12:42 AM
> To: 'Turbine JCS Users List'
> Subject: RE: Why the caching API should use Serializable rather than
> Object
> 
> It's an old reasoning.  Any mutable object put into a cache is a time-
> bomb.
> Not only is it not thread-safe for clients using the cache, they also
can
> "destroy" the invariants of the map used in the caching system,
> inadvertantly by clients who have references to the mutable objects.
> 
> The only way to avoid such problem is to defensively make copies of
> objects
> mutable (ie non-string, non-integer, etc) before saving to and/or
> retrieving
> from the cache.
> 
> The Cloneable interface is a failure (again according to Effective
Java by
> Joshua Bloch) so it's out of consideration.  To my knowledge, the
> Serializable interface is left as the only means to allow the caching
> system
> to ever possibly make such defensive copies.  The Serializable
interface
> certainly comes with it's own cost and cannot be taken
light-heartedly,
> but
> the alternative is a violation of Item 24.
> 
> Hanson
> 
> -----Original Message-----
> From: Travis Savo [mailto:tsavo@IFILM.com]
> Sent: Sunday, 23 May 2004 8:16 AM
> To: 'Turbine JCS Users List'
> Subject: RE: Why the caching API should use Serializable rather than
> Object
> 
> 
> While I absolutely agree with the principle of defensive coding, the
use
> of
> protected and private keywords to denote fields in a class which are
not
> meant to be touched by clients of the class, the invariant pattern in
> general (constructor only with no public setter being the most common
way
> to
> implement this... java.lang.String is an excellent example), and the
> potential for Bad Things(tm) to happen when the invariant pattern is
not
> observed religiously when dealing with Sets and Maps, I'm not
following
> the
> Object vs. Serializable argument being made here.  A Serializable
object
> is
> not inherently an invariant. Serializable's only contract is that ALL
> fields, public or otherwise, must be either primitives, Serializable
> themselves, or 'transient'.  The original reasoning (and this is
merely
> conjecture on my part so don't take this as law) for using
Serializable as
> the interface was that any cache which did anything more than store
> references in memory would use this interface, and the contract
supplied
> by
> it to ensure that an object could be captured in a deconstructable
form
> for
> the purpose of moving 'outside the VM' with it... whatever that form
may
> take (Byte stream, XML document, etc.)  The reasoning for removing
this
> dependency was that all caches don't need it (specifically memory
based
> caches) and that those who did need it would enforce this dependency
> themselves.  The need for the invariant still exists, but to the best
of
> my
> understanding, the Serializable interface NEVER provided that
contract.
> I'm
> sure I'm missing something (obvious or otherwise), so could you please
> elaborate on your reasoning?  Thank you!  -Travis Savo
<ts...@ifilm.com>
> 
> -----Original Message----- From: Hanson Char
> [mailto:hanson_char@yahoo.com]
> Sent: Saturday, May 22, 2004 5:39 AM To: 'Turbine JCS Users List'
Subject:
> Why the caching API should use Serializable rather than Object
Quoted
> from
> Item 24 of Effective Java by Joshua Bloch:  "You must program
defensively
> with the assumption that clients of your class will do their best to
> destroy
> its invariants."  "...if you are considering using a client-provided
> object
> reference as an element in an internal Set instance or as a key in an
> internal Map instance, you should be aware that the invariants of the
set
> or
> map would be destroyed if the object were modified after it were
> inserted."
> This principle/rule is generally violated in JCS for the use of Object
in
> the method signature.
> anson
------------------------------------------------------------------
> --
> - To unsubscribe, e-mail:
turbine-jcs-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail:
> urbine-jcs-user-help@jakarta.apache.org
---------------------------------
> --
> ---------------------------------- To unsubscribe, e-mail:
> turbine-jcs-user-unsubscribe@jakarta.apache.org For additional
commands,
> e-mail: turbine-jcs-user-help@jakarta.apache.org
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail:
turbine-jcs-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail:
turbine-jcs-user-help@jakarta.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-jcs-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-jcs-user-help@jakarta.apache.org


RE: Why the caching API should use Serializable rather than Object

Posted by Hanson Char <ha...@yahoo.com>.
It's an old reasoning.  Any mutable object put into a cache is a time-bomb.
Not only is it not thread-safe for clients using the cache, they also can
"destroy" the invariants of the map used in the caching system,
inadvertantly by clients who have references to the mutable objects.

The only way to avoid such problem is to defensively make copies of objects
mutable (ie non-string, non-integer, etc) before saving to and/or retrieving
from the cache.

The Cloneable interface is a failure (again according to Effective Java by
Joshua Bloch) so it's out of consideration.  To my knowledge, the
Serializable interface is left as the only means to allow the caching system
to ever possibly make such defensive copies.  The Serializable interface
certainly comes with it's own cost and cannot be taken light-heartedly, but
the alternative is a violation of Item 24.

Hanson

-----Original Message-----
From: Travis Savo [mailto:tsavo@IFILM.com]
Sent: Sunday, 23 May 2004 8:16 AM
To: 'Turbine JCS Users List'
Subject: RE: Why the caching API should use Serializable rather than
Object


While I absolutely agree with the principle of defensive coding, the use of
protected and private keywords to denote fields in a class which are not
meant to be touched by clients of the class, the invariant pattern in
general (constructor only with no public setter being the most common way to
implement this... java.lang.String is an excellent example), and the
potential for Bad Things(tm) to happen when the invariant pattern is not
observed religiously when dealing with Sets and Maps, I'm not following the
Object vs. Serializable argument being made here.  A Serializable object is
not inherently an invariant. Serializable's only contract is that ALL
fields, public or otherwise, must be either primitives, Serializable
themselves, or 'transient'.  The original reasoning (and this is merely
conjecture on my part so don't take this as law) for using Serializable as
the interface was that any cache which did anything more than store
references in memory would use this interface, and the contract supplied by
it to ensure that an object could be captured in a deconstructable form for
the purpose of moving 'outside the VM' with it... whatever that form may
take (Byte stream, XML document, etc.)  The reasoning for removing this
dependency was that all caches don't need it (specifically memory based
caches) and that those who did need it would enforce this dependency
themselves.  The need for the invariant still exists, but to the best of my
understanding, the Serializable interface NEVER provided that contract.  I'm
sure I'm missing something (obvious or otherwise), so could you please
elaborate on your reasoning?  Thank you!  -Travis Savo <ts...@ifilm.com>

-----Original Message----- From: Hanson Char [mailto:hanson_char@yahoo.com]
Sent: Saturday, May 22, 2004 5:39 AM To: 'Turbine JCS Users List' Subject:
Why the caching API should use Serializable rather than Object   Quoted from
Item 24 of Effective Java by Joshua Bloch:  "You must program defensively
with the assumption that clients of your class will do their best to destroy
its invariants."  "...if you are considering using a client-provided object
reference as an element in an internal Set instance or as a key in an
internal Map instance, you should be aware that the invariants of the set or
map would be destroyed if the object were modified after it were inserted."
This principle/rule is generally violated in JCS for the use of Object in
the method signature.
anson   --------------------------------------------------------------------
- To unsubscribe, e-mail: turbine-jcs-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail:
urbine-jcs-user-help@jakarta.apache.org  -----------------------------------
---------------------------------- To unsubscribe, e-mail:
turbine-jcs-user-unsubscribe@jakarta.apache.org For additional commands,
e-mail: turbine-jcs-user-help@jakarta.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-jcs-user-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-jcs-user-help@jakarta.apache.org