[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 <firstname.lastname@example.org>
> Newsgroups: comp.lang.java.machine
> Subject: Re: String/Integer/etc. final why?
> "Stuart D. Gathman" wrote:
>> In article <email@example.com>, "Pat
>> LaVarre" <firstname.lastname@example.org> wrote:
>>> I think I see that making String a class rather than an interface
>>> 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
>> existing methods final, the security requirements would (probably) be
>> (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
> i.e. without copying if the char is not shared. That is implemented
> 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
> 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
> time to do that myself, but if anyone else wants to prepare one, I'd be
> happy to look over it for security problems.