Other |
---|
5.0 b51Fixed |
Duplicate :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
Date: Thu, 06 May 2004 13:50:58 -0400 From: <###@###.###> Background: JSR133 requires that all fields of classes that are specified to be immutable must be declared as "final". This solves a long-standing issue in the memory semantics of Java that was not addressed in the original JLS. The presense of "final" in such cases is more than a decoration. It causes the compiler and hardware to not reorder critical instructions in a way that could cause one thread to "catch" an immutable object in the course of construction, and thus see its pre-construction (0/null) value instead of its actual final value. This is not just a theoretical possibility; without the use of "final", this can and does occur regularly on multiprocessors. A further discussion with examples of how this may induce security holes may be found at http://www.cs.umd.edu/users/pugh/java/memoryModel/jsr-133-faq.html#finalWrong As part of JSR133, the expert group surveyed all classes in java.lang and java.util, to find those that required field declarations be marked as "final" to meet their specs. This was then done as bug 4998264. While this is all fine, the JSR133 group did not address (or anticipate the consequences of) a known interaction between "final" and code that does "manual" deserialization, such as the XML serialization in appServer: It is impossible to reflectively assign a value to a final field. Thus, appServer broke. This might be indicative of other similar code out there also being broken. While it might be deal with this by undoing some of the "finals" in 4998264, this would be a crummy alternative in two senses: (1) It merely delays the day of reckoning for dealing with the underlying problem (2) People writing multithreaded code will be relying on immutability guarantees that are not actually supported, so will encounter extremely difficult to locate bugs. Proposal: Allow reflective set-field operations on any final field f, ONLY if f.setAccessible(true) succeeds. Advantages: 1. appServer will actually work. (Not just sort-of work, as true even when using 1.4.x). Any other similar code out there that bothers to do explicit setAccessible calls before setting fields will similarly work. 2. In some limited circumstances, this technique can be used in a serializable class's custom readObject method to initialize final fields upon deserialization directly (rather than through defaultReadObject). Note that because of the permission requirement, this only applies to highly trusted code; it is not a general solution. 3. No API change. It only requires addition of one new sentence in the javadocs to describe the case when setting final is allowed. 4. By requiring the setAccessible check EVEN if the field is public, there is essentially no possibility of accidental misuse. 5. If you have permission to suppress all access checks, then you can, among other things change the security manager, so there is no additional security risk here. 6. Bill Pugh and I can/will adjust the JSR133 spec to add the appropriate wording about resulting multithreaded semantics. 7. There is almost no impact on plans to further optimize final fields in the future inside hotspot. 8. And mainly: I think this is the simplest solution that actually works. Disadvantages: 1. While the changes are straightforward, there are more lines of them than anyone wants to see at this point. 2. If people use this in inappropriate contexts (i.e., in situations not related to object reconstruction or deserialization) their programs will make no sense.
|