Re: JavaMemoryModel: Mutually exclusive goals for Java memory model

From: Cliff Click (Cliff.Click@sun.com)
Date: Thu Apr 04 2002 - 12:59:16 EST


This only happens when the underlying char array is exported to another
thread
prior to being converted into a String. Can we just get away with
stating that
this is another instance of 'escaping prior to end of the constructor',
claim
it's bad programming practice, remove the guarentees and leave it at that?

I.e., the new JMM spec says something along the lines of: if you allow
another
thread unsync'd access to the innards of an object you are constructing,
either
by exporting the object itself or any of it's subparts, prior to the end
of the
constructor then final's are not guarenteed to not change in the other
thread.

We then remove some (but not all) safety guarentees from Strings and maybe
Sun needs to walk through the security codes and make sure passed-in Strings
are either copied, OR: the codes do not attempt to prove aliasing facts
between unknown char arrays and sensitive Strings (surely they do not!).
Hence no security hole by this approach.

Cliff

Bill Pugh wrote:
> OK, we have figured out that two of the goals for the Java memory model
> are mutually exclusive in any reasonable memory model
>
> * Goal 1: Make the existing Sun JDK code for StringBuffers and String
> thread
> safe by changing the fields of String to final. In the existing code,
> all StringBuffer methods are synchronized, and there is a boolean
> that says whether the backing char[] is read only. When a StringBuffer
> is turned into a String, the String reuses the existing char [],
> but the StringBuffer now knows that the char[] is read only, and
> does a copy on write if needed.
>
> * Goal 2: Allow the compiler to do standard compiler optimization
> techniques.
>
> Specifically, the compiler should be able to transform:
>
>
> Point p1 = Foo.p;
> int x1 = p1.x;
> Point p2 = Foo.p;
> if (p1 == p2) {
> int x2 = p2.x;
> ...
> }
>
> into
>
> Point p1 = Foo.p;
> int x1 = p1.x;
> Point p2 = Foo.p;
> if (p1 == p2) {
> int x2 = x1;
> ...
> }
>
> More generally, assume that within a thread there are
> two reads, r1 and r2, of the same variable v (i.e., reads of the same
> heap memory location; a field or an array element). Unless there is
> some
> kind of synchronization between r1 and r2 that would force v to be
> reloaded, Cliff wants full freedom to reuse the value of r1 for the
> value of r2. Since synchronization never forces a final field to be
> reloaded, he should always be able to do this reuse of v is final.
>
> OK, these goals are mutually exclusive in any reasonable memory model.
> Consider an example that shows the effect of the behavior allowed by
> goal 2:
>
> Initially,
>
> Foo.sb = new StringBuffer("a");
> Foo.s = null
>
> Thread 1
> StringBuffer sb1 = Foo.sb;
> char c1a = sb1.charAt(0); // sees 'a'
> String s1b = Foo.s;
> char c1b = s1b.charAt(0); // might see 'a' or 'b', or throw null pointer
> char c1c = s1b.charAt(0); // might see 'a' or 'b'
>
> Thread 2
> StringBuffer sb2 = Foo.sb;
> sb2.setCharAt(0,'b');
> Foo.s = new String(sb2);
>
> The problem is that the char[] backing the StringBuffer is visible to
> Thread 1 before it is turned into a String by thread 2 and the 3 charAt
> calls in thread 1 all access the same variable: the first element of the
> character array used in both the StringBuffer and the String. Since
> there is no synchronization, the value of c1a can be reused for c1b and
> c1c.
>
> For the transformation Cliff wants to do, the user program compared p1
> and p2, allowing the compiler to reason that p1.x and p2.x referred to
> the same memory location. However, I am not willing to let comparing two
> registers have semantics in the memory model; it is just too ugly.
>
>
> OK, if we abandon goal 1, then in the general case we will force copying
> when we convert from a StringBuffer into a String. On the other hand, we
> will be able to get rid of the synchronization in StringBuffer. In
> special cases where we can determine that the StringBuffer hasn't
> leaked, we might be able to avoid the copying.
>
> Cliff has been talking about the advantages of an VM implementation in
> which the char's of a String are always inlined. However, this
> implementation would also force copying for substring operations.
>
>
> So we need to decide what to do. We bent over backwards trying to
> handle the existing StringBuffer code. We now see that we may have bent
> over too far. I can make the memory model go either way, we just need to
> decide what we want to do here.
>
> Bill
> -------------------------------
> JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel

-- 
Dr. Cliff Click      Chief Architect, HotSpot Server  Sun Microsystems, Inc.
Cliff.Click@Sun.COM  Senior Staff Engineer            4150 Network Circle
(408) 276-7046       MS USCA14-102                    Santa Clara, CA 95054

------------------------------- JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel



This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:39 EDT