> You correctly state that the attack only works for "trusted immutable
> classes" (e.g., String). We agree that the current String implementation
> would not withstand such an attack under a weak memory model. You say
> (roughly speaking) "we could add one or two hideous access modifiers that
> ordinary programmers won't understand, or change the semantics of current
> modifiers, so experts will be able to write secure immutable classes."
I continue to think that rather than define `immutable', the spec
should just describe the memory effects of `final' that support its
semantics. In fact, the more I think about it, the more I think that
these ARE just integral aspects of the semantics of final, but that
they were not carefully enough stated in JLS, in part because `blank
finals' were introduced after JLS came out.
Can anyone think of a non-performance-based story about why final
fields should ever be read, even by current (constructing) thread
before they receive their values? Or why multiple assignments should
ever be allowed?
(If not, then `final volatile' is superfluous, right?)
Not that it much helps the VM folks, but the rules surrounding final
could be further strengthened to help people get this right, and to
avoid some of the bad scenarios that Bill mentioned:
* Disallow escape of `this' before assignment to finals in constructors.
Adding this to the usual rules surrounding finals:
* Disallow reads of finals before writes, even in constructors.
* Disallow multiple writes to finals in constructors.
This would still be fairly easy to conservatively check during
classloading too. The associated JMM rules would need to somehow
disable reorderings that defeat the checks.
(BTW, if I could be accused of inventing anything about Java, it would
be blank finals (which were introduced along with inner classes). So
it is my lapse as much as anyone else's that these were not specified
carefully enough. If I had appreciated publication-before-assignment
problems, the above rule probably would have been in the
inner-class/blank-final document to begin with.)
One common but dangerous practice that stronger Java-level rules would
help prevent is definition of constructors that bind AWT/Swing event
listeners before all final fields are initialized.
These strengthenings would also simplify Bill's proposed:
> Note that this doesn't conflict with the other ideas we suggested
> about final or final volatile fields never being stale. What we could
> say is something like:
> * When a thread reads a final (or perhaps a volatile final) field,
> then value it reads must reflect all writes to that field at the time
> the object was published; Furthermore, it is legal for a thread to
> reuse the value of a final field, even if memory barriers intervene.
> Thus, the weak memory model can be exploited by an attacker to corrupt a
> class that expects reasonable behavior from its immutable input arguments.
> Simply put, it is not uncommon for one class to depend on the guaranteed
> behavior of another class (e.g., the immutability of a String) for its
> security. That is why I think it's absolutely intolerable to allow
> ill-formed objects to be visible to a thread, even if the thread does not
> perform adequate synchronization.
The initialization-safety-guarantee-only-for-finals story would then
go: If your life depends on lack of change after initialization,
declare it final.
Is this too much to ask? The String *class* is already declared as
final for similar reasons.
> > 790 are marked as final
> > For the fields not marked as final but that could be,
> > there are modified in constructors but nowhere else
> > (although I didn't check native code).
> FYI, at least two fields marked as final (System.out and System.err) are
> actually changed by native code. This is a known bug, but I don't think it
> has been addressed.
> I second Paul's comments about the lack of use of final - the compilers
> have been far too buggy to use final seriously/properly. I doubt that there
> is much motivation (or available resource) within Javasoft to go back
> through and fix this, especially when considering backward compatibility
> with old VM's.
Also, Outer.this of an inner class is implicitly final.
> I checked, and all of the benchmarks I tried, I only
> found a handfull of fields marked volatile:
While not widely used in the sorts of classes found in JDK, volatile
IS used heavily in certain styles of parallel programming that
otherwise don't need much synchronization.
-- Doug Lea, Computer Science Department, SUNY Oswego, Oswego, NY 13126 USA email@example.com 315-341-2688 FAX:315-341-5424 http://gee.cs.oswego.edu/ ------------------------------- This is the JavaMemoryModel mailing list, managed by Majordomo 1.94.4.
To send a message to the list, email JavaMemoryModel@cs.umd.edu To send a request to the list, email firstname.lastname@example.org and put your request in the body of the message (use the request "help" for help). For more information, visit http://www.cs.umd.edu/~pugh/java/memoryModel
This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:17 EDT