# HG changeset patch # User igerasim # Date 1553630489 25200 # Tue Mar 26 13:01:29 2019 -0700 # Node ID 50d1fd7c97b996f1a4a0f5016e64787b3e43f987 # Parent 8af48416e31f7c49f315e7b4b8c66c94cc3c9685 8221430: StringBuffer(CharSequence) constructor truncates when -XX:-CompactStrings specified Reviewed-by: igerasim, rriggs Contributed-by: Andrew Leonard diff --git a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java @@ -92,19 +92,24 @@ } /** - * Creates an AbstractStringBuilder with the specified coder and with + * Creates an AbstractStringBuilder with the specified coder + * (coderHint is used when compact strings are enabled) and with * the initial capacity equal to the smaller of (length + addition) * and Integer.MAX_VALUE. */ - AbstractStringBuilder(byte coder, int length, int addition) { + AbstractStringBuilder(byte coderHint, int length, int addition) { if (length < 0) { throw new NegativeArraySizeException("Negative length: " + length); } - this.coder = coder; int capacity = (length < Integer.MAX_VALUE - addition) ? length + addition : Integer.MAX_VALUE; - value = (coder == LATIN1) - ? new byte[capacity] : StringUTF16.newBytesFor(capacity); + if (COMPACT_STRINGS && coderHint == LATIN1) { + value = new byte[capacity]; + coder = LATIN1; + } else { + value = StringUTF16.newBytesFor(capacity); + coder = UTF16; + } } /** @@ -1741,4 +1746,18 @@ "start " + start + ", end " + end + ", length " + len); } } + + /** + * Determines the "coder" of the given CharSequence. + * If the coder cannot be determined, returns LATIN1. + */ + static byte getCharSequenceCoderHint(CharSequence seq) { + if (seq instanceof String) { + return ((String)seq).coder(); + } else if (seq instanceof AbstractStringBuilder) { + return ((AbstractStringBuilder)seq).getCoder(); + } else { + return LATIN1; + } + } } diff --git a/src/java.base/share/classes/java/lang/StringBuffer.java b/src/java.base/share/classes/java/lang/StringBuffer.java --- a/src/java.base/share/classes/java/lang/StringBuffer.java +++ b/src/java.base/share/classes/java/lang/StringBuffer.java @@ -162,7 +162,7 @@ * @since 1.5 */ public StringBuffer(CharSequence seq) { - super(String.LATIN1, seq.length(), 16); + super(getCharSequenceCoderHint(seq), seq.length(), 16); append(seq); } diff --git a/src/java.base/share/classes/java/lang/StringBuilder.java b/src/java.base/share/classes/java/lang/StringBuilder.java --- a/src/java.base/share/classes/java/lang/StringBuilder.java +++ b/src/java.base/share/classes/java/lang/StringBuilder.java @@ -134,7 +134,7 @@ * @param seq the sequence to copy. */ public StringBuilder(CharSequence seq) { - super(String.LATIN1, seq.length(), 16); + super(getCharSequenceCoderHint(seq), seq.length(), 16); append(seq); } diff --git a/test/jdk/java/lang/StringBuffer/CompactStringBuffer.java b/test/jdk/java/lang/StringBuffer/CompactStringBuffer.java --- a/test/jdk/java/lang/StringBuffer/CompactStringBuffer.java +++ b/test/jdk/java/lang/StringBuffer/CompactStringBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ /* * @test - * @bug 8077559 + * @bug 8077559 8221430 * @summary Tests Compact String. This test is testing StringBuffer * behavior related to Compact String. * @run testng/othervm -XX:+CompactStrings CompactStringBuffer @@ -440,6 +440,12 @@ "abcdefgh1.23456"); check(new StringBuffer().append(bmp).append(1.23456).toString(), "\u4e00\u4e01\u4e02\u4e03\u4e04\u4e05\u4e06\u4e07\u4e081.23456"); + + //////////////////////////////////////////////////////////////////// + check(new StringBuffer((CharSequence)new StringBuffer(ascii)).toString(), + ascii); + check(new StringBuffer((CharSequence)new StringBuffer(asciiMixed)).toString(), + asciiMixed); } private void checkGetChars(StringBuffer sb, int srcBegin, int srcEnd,