[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: the benefits of immutability




On Tuesday, August 19, 2003, at 04:09  PM, Perry E. Metzger wrote:
> Sure, but my point is that everything in sight (see StringBuffer,
> which is pretty obviously mutable) was made final by Java's designers,
> on the premise, presumably, that they knew everything you would ever
> want such an object to do.

Okay, I found a old usenet posting explaining why StringBuffer is final 
-- it's for security:

> Message-ID: <3BC4FE13.AA7333D4@zetnet.co.uk>
> Date: Thu, 11 Oct 2001 03:04:03 +0100
> From: David Hopwood <david.hopwood@zetnet.co.uk>
> Newsgroups: comp.lang.java.machine
> Subject: Re: String/Integer/etc. final why?
>
> "Stuart D. Gathman" wrote:
>> In article <2695edf1.0110100937.61cf0635@posting.google.com>, "Pat
>> LaVarre" <ppaatt@aol.com> wrote:
>>
>>> I think I see that making String a class rather than an interface 
>>> frees
>>> security-conscious classes from the work of converting their String
>>> parameters to ImmutableString's.
>>>
>>> But I don't see the point of making the String class final.
>>
>> An extended String class could contain mutable fields.  By decalring 
>> all
>> existing methods final, the security requirements would (probably) be 
>> met
>> (since these methods could never access any additional mutable 
>> fields) -
>> but it is simpler and safer to make the whole class final.
>>
>> The class we should, however,  be able to extend is StringBuffer.  
>> Why is
>> StringBuffer final???
>
> StringBuffer needs to be able to convert itself to a String 
> efficiently,
> i.e. without copying if the char[] is not shared. That is implemented 
> by
> having a package-access method in String that is called by
> StringBuffer.toString(). If StringBuffer were non-final and its fields
> were protected, say, then this wouldn't work, because it would never be
> possible to guarantee that the char[] is not shared with untrusted 
> code.
>
> However, it would be possible to securely make StringBuffer non-final
> (in a way that doesn't completely cripple its interface to subclasses)
> by doing something like the following:
>
>  - make all fields private (not protected).
>  - add a flag 'do_not_share' (initially false).
>  - in order to allow subclasses to get at the char[], add a protected
>    method getInternalArray that does the following:
>      copy the char[] if it is shared with a String.
>      set the do_not_share flag.
>      return the char[] (the new one, if it was copied).
>
>  - change toString() so that it copies the char[] first if do_not_share
>    is set.
>  - some of the methods need to be made final - at least toString and
>    getInternalArray, and possibly others.
>  - think about potential race conditions a lot more thoroughly than
>    I have time to do now.
>
> In any case, getting this right is more complicated than it looks.
> ISTR that Sun did at one point (in a beta version?) attempt to make
> StringBuffer non-final, and they introduced a security bug as a result.
> In the next version StringBuffer was final again.
>
> It would be worth submitting the above as an RFE, I think. I haven't 
> got
> time to do that myself, but if anyone else wants to prepare one, I'd be
> happy to look over it for security problems.