4 ms·
If you have a reference to a junk instance, which is what can happen with an unsafe publication (which is what is going on with the stringCache member variable)
by LgWoodenBadger 9y ago
If you have a reference to a junk instance, which is what can happen with an unsafe publication (which is what is going on with the stringCache member variable) then all bets are off in terms of what you can expect to see.
- pvg 9y agoWhere is the 'unsafe publication' of String.value that you see? If you can create a 'junk instance' of String, your problem is with String.
- LgWoodenBadger 9y agoThis is the implementation of java.math.BigDecimal from JDK 1.6.0_45 private transient String stringCache; public String toString() { String sc = stringCache; if (sc == null) stringCache = sc = layoutChars(true); return sc; } Within a thread that sees "sc == null" the assignment of stringCache and sc to the result of layoutChars(true); will be legitimate (they will see a valid, fully-formed, correct String). Another thread calling toString() may or may not see sc, or stringCache, assigned to a legitimate String instance, due to the Java Memory Model (happens-before, memory barriers, CPU implementation details, cache levels, etc.). The data within the String created by layoutChars will be consistent to anybody who has established a happens-before relationship with respect to stringCache (either the thread who created it, or if stringCache was volatile, or if stringCache was final, or if a memory-barrier (synchronized, atomic primitive, etc.) has been erected around it. None of that is present in this implementation of BigDecimal.toString(), which is why stringCache (and the vars used in layoutChars()) is not a valid publication in the Java Memory Model. It has nothing to do with whether String is correct, and it's not a defect in the JRE implementation. No safe publication was established with respect to stringCache, therefore the data that other threads see is undefined.
- pvg 9y agoIt has nothing to do with whether String is correct It has everything to do with it. You have to explain how you ended up with a broken instance of String. The internal state of a String instance is hosed, which is a massive violation of all sorts of JVM guarantees and assumptions - this is the OG immutable class, after all. There are two options - a broken String implementation or a broken JVM implementation.
- cesarb 9y ago> If you have a reference to a junk instance Step back a bit: where did the junk instance come from? The Java rules guarantee that a String created through the String constructors is valid on any thread that can see it. There are no "junk instances" of String. Also, writing to an object reference variable is indivisible: either a thread doesn't see the write, or it sees the full write. So there are only two states in which a thread can see the stringCache field: either it is null, or it has a reference to a valid String. It might not see the field write from another thread, but in this case this only leads to duplicating work and leaving a bit of garbage on the heap for the GC to clean. (Of course, once you start using reflection to manipulate internal fields of an object, then all bets are off, but that's not the case here.)