JDK-8159244 : Partially initialized string object created by C2's string concat optimization may escape
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 7u121,8u92,9
  • Priority: P1
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2016-06-10
  • Updated: 2017-08-07
  • Resolved: 2016-06-15
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7 JDK 8 JDK 9
7u121Fixed 8u102Fixed 9 b127Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
C2's String concatenation optimization replaces a series of StringBuilder.append() calls by creating a single char buffer array (or byte array with Compact Strings) and emitting direct loads/stores to/from this array. The final StringBuilder.toString() call is replaced by a new String allocation which is initialized to the buffer array (see [1] -> [2], CallStaticJava is replaced).
Depending on the scheduling of instructions, it may happen that a reference to the newly allocated String object escapes before the String.value field is initialized  (see [2], '334 StoreP' stores the String object, '514 StoreP' initializes the String.value field). In a highly concurrent setting, another thread may try to dereference String.value from such a partially initialized String object and crash.

TestStringObjectInitialization.java reproduces this problem with JDK 7, 8 and 9 (see attached hs_err files) in approximately 1 out of 10 runs. I had to disable Indify String Concat, Compressed Oops and G1 to trigger the bug with JDK 9.

[1] https://bugs.openjdk.java.net/secure/attachment/60305/graph_baseline_before%20SC.png
[2] https://bugs.openjdk.java.net/secure/attachment/60306/graph_baseline_after_sc.png
Comments
Fix verified by regression test.
07-08-2017

The question came up why this bug did not show up before. Putting the answer here for reference: 1) It's a concurrency issue that only shows up with a very high load 2) It requires concurrent String concatenations without any synchronization (not a common code pattern) 3) It depends on instruction scheduling of the C2 compiler which is kind of nondeterministic 4) In JDK 9 we have new String features like Compact Strings and Indify String Concat which (depending on the settings) may hide this bug
27-06-2016

Changed label to 8BPR as this is what is needed.
20-06-2016

A StoreStoreBarrier is not sufficient (see [1]). We need to emit a MemBarRelease: http://cr.openjdk.java.net/~thartmann/8159244/webrev.9.01 http://cr.openjdk.java.net/~thartmann/8159244/webrev.8u.01 [1] http://www.hboehm.info/c++mm/no_write_fences.html
14-06-2016

The solution is to add a StoreStore barrier after the String object initialization to prevent subsequent stores to float above (we do the same for the Object.clone intrinsic). Prototype fixes: http://cr.openjdk.java.net/~thartmann/8159244/webrev.9.00/ http://cr.openjdk.java.net/~thartmann/8159244/webrev.8u.00/
13-06-2016

ILW = Crash or wrong Java exceptions, easy to reproduce, -XX:-OptimizeStringConcat = HHM = P1
10-06-2016