You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@shiro.apache.org by dan <da...@bamlabs.com> on 2011/09/24 01:19:51 UTC
SimpleSession serialization
Hi --
In the writeObject() method of SimpleSession is a call to
out.defaultWriteObject() before each field is written out. This call to
defaultWriteObject() was causing exceptions for me (non-serializable, can't
serialize WeakHashMap) so it got me thinking...
My understanding is that defaultWriteObject() writes out the non-transient
fields, and is used if a class doesn't explicitly have its own writeObject()
method. Since writeObject() specifies exactly which fields to serialize, I
don't think this call is useful ... in fact, it would just make the
serialized stream bigger.
I took it out of my code and saw no ill effect from it.
Thanks,
Dan
--
View this message in context: http://shiro-user.582556.n2.nabble.com/SimpleSession-serialization-tp6826037p6826037.html
Sent from the Shiro User mailing list archive at Nabble.com.
Re: SimpleSession serialization
Posted by dan <da...@bamlabs.com>.
Hi Les,
I have read Josh Bloch's stuff and he is usually a good source. I don't
have this book, but I did run a simple test regarding this scenario. The
class basically serializes itself and reports the serialized size.
If out.defaultWriteObject() is in the code, then the size is 2079.
If out.defaultWriteObject() is commented out, then the size is 1056.
The class has a byte [1000] field which accounts for most of the size.
I think this demonstrates that out.defaultWriteObject() is causing a field
to be serialized twice. In Shiro, it makes the SimpleSession serialized
data twice as big and twice as slow as necessary.
Best,
Dan
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class TestSerialization implements Serializable
{
private final byte [] data = new byte[1000];
public static void main(String[] args)
{
TestSerialization ts = new TestSerialization();
try
{
System.out.println("Size=" + getSerializedSize(ts));
}
catch (IOException e) { }
}
private void writeObject(ObjectOutputStream out) throws IOException
{
out.defaultWriteObject();
out.write(data);
}
public static int getSerializedSize(Object obj) throws IOException {
// serialize the object..
final ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream oos = null;
int size = 0;
try
{
oos = new ObjectOutputStream(out);
oos.writeObject(obj);
final byte[] seralized = out.toByteArray();
size = seralized.length;
} finally {
try
{
if(oos != null) {
oos.close();
}
out.close();
} catch (IOException e) { }
}
return size;
}
}
--
View this message in context: http://shiro-user.582556.n2.nabble.com/SimpleSession-serialization-tp6826037p6832665.html
Sent from the Shiro User mailing list archive at Nabble.com.
Re: SimpleSession serialization - fields written twice
Posted by dan <da...@bamlabs.com>.
Hi --
Interesting... I have now read the section in Effective Java about
defaultWriteObject(). He states persuasively that its use enhances being
able to read in objects changed from version to version, say one with an
added field. If this is a benefit to Shiro (which I'm not sure about...),
then defaultWriteObject should be included. Otherwise, leaving it off and
fully controlling the serialization seems entirely reasonable. (I've done
this in the past a number of times without regret).
I'm glad to see good minds coming together!
Take care,
Dan
--
View this message in context: http://shiro-user.582556.n2.nabble.com/SimpleSession-serialization-tp6826037p6836555.html
Sent from the Shiro User mailing list archive at Nabble.com.
Re: SimpleSession serialization - fields written twice
Posted by Les Hazlewood <lh...@apache.org>.
Hi Andreas,
This was my suspicion as well after seeing Dan's findings: how the
size was exactly half after defaultWriteObject was removed. I'll make
that change asap.
Thanks for the notice!
Best regards,
Les
2011/9/27 Andreas Prieß <ap...@metaphysis.net>:
> Hi Les,
>
> I just had a look at the chapter about serialization in "Effective Java"
> to see what the rationale is about. As you mentioned
> defaultWriteObject() should be used, but the example in the book also
> clearly shows that all fields with customized serialization must not be
> serializable for the default mechanism executed by defaultWriteObject(),
> so they should normally be transient.
>
> The problem with shiros SimpleSession is that the fields are _not_
> marked transient and are therefore in fact written out twice.
>
> The solution should not be to remove defaultWriteObject() but to mark
> all the fields transient.
>
> (Looked at source checked out on 2011-09-06.)
>
>
> HTH,
>
> Andreas
>
>
> On 25.09.2011 20:02, Les Hazlewood wrote:
>> Wrt Java serialization, in.defaultReadObject() and
>> out.defaultWriteObject() should pretty much always be called as the
>> very first line in the readObject and writeObject implementations,
>> respectively.
>>
>> Josh Bloch covers this in his Effective Java book (2nd edition), page
>> 299. While too lengthy to repeat here, it boils down to ensuring the
>> class functions properly even as future modifications occur, as well
>> as for real security reasons.
>>
>> I can't comment as to whether or not your solution is fine for your
>> needs, but this explains the reason why they are in Shiro's current
>> implementation.
>>
>> Cheers,
>>
>> Les
>>
>> P.S. As an aside if anyone finds this next comment helpful, there are
>> two Java books that I have at my desk that are indispensable to me:
>> Josh Bloch's Effective Java (2nd edition) and Brian Goetz (et. al.)'s
>> Java Concurrency in Practice.
Re: SimpleSession serialization - fields written twice
Posted by Andreas Prieß <ap...@metaphysis.net>.
Hi Les,
I just had a look at the chapter about serialization in "Effective Java"
to see what the rationale is about. As you mentioned
defaultWriteObject() should be used, but the example in the book also
clearly shows that all fields with customized serialization must not be
serializable for the default mechanism executed by defaultWriteObject(),
so they should normally be transient.
The problem with shiros SimpleSession is that the fields are _not_
marked transient and are therefore in fact written out twice.
The solution should not be to remove defaultWriteObject() but to mark
all the fields transient.
(Looked at source checked out on 2011-09-06.)
HTH,
Andreas
On 25.09.2011 20:02, Les Hazlewood wrote:
> Wrt Java serialization, in.defaultReadObject() and
> out.defaultWriteObject() should pretty much always be called as the
> very first line in the readObject and writeObject implementations,
> respectively.
>
> Josh Bloch covers this in his Effective Java book (2nd edition), page
> 299. While too lengthy to repeat here, it boils down to ensuring the
> class functions properly even as future modifications occur, as well
> as for real security reasons.
>
> I can't comment as to whether or not your solution is fine for your
> needs, but this explains the reason why they are in Shiro's current
> implementation.
>
> Cheers,
>
> Les
>
> P.S. As an aside if anyone finds this next comment helpful, there are
> two Java books that I have at my desk that are indispensable to me:
> Josh Bloch's Effective Java (2nd edition) and Brian Goetz (et. al.)'s
> Java Concurrency in Practice.
>
Re: SimpleSession serialization
Posted by Les Hazlewood <lh...@apache.org>.
Hi Dan,
Wrt Java serialization, in.defaultReadObject() and
out.defaultWriteObject() should pretty much always be called as the
very first line in the readObject and writeObject implementations,
respectively.
Josh Bloch covers this in his Effective Java book (2nd edition), page
299. While too lengthy to repeat here, it boils down to ensuring the
class functions properly even as future modifications occur, as well
as for real security reasons.
I can't comment as to whether or not your solution is fine for your
needs, but this explains the reason why they are in Shiro's current
implementation.
Cheers,
Les
P.S. As an aside if anyone finds this next comment helpful, there are
two Java books that I have at my desk that are indispensable to me:
Josh Bloch's Effective Java (2nd edition) and Brian Goetz (et. al.)'s
Java Concurrency in Practice.
--
Les Hazlewood
CTO, Katasoft | http://www.katasoft.com | 888.391.5282
twitter: @lhazlewood | http://twitter.com/lhazlewood
katasoft blog: http://www.katasoft.com/blogs/lhazlewood
personal blog: http://leshazlewood.com
On Fri, Sep 23, 2011 at 4:19 PM, dan <da...@bamlabs.com> wrote:
> Hi --
>
> In the writeObject() method of SimpleSession is a call to
> out.defaultWriteObject() before each field is written out. This call to
> defaultWriteObject() was causing exceptions for me (non-serializable, can't
> serialize WeakHashMap) so it got me thinking...
>
> My understanding is that defaultWriteObject() writes out the non-transient
> fields, and is used if a class doesn't explicitly have its own writeObject()
> method. Since writeObject() specifies exactly which fields to serialize, I
> don't think this call is useful ... in fact, it would just make the
> serialized stream bigger.
>
> I took it out of my code and saw no ill effect from it.
>
> Thanks,
> Dan
>
> --
> View this message in context: http://shiro-user.582556.n2.nabble.com/SimpleSession-serialization-tp6826037p6826037.html
> Sent from the Shiro User mailing list archive at Nabble.com.