undefect. CWE-407 — 63 sites patched across 27 ecosystems

Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com

Patches, unit tests, benchmarks, whitepaper, and outreach briefs.
Public domain — no copyright claimed. Use freely.
This commit is contained in:
russell@unturf.com 2026-03-26 17:11:57 -04:00
commit 0a580b313d
70422 changed files with 17213626 additions and 0 deletions

View file

@ -0,0 +1,89 @@
/*
* Copyright (c) 2016, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @summary StringConcatFactory MH_INLINE_SIZED_EXACT strategy does not work with -XX:-CompactStrings
* @bug 8148869
*
* @compile -XDstringConcat=indy CompactStringsInitialCoder.java
* @run main/othervm -Xverify:all -XX:+CompactStrings CompactStringsInitialCoder
*
* @compile -XDstringConcat=indyWithConstants CompactStringsInitialCoder.java
* @run main/othervm -Xverify:all -XX:+CompactStrings CompactStringsInitialCoder
*
* @compile -XDstringConcat=indy CompactStringsInitialCoder.java
* @run main/othervm -Xverify:all -XX:-CompactStrings CompactStringsInitialCoder
*
* @compile -XDstringConcat=indyWithConstants CompactStringsInitialCoder.java
* @run main/othervm -Xverify:all -XX:-CompactStrings CompactStringsInitialCoder
*/
import java.lang.StringBuilder;
public class CompactStringsInitialCoder {
static String strEmpty = "";
static String strLatin1 = "\u0042";
static String strUTF16 = "\u4242";
static char charLatin1 = '\u0042';
static char charUTF16 = '\u4242';
public static void main(String[] args) throws Exception {
test("\u0042", "" + '\u0042');
test("\u4242", "" + '\u4242');
test("\u0042", "" + charLatin1);
test("\u4242", "" + charUTF16);
test("\u0042", strEmpty + '\u0042');
test("\u4242", strEmpty + '\u4242');
test("\u0042\u0042", strLatin1 + '\u0042');
test("\u0042\u4242", strLatin1 + '\u4242');
test("\u4242\u0042", strUTF16 + '\u0042');
test("\u4242\u4242", strUTF16 + '\u4242');
test("\u0042\u0042", "\u0042" + charLatin1);
test("\u0042\u4242", "\u0042" + charUTF16);
test("\u4242\u0042", "\u4242" + charLatin1);
test("\u4242\u4242", "\u4242" + charUTF16);
test("\u0042\u0042", "" + charLatin1 + charLatin1);
test("\u0042\u4242", "" + charLatin1 + charUTF16);
test("\u4242\u0042", "" + charUTF16 + charLatin1);
test("\u4242\u4242", "" + charUTF16 + charUTF16);
}
public static void test(String expected, String actual) {
if (!expected.equals(actual)) {
StringBuilder sb = new StringBuilder();
sb.append("Expected = ");
sb.append(expected);
sb.append(", actual = ");
sb.append(actual);
throw new IllegalStateException(sb.toString());
}
}
}

View file

@ -0,0 +1,79 @@
/*
* Copyright (c) 2024, Alibaba Group Holding Limited. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.lang.StringBuilder;
import java.lang.invoke.*;
import java.lang.management.ManagementFactory;
import jdk.test.whitebox.WhiteBox;
/**
* @test
* @summary Test whether the hidden class unloading of StringConcatFactory works
*
* @library /test/lib
* @build jdk.test.whitebox.WhiteBox
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
* @requires vm.flagless
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* -Xverify:all HiddenClassUnloading
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
* -Xverify:all -XX:-CompactStrings HiddenClassUnloading
*/
public class HiddenClassUnloading {
public static void main(String[] args) throws Throwable {
var lookup = MethodHandles.lookup();
var types = new Class<?>[] {
int.class, long.class, double.class, float.class, char.class, boolean.class, String.class,
};
long initUnloadedClassCount = ManagementFactory.getClassLoadingMXBean().getUnloadedClassCount();
for (int i = 0; i < 2000; i++) {
int radix = types.length;
String str = Integer.toString(i, radix);
int length = str.length();
var ptypes = new Class[length];
for (int j = 0; j < length; j++) {
int index = Integer.parseInt(str.substring(j, j + 1), radix);
ptypes[j] = types[index];
}
StringConcatFactory.makeConcatWithConstants(
lookup,
"concat",
MethodType.methodType(String.class, ptypes),
"\1".repeat(length), // recipe
new Object[0]
);
}
// Request GC which performs class unloading
WhiteBox.getWhiteBox().fullGC();
long unloadedClassCount = ManagementFactory.getClassLoadingMXBean().getUnloadedClassCount();
if (initUnloadedClassCount == unloadedClassCount) {
throw new RuntimeException("unloadedClassCount is zero");
}
}
}

View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 2025, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8356152
* @summary Check that huge concatenations throw OutOfMemoryError
* @requires os.maxMemory > 8G
* @run junit/othervm -Xmx8G -XX:+CompactStrings -Dcompact=true HugeConcatTest
* @run junit/othervm -Xmx8G -XX:-CompactStrings -Dcompact=false HugeConcatTest
*/
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.Assert.assertThrows;
public class HugeConcatTest {
private static final int HUGE_LENGTH_UTF16 = Integer.MAX_VALUE / 2 - 2;
private static String hugeLatin1;
private static final String hugeUTF16 = "\u20AC".repeat(HUGE_LENGTH_UTF16);
@BeforeAll
public static void initHugeLatin1() {
String compact = System.getProperty("compact", "true");
int hugeLatin1Length = Boolean.parseBoolean(compact)
? Integer.MAX_VALUE - 2
: HUGE_LENGTH_UTF16;
hugeLatin1 = "a".repeat(hugeLatin1Length);
}
@Test
public void testConcat_Latin1_Latin1() {
assertThrows(OutOfMemoryError.class, () -> { var s = hugeLatin1 + hugeLatin1; });
assertThrows(OutOfMemoryError.class, () -> hugeLatin1.concat(hugeLatin1));
}
@Test
public void testConcat_Latin1_UTF16() {
assertThrows(OutOfMemoryError.class, () -> { var s = hugeLatin1 + hugeUTF16; });
assertThrows(OutOfMemoryError.class, () -> hugeLatin1.concat(hugeUTF16));
}
@Test
public void testConcat_UTF16_Latin1() {
assertThrows(OutOfMemoryError.class, () -> { var s = hugeUTF16 + hugeLatin1; });
assertThrows(OutOfMemoryError.class, () -> hugeUTF16.concat(hugeLatin1));
}
@Test
public void testConcat_UTF16_UTF16() {
assertThrows(OutOfMemoryError.class, () -> { var s = hugeUTF16 + hugeUTF16; });
assertThrows(OutOfMemoryError.class, () -> hugeUTF16.concat(hugeUTF16));
}
}

View file

@ -0,0 +1,162 @@
/*
* Copyright (c) 2015, 2016, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @summary test implicit String concatenations
*
* @compile ImplicitStringConcat.java
* @run main/othervm -Xverify:all ImplicitStringConcat
*
* @compile -XDstringConcat=inline ImplicitStringConcat.java
* @run main/othervm -Xverify:all ImplicitStringConcat
*
* @compile -XDstringConcat=indy ImplicitStringConcat.java
* @run main/othervm -Xverify:all ImplicitStringConcat
*
* @compile -XDstringConcat=indyWithConstants ImplicitStringConcat.java
* @run main/othervm -Xverify:all ImplicitStringConcat
*/
import java.lang.StringBuilder;
public class ImplicitStringConcat {
static boolean b = true;
static byte by = 42;
static short sh = 42;
static char ch = 'a';
static int i = 42;
static float fl = 42.0f;
static long l = 42;
static double d = 42.0d;
static String s = "foo";
static String sNull = null;
static Object o = "bar";
static Object oNull = null;
static CharSequence cs = "bar";
static char[] chars = new char[] {'a'};
static MyClass myCl = new MyClass();
static MyClassNull myClNull = new MyClassNull();
static Object myCl2 = new MyClass();
static Object[] myArr = new Object[] { myCl };
static final Object[] s_myArr = new Object[] { myCl };
static StringBuffer sb = new StringBuffer("a");
public static void main(String[] args) throws Exception {
test("footrue", s + b);
test("foo42", s + by);
test("foo42", s + sh);
test("fooa", s + ch);
test("foo42", s + i);
test("foo42", s + l);
test("foo42.0", s + fl);
test("foo42.0", s + d);
test("foofoo", s + s);
test("foonull", s + sNull);
test("foobar", s + o);
test("foonull", s + oNull);
test("foobar", s + cs);
{
StringBuilder sb = new StringBuilder();
sb.append("foo");
sb.append(myArr.toString());
test(sb.toString(), s + myArr);
}
{
StringBuilder sb = new StringBuilder();
sb.append("foo");
sb.append(s_myArr.toString());
test(sb.toString(), s + s_myArr);
}
{
StringBuilder sb = new StringBuilder();
sb.append("foo[C@");
sb.append(Integer.toHexString(System.identityHashCode(chars)));
test(sb.toString(), s + chars);
}
test("fooa", s + ImplicitStringConcat.sb);
test("foonull", s + null);
test("fooMyClass", s + myCl);
test("foonull", s + myClNull);
test("fooMyClass", s + myCl2);
s = "foo"; s += b; test("footrue", s);
s = "foo"; s += by; test("foo42", s);
s = "foo"; s += sh; test("foo42", s);
s = "foo"; s += ch; test("fooa", s);
s = "foo"; s += i; test("foo42", s);
s = "foo"; s += l; test("foo42", s);
s = "foo"; s += fl; test("foo42.0", s);
s = "foo"; s += d; test("foo42.0", s);
s = "foo"; s += s; test("foofoo", s);
s = "foo"; s += sNull; test("foonull", s);
s = "foo"; s += o; test("foobar", s);
s = "foo"; s += oNull; test("foonull", s);
s = "foo"; s += cs; test("foobar", s);
{
StringBuilder sb = new StringBuilder();
sb.append("foo[C@");
sb.append(Integer.toHexString(System.identityHashCode(chars)));
s = "foo";
s += chars;
test(sb.toString(), s);
}
s = "foo"; s += ImplicitStringConcat.sb; test("fooa", s);
s = "foo"; s += null; test("foonull", s);
s = "foo"; s += myCl; test("fooMyClass", s);
s = "foo"; s += myCl2; test("fooMyClass", s);
}
public static void test(String expected, String actual) {
// Fingers crossed: String concat should work.
if (!expected.equals(actual)) {
StringBuilder sb = new StringBuilder();
sb.append("Expected = ");
sb.append(expected);
sb.append(", actual = ");
sb.append(actual);
throw new IllegalStateException(sb.toString());
}
}
static class MyClass {
public String toString() {
return "MyClass";
}
}
static class MyClassNull {
public String toString() {
return null;
}
}
}

View file

@ -0,0 +1,69 @@
/*
* Copyright (c) 2015, 2016, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @summary Test multiple number of arguments to concatenate.
*
* @compile ImplicitStringConcatArgCount.java
* @run main/othervm -Xverify:all ImplicitStringConcatArgCount
*
* @compile -XDallowStringFolding=false -XDstringConcat=inline ImplicitStringConcatArgCount.java
* @run main/othervm -Xverify:all ImplicitStringConcatArgCount
*
* @compile -XDallowStringFolding=false -XDstringConcat=indy ImplicitStringConcatArgCount.java
* @run main/othervm -Xverify:all ImplicitStringConcatArgCount
*
* @compile -XDallowStringFolding=false -XDstringConcat=indyWithConstants ImplicitStringConcatArgCount.java
* @run main/othervm -Xverify:all ImplicitStringConcatArgCount
*/
public class ImplicitStringConcatArgCount {
static final String s = "f";
static final String s1 = "o";
static String s2 = "o";
static int i = 7;
public static void main(String[] args) throws Exception {
test("fo", s + s1);
test("foo", s + s1 + s2);
test("foo7", s + s1 + s2 + i);
test("foo77", s + s1 + s2 + i + i);
test("foo777", s + s1 + s2 + i + i + i);
test("foo7777", s + s1 + s2 + i + i + i + i);
test("foo77777", s + s1 + s2 + i + i + i + i + i);
test("foo777777", s + s1 + s2 + i + i + i + i + i + i);
test("foo7777777", s + s1 + s2 + i + i + i + i + i + i + i);
test("foo77777777", s + s1 + s2 + i + i + i + i + i + i + i + i);
}
public static void test(String expected, String actual) {
if (!expected.equals(actual)) {
StringBuilder sb = new StringBuilder();
sb.append("Expected = ");
sb.append(expected);
sb.append(", actual = ");
sb.append(actual);
throw new IllegalStateException(sb.toString());
}
}
}

View file

@ -0,0 +1,178 @@
/*
* Copyright (c) 2018, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @summary "+=" applied to String operands can provoke side effects
* @bug 8204322
*
* @compile ImplicitStringConcatAssignLHS.java
* @run main/othervm -Xverify:all ImplicitStringConcatAssignLHS
*
* @compile -XDstringConcat=inline ImplicitStringConcatAssignLHS.java
* @run main/othervm -Xverify:all ImplicitStringConcatAssignLHS
*
* @compile -XDstringConcat=indy ImplicitStringConcatAssignLHS.java
* @run main/othervm -Xverify:all ImplicitStringConcatAssignLHS
*
* @compile -XDstringConcat=indyWithConstants ImplicitStringConcatAssignLHS.java
* @run main/othervm -Xverify:all ImplicitStringConcatAssignLHS
*/
import java.lang.StringBuilder;
public class ImplicitStringConcatAssignLHS {
static final int ARR_SIZE = 10; // enough padding to capture ill offsets
static int x;
public static void main(String[] args) throws Exception {
{
x = 0;
Object[] arr = new Object[ARR_SIZE];
arr[x++] += "foo";
check(1, "plain-plain Object[]");
}
{
x = 0;
getObjArray()[x++] += "foo";
check(2, "method-plain Object[]");
}
{
x = 0;
getObjArray()[getIndex()] += "foo";
check(2, "method-method Object[]");
}
{
x = 0;
String[] arr = new String[ARR_SIZE];
arr[x++] += "foo";
check(1, "plain-plain String[]");
}
{
x = 0;
getStringArray()[x++] += "foo";
check(2, "method-plain String[]");
}
{
x = 0;
getStringArray()[getIndex()] += "foo";
check(2, "method-method String[]");
}
{
x = 0;
CharSequence[] arr = new CharSequence[ARR_SIZE];
arr[x++] += "foo";
check(1, "plain-plain CharSequence[]");
}
{
x = 0;
getCharSequenceArray()[x++] += "foo";
check(2, "method-plain CharSequence[]");
}
{
x = 0;
getCharSequenceArray()[getIndex()] += "foo";
check(2, "method-method CharSequence[]");
}
{
x = 0;
new MyClass().s += "foo";
check(1, "MyClass::new (String)");
}
{
x = 0;
getMyClass().s += "foo";
check(1, "method MyClass::new (String)");
}
{
x = 0;
new MyClass().o += "foo";
check(1, "MyClass::new (object)");
}
{
x = 0;
getMyClass().o += "foo";
check(1, "method MyClass::new (object)");
}
}
public static void check(int expected, String label) {
if (x != expected) {
StringBuilder sb = new StringBuilder();
sb.append(label);
sb.append(": ");
sb.append("Expected = ");
sb.append(expected);
sb.append("actual = ");
sb.append(x);
throw new IllegalStateException(sb.toString());
}
}
public static int getIndex() {
return x++;
}
public static class MyClass {
Object o;
String s;
public MyClass() {
x++;
}
}
public static MyClass getMyClass() {
return new MyClass();
}
public static Object[] getObjArray() {
x++;
return new Object[ARR_SIZE];
}
public static String[] getStringArray() {
x++;
return new String[ARR_SIZE];
}
public static CharSequence[] getCharSequenceArray() {
x++;
return new String[ARR_SIZE];
}
}

View file

@ -0,0 +1,151 @@
/*
* Copyright (c) 2015, 2021, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @summary Test the boundary values for concatenation arguments.
*
* @compile ImplicitStringConcatBoundaries.java
* @run main/othervm -Xverify:all ImplicitStringConcatBoundaries
*
* @compile -XDstringConcat=inline ImplicitStringConcatBoundaries.java
* @run main/othervm -Xverify:all ImplicitStringConcatBoundaries
*
* @compile -XDstringConcat=indy ImplicitStringConcatBoundaries.java
* @run main/othervm -Xverify:all ImplicitStringConcatBoundaries
*
* @compile -XDstringConcat=indyWithConstants ImplicitStringConcatBoundaries.java
* @run main/othervm -Xverify:all ImplicitStringConcatBoundaries
*/
public class ImplicitStringConcatBoundaries {
public static final boolean BOOL_TRUE_1 = true;
public static boolean BOOL_TRUE_2 = true;
public static final boolean BOOL_FALSE_1 = false;
public static boolean BOOL_FALSE_2 = false;
public static final byte BYTE_MIN_1 = Byte.MIN_VALUE;
public static byte BYTE_MIN_2 = Byte.MIN_VALUE;
public static final byte BYTE_MAX_1 = Byte.MAX_VALUE;
public static byte BYTE_MAX_2 = Byte.MAX_VALUE;
public static final short SHORT_MIN_1 = Short.MIN_VALUE;
public static short SHORT_MIN_2 = Short.MIN_VALUE;
public static final short SHORT_MAX_1 = Short.MAX_VALUE;
public static short SHORT_MAX_2 = Short.MAX_VALUE;
public static final char CHAR_MIN_1 = Character.MIN_VALUE;
public static char CHAR_MIN_2 = Character.MIN_VALUE;
public static final char CHAR_MAX_1 = Character.MAX_VALUE;
public static char CHAR_MAX_2 = Character.MAX_VALUE;
public static final int INT_MIN_1 = Integer.MIN_VALUE;
public static int INT_MIN_2 = Integer.MIN_VALUE;
public static final int INT_MAX_1 = Integer.MAX_VALUE;
public static int INT_MAX_2 = Integer.MAX_VALUE;
public static final float FLOAT_MIN_EXP_1 = Float.MIN_EXPONENT;
public static float FLOAT_MIN_EXP_2 = Float.MIN_EXPONENT;
public static final float FLOAT_MIN_NORM_1 = Float.MIN_NORMAL;
public static float FLOAT_MIN_NORM_2 = Float.MIN_NORMAL;
public static final float FLOAT_MIN_1 = Float.MIN_VALUE;
public static float FLOAT_MIN_2 = Float.MIN_VALUE;
public static final float FLOAT_MAX_1 = Float.MAX_VALUE;
public static float FLOAT_MAX_2 = Float.MAX_VALUE;
public static final long LONG_MIN_1 = Long.MIN_VALUE;
public static long LONG_MIN_2 = Long.MIN_VALUE;
public static final long LONG_MAX_1 = Long.MAX_VALUE;
public static long LONG_MAX_2 = Long.MAX_VALUE;
public static final double DOUBLE_MIN_EXP_1 = Double.MIN_EXPONENT;
public static double DOUBLE_MIN_EXP_2 = Double.MIN_EXPONENT;
public static final double DOUBLE_MIN_NORM_1 = Double.MIN_NORMAL;
public static double DOUBLE_MIN_NORM_2 = Double.MIN_NORMAL;
public static final double DOUBLE_MIN_1 = Double.MIN_VALUE;
public static double DOUBLE_MIN_2 = Double.MIN_VALUE;
public static final double DOUBLE_MAX_1 = Double.MAX_VALUE;
public static double DOUBLE_MAX_2 = Double.MAX_VALUE;
public static void main(String[] args) throws Exception {
test("foofalse", "foo" + BOOL_FALSE_1);
test("foofalse", "foo" + BOOL_FALSE_2);
test("footrue", "foo" + BOOL_TRUE_1);
test("footrue", "foo" + BOOL_TRUE_2);
test("foo127", "foo" + BYTE_MAX_1);
test("foo127", "foo" + BYTE_MAX_2);
test("foo-128", "foo" + BYTE_MIN_1);
test("foo-128", "foo" + BYTE_MIN_2);
test("foo32767", "foo" + SHORT_MAX_1);
test("foo32767", "foo" + SHORT_MAX_2);
test("foo-32768", "foo" + SHORT_MIN_1);
test("foo-32768", "foo" + SHORT_MIN_2);
test("foo\u0000", "foo" + CHAR_MIN_1);
test("foo\u0000", "foo" + CHAR_MIN_2);
test("foo\uFFFF", "foo" + CHAR_MAX_1);
test("foo\uFFFF", "foo" + CHAR_MAX_2);
test("foo2147483647", "foo" + INT_MAX_1);
test("foo2147483647", "foo" + INT_MAX_2);
test("foo-2147483648", "foo" + INT_MIN_1);
test("foo-2147483648", "foo" + INT_MIN_2);
test("foo1.1754944E-38", "foo" + FLOAT_MIN_NORM_1);
test("foo1.1754944E-38", "foo" + FLOAT_MIN_NORM_2);
test("foo-126.0", "foo" + FLOAT_MIN_EXP_1);
test("foo-126.0", "foo" + FLOAT_MIN_EXP_2);
test("foo1.4E-45", "foo" + FLOAT_MIN_1);
test("foo1.4E-45", "foo" + FLOAT_MIN_2);
test("foo3.4028235E38", "foo" + FLOAT_MAX_1);
test("foo3.4028235E38", "foo" + FLOAT_MAX_2);
test("foo-9223372036854775808", "foo" + LONG_MIN_1);
test("foo-9223372036854775808", "foo" + LONG_MIN_2);
test("foo9223372036854775807", "foo" + LONG_MAX_1);
test("foo9223372036854775807", "foo" + LONG_MAX_2);
test("foo2.2250738585072014E-308", "foo" + DOUBLE_MIN_NORM_1);
test("foo2.2250738585072014E-308", "foo" + DOUBLE_MIN_NORM_2);
test("foo-1022.0", "foo" + DOUBLE_MIN_EXP_1);
test("foo-1022.0", "foo" + DOUBLE_MIN_EXP_2);
test("foo4.9E-324", "foo" + DOUBLE_MIN_1);
test("foo4.9E-324", "foo" + DOUBLE_MIN_2);
test("foo1.7976931348623157E308", "foo" + DOUBLE_MAX_1);
test("foo1.7976931348623157E308", "foo" + DOUBLE_MAX_2);
}
public static void test(String expected, String actual) {
if (!expected.equals(actual)) {
StringBuilder sb = new StringBuilder();
sb.append("Expected = ");
sb.append(expected);
sb.append(", actual = ");
sb.append(actual);
throw new IllegalStateException(sb.toString());
}
}
}

View file

@ -0,0 +1,141 @@
/*
* Copyright (c) 2015, 2016, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @summary Test implicit String concatenations with lots of arguments.
*
* @compile ImplicitStringConcatMany.java
* @run main/othervm -Xverify:all ImplicitStringConcatMany
*
* @compile -XDstringConcat=inline ImplicitStringConcatMany.java
* @run main/othervm -Xverify:all ImplicitStringConcatMany
*
* @compile -XDstringConcat=indy ImplicitStringConcatMany.java
* @run main/othervm -Xverify:all ImplicitStringConcatMany
*
* @compile -XDstringConcat=indyWithConstants ImplicitStringConcatMany.java
* @run main/othervm -Xverify:all ImplicitStringConcatMany
*/
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class ImplicitStringConcatMany {
static String s000, s001, s002, s003, s004, s005, s006, s007, s008, s009;
static String s010, s011, s012, s013, s014, s015, s016, s017, s018, s019;
static String s020, s021, s022, s023, s024, s025, s026, s027, s028, s029;
static String s030, s031, s032, s033, s034, s035, s036, s037, s038, s039;
static String s040, s041, s042, s043, s044, s045, s046, s047, s048, s049;
static String s050, s051, s052, s053, s054, s055, s056, s057, s058, s059;
static String s060, s061, s062, s063, s064, s065, s066, s067, s068, s069;
static String s070, s071, s072, s073, s074, s075, s076, s077, s078, s079;
static String s080, s081, s082, s083, s084, s085, s086, s087, s088, s089;
static String s090, s091, s092, s093, s094, s095, s096, s097, s098, s099;
static String s100, s101, s102, s103, s104, s105, s106, s107, s108, s109;
static String s110, s111, s112, s113, s114, s115, s116, s117, s118, s119;
static String s120, s121, s122, s123, s124, s125, s126, s127, s128, s129;
static String s130, s131, s132, s133, s134, s135, s136, s137, s138, s139;
static String s140, s141, s142, s143, s144, s145, s146, s147, s148, s149;
static String s150, s151, s152, s153, s154, s155, s156, s157, s158, s159;
static String s160, s161, s162, s163, s164, s165, s166, s167, s168, s169;
static String s170, s171, s172, s173, s174, s175, s176, s177, s178, s179;
static String s180, s181, s182, s183, s184, s185, s186, s187, s188, s189;
static String s190, s191, s192, s193, s194, s195, s196, s197, s198, s199;
static String s200, s201, s202, s203, s204, s205, s206, s207, s208, s209;
static String s210, s211, s212, s213, s214, s215, s216, s217, s218, s219;
static String s220, s221, s222, s223, s224, s225, s226, s227, s228, s229;
static String s230, s231, s232, s233, s234, s235, s236, s237, s238, s239;
static String s240, s241, s242, s243, s244, s245, s246, s247, s248, s249;
static String s250, s251, s252, s253, s254, s255, s256, s257, s258, s259;
static String s260, s261, s262, s263, s264, s265, s266, s267, s268, s269;
static String s270, s271, s272, s273, s274, s275, s276, s277, s278, s279;
static String s280, s281, s282, s283, s284, s285, s286, s287, s288, s289;
static String s290, s291, s292, s293, s294, s295, s296, s297, s298, s299;
static {
for (Field f : ImplicitStringConcatMany.class.getDeclaredFields()) {
if (Modifier.isStatic(f.getModifiers())) {
String name = f.getName();
try {
f.set(null, name);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
}
}
public static void main(String[] args) throws Exception {
String res =
s000 + s001 + s002 + s003 + s004 + s005 + s006 + s007 + s008 + s009 +
s010 + s011 + s012 + s013 + s014 + s015 + s016 + s017 + s018 + s019 +
s020 + s021 + s022 + s023 + s024 + s025 + s026 + s027 + s028 + s029 +
s030 + s031 + s032 + s033 + s034 + s035 + s036 + s037 + s038 + s039 +
s040 + s041 + s042 + s043 + s044 + s045 + s046 + s047 + s048 + s049 +
s050 + s051 + s052 + s053 + s054 + s055 + s056 + s057 + s058 + s059 +
s060 + s061 + s062 + s063 + s064 + s065 + s066 + s067 + s068 + s069 +
s070 + s071 + s072 + s073 + s074 + s075 + s076 + s077 + s078 + s079 +
s080 + s081 + s082 + s083 + s084 + s085 + s086 + s087 + s088 + s089 +
s090 + s091 + s092 + s093 + s094 + s095 + s096 + s097 + s098 + s099 +
s100 + s101 + s102 + s103 + s104 + s105 + s106 + s107 + s108 + s109 +
s110 + s111 + s112 + s113 + s114 + s115 + s116 + s117 + s118 + s119 +
s120 + s121 + s122 + s123 + s124 + s125 + s126 + s127 + s128 + s129 +
s130 + s131 + s132 + s133 + s134 + s135 + s136 + s137 + s138 + s139 +
s140 + s141 + s142 + s143 + s144 + s145 + s146 + s147 + s148 + s149 +
s150 + s151 + s152 + s153 + s154 + s155 + s156 + s157 + s158 + s159 +
s160 + s161 + s162 + s163 + s164 + s165 + s166 + s167 + s168 + s169 +
s170 + s171 + s172 + s173 + s174 + s175 + s176 + s177 + s178 + s179 +
s180 + s181 + s182 + s183 + s184 + s185 + s186 + s187 + s188 + s189 +
s190 + s191 + s192 + s193 + s194 + s195 + s196 + s197 + s198 + s199 +
s200 + s201 + s202 + s203 + s204 + s205 + s206 + s207 + s208 + s209 +
s210 + s211 + s212 + s213 + s214 + s215 + s216 + s217 + s218 + s219 +
s220 + s221 + s222 + s223 + s224 + s225 + s226 + s227 + s228 + s229 +
s230 + s231 + s232 + s233 + s234 + s235 + s236 + s237 + s238 + s239 +
s240 + s241 + s242 + s243 + s244 + s245 + s246 + s247 + s248 + s249 +
s250 + s251 + s252 + s253 + s254 + s255 + s256 + s257 + s258 + s259 +
s260 + s261 + s262 + s263 + s264 + s265 + s266 + s267 + s268 + s269 +
s270 + s271 + s272 + s273 + s274 + s275 + s276 + s277 + s278 + s279 +
s280 + s281 + s282 + s283 + s284 + s285 + s286 + s287 + s288 + s289 +
s290 + s291 + s292 + s293 + s294 + s295 + s296 + s297 + s298 + s299;
StringBuilder sb = new StringBuilder();
for (int c = 0; c < 300; c++) {
sb.append(String.format("s%03d", c));
}
test(sb.toString(), res);
}
public static void test(String expected, String actual) {
// Fingers crossed: String concat should work.
if (!expected.equals(actual)) {
throw new IllegalStateException("Expected = " + expected + ", actual = " + actual);
}
}
}

View file

@ -0,0 +1,141 @@
/*
* Copyright (c) 2015, 2016, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @summary Test implicit String concatenations with lots of arguments (two-slot version)
*
* @compile ImplicitStringConcatManyLongs.java
* @run main/othervm -Xverify:all ImplicitStringConcatManyLongs
*
* @compile -XDstringConcat=inline ImplicitStringConcatManyLongs.java
* @run main/othervm -Xverify:all ImplicitStringConcatManyLongs
*
* @compile -XDstringConcat=indy ImplicitStringConcatManyLongs.java
* @run main/othervm -Xverify:all ImplicitStringConcatManyLongs
*
* @compile -XDstringConcat=indyWithConstants ImplicitStringConcatManyLongs.java
* @run main/othervm -Xverify:all ImplicitStringConcatManyLongs
*/
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class ImplicitStringConcatManyLongs {
static long s000, s001, s002, s003, s004, s005, s006, s007, s008, s009;
static long s010, s011, s012, s013, s014, s015, s016, s017, s018, s019;
static long s020, s021, s022, s023, s024, s025, s026, s027, s028, s029;
static long s030, s031, s032, s033, s034, s035, s036, s037, s038, s039;
static long s040, s041, s042, s043, s044, s045, s046, s047, s048, s049;
static long s050, s051, s052, s053, s054, s055, s056, s057, s058, s059;
static long s060, s061, s062, s063, s064, s065, s066, s067, s068, s069;
static long s070, s071, s072, s073, s074, s075, s076, s077, s078, s079;
static long s080, s081, s082, s083, s084, s085, s086, s087, s088, s089;
static long s090, s091, s092, s093, s094, s095, s096, s097, s098, s099;
static long s100, s101, s102, s103, s104, s105, s106, s107, s108, s109;
static long s110, s111, s112, s113, s114, s115, s116, s117, s118, s119;
static long s120, s121, s122, s123, s124, s125, s126, s127, s128, s129;
static long s130, s131, s132, s133, s134, s135, s136, s137, s138, s139;
static long s140, s141, s142, s143, s144, s145, s146, s147, s148, s149;
static long s150, s151, s152, s153, s154, s155, s156, s157, s158, s159;
static long s160, s161, s162, s163, s164, s165, s166, s167, s168, s169;
static long s170, s171, s172, s173, s174, s175, s176, s177, s178, s179;
static long s180, s181, s182, s183, s184, s185, s186, s187, s188, s189;
static long s190, s191, s192, s193, s194, s195, s196, s197, s198, s199;
static long s200, s201, s202, s203, s204, s205, s206, s207, s208, s209;
static long s210, s211, s212, s213, s214, s215, s216, s217, s218, s219;
static long s220, s221, s222, s223, s224, s225, s226, s227, s228, s229;
static long s230, s231, s232, s233, s234, s235, s236, s237, s238, s239;
static long s240, s241, s242, s243, s244, s245, s246, s247, s248, s249;
static long s250, s251, s252, s253, s254, s255, s256, s257, s258, s259;
static long s260, s261, s262, s263, s264, s265, s266, s267, s268, s269;
static long s270, s271, s272, s273, s274, s275, s276, s277, s278, s279;
static long s280, s281, s282, s283, s284, s285, s286, s287, s288, s289;
static long s290, s291, s292, s293, s294, s295, s296, s297, s298, s299;
static {
for (Field f : ImplicitStringConcatManyLongs.class.getDeclaredFields()) {
if (Modifier.isStatic(f.getModifiers())) {
String name = f.getName();
try {
f.set(null, Long.valueOf(name.substring(1)));
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
}
}
public static void main(String[] args) throws Exception {
String res = "" +
s000 + s001 + s002 + s003 + s004 + s005 + s006 + s007 + s008 + s009 +
s010 + s011 + s012 + s013 + s014 + s015 + s016 + s017 + s018 + s019 +
s020 + s021 + s022 + s023 + s024 + s025 + s026 + s027 + s028 + s029 +
s030 + s031 + s032 + s033 + s034 + s035 + s036 + s037 + s038 + s039 +
s040 + s041 + s042 + s043 + s044 + s045 + s046 + s047 + s048 + s049 +
s050 + s051 + s052 + s053 + s054 + s055 + s056 + s057 + s058 + s059 +
s060 + s061 + s062 + s063 + s064 + s065 + s066 + s067 + s068 + s069 +
s070 + s071 + s072 + s073 + s074 + s075 + s076 + s077 + s078 + s079 +
s080 + s081 + s082 + s083 + s084 + s085 + s086 + s087 + s088 + s089 +
s090 + s091 + s092 + s093 + s094 + s095 + s096 + s097 + s098 + s099 +
s100 + s101 + s102 + s103 + s104 + s105 + s106 + s107 + s108 + s109 +
s110 + s111 + s112 + s113 + s114 + s115 + s116 + s117 + s118 + s119 +
s120 + s121 + s122 + s123 + s124 + s125 + s126 + s127 + s128 + s129 +
s130 + s131 + s132 + s133 + s134 + s135 + s136 + s137 + s138 + s139 +
s140 + s141 + s142 + s143 + s144 + s145 + s146 + s147 + s148 + s149 +
s150 + s151 + s152 + s153 + s154 + s155 + s156 + s157 + s158 + s159 +
s160 + s161 + s162 + s163 + s164 + s165 + s166 + s167 + s168 + s169 +
s170 + s171 + s172 + s173 + s174 + s175 + s176 + s177 + s178 + s179 +
s180 + s181 + s182 + s183 + s184 + s185 + s186 + s187 + s188 + s189 +
s190 + s191 + s192 + s193 + s194 + s195 + s196 + s197 + s198 + s199 +
s200 + s201 + s202 + s203 + s204 + s205 + s206 + s207 + s208 + s209 +
s210 + s211 + s212 + s213 + s214 + s215 + s216 + s217 + s218 + s219 +
s220 + s221 + s222 + s223 + s224 + s225 + s226 + s227 + s228 + s229 +
s230 + s231 + s232 + s233 + s234 + s235 + s236 + s237 + s238 + s239 +
s240 + s241 + s242 + s243 + s244 + s245 + s246 + s247 + s248 + s249 +
s250 + s251 + s252 + s253 + s254 + s255 + s256 + s257 + s258 + s259 +
s260 + s261 + s262 + s263 + s264 + s265 + s266 + s267 + s268 + s269 +
s270 + s271 + s272 + s273 + s274 + s275 + s276 + s277 + s278 + s279 +
s280 + s281 + s282 + s283 + s284 + s285 + s286 + s287 + s288 + s289 +
s290 + s291 + s292 + s293 + s294 + s295 + s296 + s297 + s298 + s299;
StringBuilder sb = new StringBuilder();
for (int c = 0; c < 300; c++) {
sb.append(c);
}
test(sb.toString(), res);
}
public static void test(String expected, String actual) {
// Fingers crossed: String concat should work.
if (!expected.equals(actual)) {
throw new IllegalStateException("Expected = " + expected + ", actual = " + actual);
}
}
}

View file

@ -0,0 +1,136 @@
/*
* Copyright (c) 2022, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test 8297530
* @summary This sanity tests that OOME is correctly thrown when
* the length of the array to be allocated for a concatenation.
* Before the fix for 8297530 an IllegalArgumentException could
* erroneously be thrown when the length of the string is between
* Integer.MAX_VALUE / 2 and Integer.MAX_VALUE and the String coder
* is UTF16.
*
* @requires sun.arch.data.model == "64"
* @run main/othervm -Xverify:all -Xmx4g ImplicitStringConcatOOME
* @run main/othervm -Xverify:all -Xmx4g -XX:-CompactStrings ImplicitStringConcatOOME
*/
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class ImplicitStringConcatOOME {
static String s000, s001, s002, s003, s004, s005, s006, s007, s008, s009;
static String s010, s011, s012, s013, s014, s015, s016, s017, s018, s019;
static String s020, s021, s022, s023, s024, s025, s026, s027, s028, s029;
static String s030, s031, s032, s033, s034, s035, s036, s037, s038, s039;
static String s040, s041, s042, s043, s044, s045, s046, s047, s048, s049;
static String s050, s051, s052, s053, s054, s055, s056, s057, s058, s059;
static String s060, s061, s062, s063, s064, s065, s066, s067, s068, s069;
static String s070, s071, s072, s073, s074, s075, s076, s077, s078, s079;
static String s080, s081, s082, s083, s084, s085, s086, s087, s088, s089;
static String s090, s091, s092, s093, s094, s095, s096, s097, s098, s099;
static String s100, s101, s102, s103, s104, s105, s106, s107, s108, s109;
static String s110, s111, s112, s113, s114, s115, s116, s117, s118, s119;
static String s120, s121, s122, s123, s124, s125, s126, s127, s128, s129;
static String s130, s131, s132, s133, s134, s135, s136, s137, s138, s139;
static String s140, s141, s142, s143, s144, s145, s146, s147, s148, s149;
static String s150, s151, s152, s153, s154, s155, s156, s157, s158, s159;
static String s160, s161, s162, s163, s164, s165, s166, s167, s168, s169;
static String s170, s171, s172, s173, s174, s175, s176, s177, s178, s179;
static String s180, s181, s182, s183, s184, s185, s186, s187, s188, s189;
static String s190, s191, s192, s193, s194, s195, s196, s197, s198, s199;
static String s_utf16;
static {
String s = "10 letters".repeat(1_073_742);
for (Field f : ImplicitStringConcatOOME.class.getDeclaredFields()) {
if (Modifier.isStatic(f.getModifiers())) {
try {
f.set(null, s);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
}
s_utf16 = "\u0257";
}
public static void main(String[] args) throws Exception {
try {
String res =
s000 + s001 + s002 + s003 + s004 + s005 + s006 + s007 + s008 + s009 +
s010 + s011 + s012 + s013 + s014 + s015 + s016 + s017 + s018 + s019 +
s020 + s021 + s022 + s023 + s024 + s025 + s026 + s027 + s028 + s029 +
s030 + s031 + s032 + s033 + s034 + s035 + s036 + s037 + s038 + s039 +
s040 + s041 + s042 + s043 + s044 + s045 + s046 + s047 + s048 + s049 +
s050 + s051 + s052 + s053 + s054 + s055 + s056 + s057 + s058 + s059 +
s060 + s061 + s062 + s063 + s064 + s065 + s066 + s067 + s068 + s069 +
s070 + s071 + s072 + s073 + s074 + s075 + s076 + s077 + s078 + s079 +
s080 + s081 + s082 + s083 + s084 + s085 + s086 + s087 + s088 + s089 +
s090 + s091 + s092 + s093 + s094 + s095 + s096 + s097 + s098 + s099 +
s100 + s101 + s102 + s103 + s104 + s105 + s106 + s107 + s108 + s109 +
s110 + s111 + s112 + s113 + s114 + s115 + s116 + s117 + s118 + s119 +
s120 + s121 + s122 + s123 + s124 + s125 + s126 + s127 + s128 + s129 +
s130 + s131 + s132 + s133 + s134 + s135 + s136 + s137 + s138 + s139 +
s140 + s141 + s142 + s143 + s144 + s145 + s146 + s147 + s148 + s149 +
s150 + s151 + s152 + s153 + s154 + s155 + s156 + s157 + s158 + s159 +
s160 + s161 + s162 + s163 + s164 + s165 + s166 + s167 + s168 + s169 +
s170 + s171 + s172 + s173 + s174 + s175 + s176 + s177 + s178 + s179 +
s180 + s181 + s182 + s183 + s184 + s185 + s186 + s187 + s188 + s189 +
s190 + s191 + s192 + s193 + s194 + s195 + s196 + s197 + s198 + s199;
throw new IllegalStateException("Expected OOME");
} catch (OutOfMemoryError e) {
// Expected
}
try {
// Compact Strings meant capacity for UTF16 strings were cut in
// half, regardless of -XX:+CompactStrings setting
String res =
s000 + s001 + s002 + s003 + s004 + s005 + s006 + s007 + s008 + s009 +
s010 + s011 + s012 + s013 + s014 + s015 + s016 + s017 + s018 + s019 +
s020 + s021 + s022 + s023 + s024 + s025 + s026 + s027 + s028 + s029 +
s030 + s031 + s032 + s033 + s034 + s035 + s036 + s037 + s038 + s039 +
s040 + s041 + s042 + s043 + s044 + s045 + s046 + s047 + s048 + s049 +
s050 + s051 + s052 + s053 + s054 + s055 + s056 + s057 + s058 + s059 +
s060 + s061 + s062 + s063 + s064 + s065 + s066 + s067 + s068 + s069 +
s070 + s071 + s072 + s073 + s074 + s075 + s076 + s077 + s078 + s079 +
s080 + s081 + s082 + s083 + s084 + s085 + s086 + s087 + s088 + s089 +
s090 + s091 + s092 + s093 + s094 + s095 + s096 + s097 + s098 + s099 +
s_utf16;
throw new IllegalStateException("Expected OOME");
} catch (OutOfMemoryError e) {
// Expected
}
}
public static void test(String expected, String actual) {
// Fingers crossed: String concat should work.
if (!expected.equals(actual)) {
throw new IllegalStateException("Expected = " + expected + ", actual = " + actual);
}
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2018, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @summary Test implicit string concat calls argument conversions in the right order
* @bug 8200118
*
* @compile ImplicitStringConcatOrder.java
* @run main/othervm -Xverify:all ImplicitStringConcatOrder
*
* @compile -XDstringConcat=inline ImplicitStringConcatOrder.java
* @run main/othervm -Xverify:all ImplicitStringConcatOrder
*
* @compile -XDstringConcat=indy ImplicitStringConcatOrder.java
* @run main/othervm -Xverify:all ImplicitStringConcatOrder
*
* @compile -XDstringConcat=indyWithConstants ImplicitStringConcatOrder.java
* @run main/othervm -Xverify:all ImplicitStringConcatOrder
*/
import java.lang.StringBuilder;
public class ImplicitStringConcatOrder {
static MyClass c = new MyClass();
public static void main(String[] args) throws Exception {
test("foo123bar", "foo" + c + c + c + "bar");
test("bazxyz456abc", "baz" + ("xyz" + c + c) + c + "abc");
test("caf7eba89be", "caf" + c + ("eba" + c + c) + "be");
}
public static void test(String expected, String actual) {
if (!expected.equals(actual)) {
StringBuilder sb = new StringBuilder();
sb.append("Expected = ");
sb.append(expected);
sb.append(", actual = ");
sb.append(actual);
throw new IllegalStateException(sb.toString());
}
}
static class MyClass {
int x;
public String toString() {
return String.valueOf(++x);
}
}
}

View file

@ -0,0 +1,74 @@
/*
* Copyright (c) 2015, 2020, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @summary Test implicit String concatenations, multiple shapes.
* @bug 8148483 8245959 8247681
*
* @compile ImplicitStringConcatShapes.java
* @run main/othervm -Xverify:all ImplicitStringConcatShapes
*
* @compile -XDstringConcat=inline ImplicitStringConcatShapes.java
* @run main/othervm -Xverify:all ImplicitStringConcatShapes
*
* @compile -XDstringConcat=indy ImplicitStringConcatShapes.java
* @run main/othervm -Xverify:all ImplicitStringConcatShapes
*
* @compile -XDstringConcat=indyWithConstants ImplicitStringConcatShapes.java
* @run main/othervm -Xverify:all ImplicitStringConcatShapes
*/
public class ImplicitStringConcatShapes {
public static void test(String expected, String actual) {
// Fingers crossed: String concat should work.
if (!expected.equals(actual)) {
StringBuilder sb = new StringBuilder();
sb.append("Expected = ");
sb.append(expected);
sb.append(", actual = ");
sb.append(actual);
throw new IllegalStateException(sb.toString());
}
}
static class MyClass {
private final int i;
public MyClass(int i) {
this.i = i;
}
public String toString() {
return new StringBuilder("C(").append(i).append(")").toString();
}
}
static class MyClassNullToString {
public String toString() {
return null;
}
}
public static void main(String[] args) throws Exception {
new ImplicitStringConcatShapes().run();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,333 @@
/*
* Copyright (c) 2015, 2020, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
public class ImplicitStringConcatShapesTestGen {
public static String escapeToUnicode(String str) {
StringBuilder b = new StringBuilder();
for (char c : str.toCharArray()) {
if (c < 128) {
b.append(c);
} else {
b.append("\\u").append(String.format("%04X", (int) c));
}
}
return b.toString();
}
public static void main(String... args) throws IOException {
PrintWriter pw = new PrintWriter(System.out);
String[] types = {
"boolean",
"byte",
"byteMinus",
"char",
"short",
"shortMinus",
"int",
"intMinus",
"integer",
"integerNull",
"float",
"floatMinus",
"long",
"longMinus",
"double",
"doubleMinus",
"object",
"objectNull",
"objectNullToString",
"String",
"StringUTF16",
"StringU1",
"StringU2",
"intArrayNull",
"objectArrayNull",
};
for (String t : Files.readAllLines(Paths.get("ImplicitStringConcatShapes-head.template"))) {
pw.println(t);
}
Map<String, String> values = new HashMap<>();
Random current = new Random(12345);
for (int mode = 0; mode <= 2; mode++) {
for (String type : types) {
int i = current.nextInt(100);
boolean isStatic = (mode | 1) == 1;
boolean isFinal = (mode | 2) == 2;
String fieldName = (isStatic ? "s" : "") + (isFinal ? "f" : "") + "_" + typeSig(type);
String value = initValue(type, i);
String stringValue = stringValue(type, i);
values.put(fieldName, stringValue);
pw.printf(" %s %s %s %s = %s;%n", isStatic ? "static" : "", isFinal ? "final" : "", typeValue(type, i), fieldName, value);
}
}
pw.println();
List<String> lines = new ArrayList<>();
List<String> l = new ArrayList<>(values.keySet());
for (String l1 : l) {
lines.add(String.format("test(\"%s\", \"\" + %s);",
escapeToUnicode(values.get(l1)),
l1
));
lines.add(String.format("test(\"%s\", \"prefix\" + %s);",
escapeToUnicode("prefix" + values.get(l1)),
l1
));
lines.add(String.format("test(\"%s\", %s + \"suffix\");",
escapeToUnicode(values.get(l1) + "suffix"),
l1
));
lines.add(String.format("test(\"%s\", \"prefix\" + %s + \"suffix\");",
escapeToUnicode("prefix" + values.get(l1) + "suffix"),
l1
));
}
for (String l1 : l) {
for (String l2 : l) {
lines.add(String.format("test(\"%s\", \"\" + %s + %s);",
escapeToUnicode(values.get(l1) + values.get(l2)),
l1, l2
));
lines.add(String.format("test(\"%s\", \"\" + %s + %s + \"suffix\");",
escapeToUnicode(values.get(l1) + values.get(l2) + "suffix"),
l1, l2
));
lines.add(String.format("test(\"%s\", \"prefix\" + %s + \"suffix1\" + %s + \"suffix2\");",
escapeToUnicode("prefix" + values.get(l1) + "suffix1" + values.get(l2) + "suffix2"),
l1, l2
));
}
}
final int STRIDE = 1000;
int strides = lines.size() / STRIDE + 1;
pw.println(" public void run() {");
for (int c = 0; c < strides; c++) {
pw.println(" run" + c + "();");
}
pw.println(" }");
pw.println();
for (int c = 0; c < strides; c++) {
pw.println(" public void run" + c + "() {");
for (String line : lines.subList(c * STRIDE, Math.min(lines.size(), (c+1) * STRIDE))) {
pw.println(" " + line);
}
pw.println(" }");
pw.println();
}
pw.println("}");
pw.flush();
pw.close();
}
private static String typeSig(String type) {
switch (type) {
case "boolean": return "bl";
case "byte": return "b";
case "byteMinus": return "bM";
case "short": return "s";
case "shortMinus": return "sM";
case "char": return "c";
case "int": return "i";
case "intMinus": return "iM";
case "integer": return "I";
case "integerNull": return "IN";
case "float": return "f";
case "floatMinus": return "fM";
case "long": return "l";
case "longMinus": return "lM";
case "double": return "d";
case "doubleMinus": return "dM";
case "String": return "str";
case "StringUTF16": return "strU";
case "StringU1": return "strU1";
case "StringU2": return "strU2";
case "object": return "o";
case "objectNull": return "oN";
case "objectNullToString": return "oNtS";
case "intArrayNull": return "iAN";
case "objectArrayNull": return "oAN";
default:
throw new IllegalStateException();
}
}
private static String typeValue(String type, int i) {
switch (type) {
case "boolean":
case "byte":
case "byteMinus":
case "char":
case "short":
case "shortMinus":
case "int":
case "intMinus":
case "float":
case "floatMinus":
case "long":
case "longMinus":
case "double":
case "doubleMinus":
return type.replace("Minus", "");
case "String":
case "StringUTF16":
case "StringU1":
case "StringU2":
return "String";
case "object":
case "objectNull":
case "objectNullToString":
return "Object";
case "integer":
case "integerNull":
return "Integer";
case "intArrayNull":
return "int[]";
case "objectArrayNull":
return "Object[]";
default:
throw new IllegalStateException();
}
}
private static String initValue(String type, int i) {
switch (type) {
case "boolean":
return String.valueOf((i & 1) == 1);
case "byte":
return String.valueOf(i);
case "byteMinus":
return String.valueOf(-i);
case "short":
return String.valueOf(i*100);
case "shortMinus":
return String.valueOf(-i*100);
case "intMinus":
return String.valueOf(-i*1_000_000);
case "int":
case "integer":
return String.valueOf(i*1_000_000);
case "long":
return String.valueOf(i*1_000_000_000) + "L";
case "longMinus":
return String.valueOf(-i*1_000_000_000) + "L";
case "char":
return "'" + (char)(i % 26 + 65) + "'";
case "double":
return String.valueOf(i) + ".0d";
case "doubleMinus":
return "-" + String.valueOf(i) + ".0d";
case "float":
return String.valueOf(i) + ".0f";
case "floatMinus":
return "-" + String.valueOf(i) + ".0f";
case "object":
return "new MyClass(" + i + ")";
case "objectNullToString":
return "new MyClassNullToString()";
case "integerNull":
case "objectNull":
case "intArrayNull":
case "objectArrayNull":
return "null";
case "String":
return "\"" + i + "\"";
case "StringUTF16":
return "\"\\u0451" + i + "\"";
case "StringU1":
return "\"\\u0001" + i + "\"";
case "StringU2":
return "\"\\u0002" + i + "\"";
default:
throw new IllegalStateException();
}
}
private static String stringValue(String type, int i) {
switch (type) {
case "boolean":
return String.valueOf((i & 1) == 1);
case "byte":
return String.valueOf(i);
case "byteMinus":
return String.valueOf(-i);
case "short":
return String.valueOf(i*100);
case "shortMinus":
return String.valueOf(-i*100);
case "intMinus":
return String.valueOf(-i*1_000_000);
case "int":
case "integer":
return String.valueOf(i*1_000_000);
case "long":
return String.valueOf(i*1_000_000_000);
case "longMinus":
return String.valueOf(-i*1_000_000_000);
case "char":
return String.valueOf((char) (i % 26 + 65));
case "double":
case "float":
return String.valueOf(i) + ".0";
case "doubleMinus":
case "floatMinus":
return "-" + String.valueOf(i) + ".0";
case "object":
return "C(" + i + ")";
case "integerNull":
case "objectNull":
case "objectNullToString":
case "intArrayNull":
case "objectArrayNull":
return "null";
case "String":
return "" + i;
case "StringUTF16":
return "\u0451" + i;
case "StringU1":
return "\u0001" + i;
case "StringU2":
return "\u0002" + i;
default:
throw new IllegalStateException();
}
}
}

View file

@ -0,0 +1,60 @@
/*
* Copyright (c) 2021, Red Hat, Inc. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 8267773
* @summary Test
*
* @compile IntegerMinValue.java
* @run main/othervm -Xverify:all -Xbatch IntegerMinValue
*
* @compile -XDstringConcat=inline IntegerMinValue.java
* @run main/othervm -Xverify:all -Xbatch IntegerMinValue
*
* @compile -XDstringConcat=indy IntegerMinValue.java
* @run main/othervm -Xverify:all -Xbatch IntegerMinValue
*
* @compile -XDstringConcat=indyWithConstants IntegerMinValue.java
* @run main/othervm -Xverify:all -Xbatch IntegerMinValue
*/
public class IntegerMinValue {
public void test() {
int i = Integer.MIN_VALUE;
String s = "" + i;
if (!"-2147483648".equals(s)) {
throw new IllegalStateException("Failed: " + s);
}
System.out.println(s);
}
public static void main(String[] strArr) {
IntegerMinValue t = new IntegerMinValue();
for (int i = 0; i < 100_000; i++ ) {
t.test();
}
}
}

View file

@ -0,0 +1,361 @@
/*
* Copyright (c) 2015, 2016, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.io.Serializable;
import java.lang.invoke.*;
import java.util.concurrent.Callable;
/**
* @test
* @summary Test input invariants for StringConcatFactory
* @bug 8246152 8247681
*
* @compile StringConcatFactoryInvariants.java
*
* @run main/othervm -Xverify:all StringConcatFactoryInvariants
*
*/
public class StringConcatFactoryInvariants {
private static final char TAG_ARG = '\u0001';
private static final char TAG_CONST = '\u0002';
public static void main(String[] args) throws Throwable {
MethodHandles.Lookup lookup = MethodHandles.lookup();
String methodName = "foo";
MethodType mt = MethodType.methodType(String.class, String.class, int.class);
String recipe = "" + TAG_ARG + TAG_ARG + TAG_CONST;
Object[][] constants = new Object[][] {
new String[] { "" },
new String[] { "bar" },
new Integer[] { 1 },
new Short[] { 2 },
new Long[] { 3L },
new Boolean[] { true },
new Character[] { 'a' },
new Byte[] { -128 },
new Class[] { String.class },
new MethodHandle[] { MethodHandles.constant(String.class, "constant") },
new MethodType[] { MethodType.methodType(String.class) }
};
// The string representation that should end up if the corresponding
// Object[] in constants is used as an argument to makeConcatWithConstants
String[] constantString = new String[] {
"",
"bar",
"1",
"2",
"3",
"true",
"a",
"-128",
"class java.lang.String",
"MethodHandle()String",
"()String"
};
final int LIMIT = 200;
// Simple factory: check for dynamic arguments overflow
Class<?>[] underThreshold = new Class<?>[LIMIT - 1];
Class<?>[] threshold = new Class<?>[LIMIT];
Class<?>[] overThreshold = new Class<?>[LIMIT + 1];
StringBuilder sbUnderThreshold = new StringBuilder();
sbUnderThreshold.append(TAG_CONST);
for (int c = 0; c < LIMIT - 1; c++) {
underThreshold[c] = int.class;
threshold[c] = int.class;
overThreshold[c] = int.class;
sbUnderThreshold.append(TAG_ARG);
}
threshold[LIMIT - 1] = int.class;
overThreshold[LIMIT - 1] = int.class;
overThreshold[LIMIT] = int.class;
String recipeEmpty = "";
String recipeUnderThreshold = sbUnderThreshold.toString();
String recipeThreshold = sbUnderThreshold.append(TAG_ARG).toString();
String recipeOverThreshold = sbUnderThreshold.append(TAG_ARG).toString();
MethodType mtEmpty = MethodType.methodType(String.class);
MethodType mtUnderThreshold = MethodType.methodType(String.class, underThreshold);
MethodType mtThreshold = MethodType.methodType(String.class, threshold);
MethodType mtOverThreshold = MethodType.methodType(String.class, overThreshold);
// Check the basic functionality is working
{
CallSite cs = StringConcatFactory.makeConcat(lookup, methodName, mt);
test("foo42", (String) cs.getTarget().invokeExact("foo", 42));
}
{
for (int i = 0; i < constants.length; i++) {
CallSite cs = StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, recipe, constants[i]);
test("foo42".concat(constantString[i]), (String) cs.getTarget().invokeExact("foo", 42));
}
}
// Check unary expressions with pre- and postfix constants
{
String constArgRecipe = "" + TAG_CONST + TAG_ARG;
String argConstRecipe = "" + TAG_ARG + TAG_CONST;
MethodType unaryMt = MethodType.methodType(String.class, String.class);
for (int i = 0; i < constants.length; i++) {
CallSite prefixCS = StringConcatFactory.makeConcatWithConstants(lookup, methodName, unaryMt, constArgRecipe, constants[i]);
test(constantString[i].concat("foo"), (String) prefixCS.getTarget().invokeExact("foo"));
CallSite postfixCS = StringConcatFactory.makeConcatWithConstants(lookup, methodName, unaryMt, argConstRecipe, constants[i]);
test("foo".concat(constantString[i]), (String) postfixCS.getTarget().invokeExact("foo"));
}
}
// Simple factory, check for nulls:
failNPE("Lookup is null",
() -> StringConcatFactory.makeConcat(null, methodName, mt));
failNPE("Method name is null",
() -> StringConcatFactory.makeConcat(lookup, null, mt));
failNPE("MethodType is null",
() -> StringConcatFactory.makeConcat(lookup, methodName, null));
// Advanced factory, check for nulls:
for (int i = 0; i < constants.length; i++) {
final Object[] consts = constants[i];
failNPE("Lookup is null",
() -> StringConcatFactory.makeConcatWithConstants(null, methodName, mt, recipe, consts));
failNPE("Method name is null",
() -> StringConcatFactory.makeConcatWithConstants(lookup, null, mt, recipe, consts));
failNPE("MethodType is null",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, null, recipe, consts));
failNPE("Recipe is null",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, null, consts));
}
failNPE("Constants vararg is null",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, recipe, (Object[]) null));
failNPE("Constant argument is null",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mt, recipe, new Object[] { null }));
// Simple factory, check for return type
fail("Return type: void",
() -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(void.class, String.class, int.class)));
fail("Return type: int",
() -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(int.class, String.class, int.class)));
fail("Return type: StringBuilder",
() -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(StringBuilder.class, String.class, int.class)));
ok("Return type: Object",
() -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(Object.class, String.class, int.class)));
ok("Return type: CharSequence",
() -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(CharSequence.class, String.class, int.class)));
ok("Return type: Serializable",
() -> StringConcatFactory.makeConcat(lookup, methodName, MethodType.methodType(Serializable.class, String.class, int.class)));
// Advanced factory, check for return types
for (int i = 0; i < constants.length; i++) {
final Object[] consts = constants[i];
fail("Return type: void",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(void.class, String.class, int.class), recipe, consts));
fail("Return type: int",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(int.class, String.class, int.class), recipe, consts));
fail("Return type: StringBuilder",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(StringBuilder.class, String.class, int.class), recipe, consts));
ok("Return type: Object",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Object.class, String.class, int.class), recipe, consts));
ok("Return type: CharSequence",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(CharSequence.class, String.class, int.class), recipe, consts));
ok("Return type: Serializable",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(Serializable.class, String.class, int.class), recipe, consts));
}
// Simple factory: check for dynamic arguments overflow
ok("Dynamic arguments is under limit",
() -> StringConcatFactory.makeConcat(lookup, methodName, mtUnderThreshold));
ok("Dynamic arguments is at the limit",
() -> StringConcatFactory.makeConcat(lookup, methodName, mtThreshold));
fail("Dynamic arguments is over the limit",
() -> StringConcatFactory.makeConcat(lookup, methodName, mtOverThreshold));
// Advanced factory: check for dynamic arguments overflow
ok("Dynamic arguments is under limit",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtUnderThreshold, recipeUnderThreshold, constants[0]));
ok("Dynamic arguments is at the limit",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold, constants[0]));
fail("Dynamic arguments is over the limit",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtOverThreshold, recipeOverThreshold, constants[0]));
// Advanced factory: check for mismatched recipe and Constants
ok("Static arguments and recipe match",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold, "bar"));
fail("Static arguments and recipe mismatch: too few",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold));
fail("Static arguments and recipe mismatch: too many",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold, "bar", "baz"));
failNPE("Static arguments and recipe mismatch, too many, overflowing constant is null",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold, "bar", null));
// Advanced factory: check for mismatched recipe and dynamic arguments
fail("Dynamic arguments and recipe mismatch",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeUnderThreshold, constants[0]));
ok("Dynamic arguments and recipe match",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeThreshold, constants[0]));
fail("Dynamic arguments and recipe mismatch",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtThreshold, recipeOverThreshold, constants[0]));
// Test passing array as constant
{
Object[] arg = {"boo", "bar"};
CallSite cs1 = StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(String.class, int.class), "" + TAG_ARG + TAG_CONST + TAG_CONST, arg);
test("42boobar", (String) cs1.getTarget().invokeExact(42));
}
// Test passing null constant
ok("Can pass regular constants",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(String.class, int.class), "" + TAG_ARG + TAG_CONST, "foo"));
failNPE("Cannot pass null constants",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, MethodType.methodType(String.class, int.class), "" + TAG_ARG + TAG_CONST, new Object[]{null}));
// Simple factory: test empty arguments
ok("Ok to pass empty arguments",
() -> StringConcatFactory.makeConcat(lookup, methodName, mtEmpty));
// Advanced factory: test empty arguments
ok("Ok to pass empty arguments",
() -> StringConcatFactory.makeConcatWithConstants(lookup, methodName, mtEmpty, recipeEmpty));
// Simple factory: public Lookup is rejected
fail("Passing public Lookup",
() -> StringConcatFactory.makeConcat(MethodHandles.publicLookup(), methodName, mtEmpty));
// Advanced factory: public Lookup is rejected
fail("Passing public Lookup",
() -> StringConcatFactory.makeConcatWithConstants(MethodHandles.publicLookup(), methodName, mtEmpty, recipeEmpty));
// Zero inputs
{
MethodType zero = MethodType.methodType(String.class);
CallSite cs = StringConcatFactory.makeConcat(lookup, methodName, zero);
test("", (String) cs.getTarget().invokeExact());
cs = StringConcatFactory.makeConcatWithConstants(lookup, methodName, zero, "");
test("", (String) cs.getTarget().invokeExact());
}
// One input
{
MethodType zero = MethodType.methodType(String.class);
MethodType one = MethodType.methodType(String.class, String.class);
CallSite cs = StringConcatFactory.makeConcat(lookup, methodName, one);
test("A", (String) cs.getTarget().invokeExact("A"));
cs = StringConcatFactory.makeConcatWithConstants(lookup, methodName, one, "\1");
test("A", (String) cs.getTarget().invokeExact("A"));
cs = StringConcatFactory.makeConcatWithConstants(lookup, methodName, zero, "\2", "A");
test("A", (String) cs.getTarget().invokeExact());
}
}
public static void ok(String msg, Callable runnable) {
try {
runnable.call();
} catch (Throwable e) {
e.printStackTrace();
throw new IllegalStateException(msg + ", should have passed", e);
}
}
public static void fail(String msg, Callable runnable) {
boolean expected = false;
try {
runnable.call();
} catch (StringConcatException e) {
expected = true;
} catch (Throwable e) {
e.printStackTrace();
}
if (!expected) {
throw new IllegalStateException(msg + ", should have failed with StringConcatException");
}
}
public static void failNPE(String msg, Callable runnable) {
boolean expected = false;
try {
runnable.call();
} catch (NullPointerException e) {
expected = true;
} catch (Throwable e) {
e.printStackTrace();
}
if (!expected) {
throw new IllegalStateException(msg + ", should have failed with NullPointerException");
}
}
public static void test(String expected, String actual) {
// Fingers crossed: String concat should work.
if (!expected.equals(actual)) {
StringBuilder sb = new StringBuilder();
sb.append("Expected = ");
sb.append(expected);
sb.append(", actual = ");
sb.append(actual);
throw new IllegalStateException(sb.toString());
}
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.StringConcatFactory;
/**
* @test
* @summary StringConcatFactory allow recipes with repeated constants, but this
* is not expressible with java code and needs an explicit sanity test
* @bug 8222852
*
* @compile StringConcatFactoryRepeatedConstants.java
*
* @run main/othervm -Xverify:all StringConcatFactoryRepeatedConstants
*/
public class StringConcatFactoryRepeatedConstants {
public static void main(String[] args) throws Throwable {
CallSite site = StringConcatFactory.makeConcatWithConstants(
MethodHandles.lookup(),
"foo",
MethodType.methodType(String.class),
"\u0002\u0002",
"foo", "bar"
);
String string = (String)site.dynamicInvoker().invoke();
if (!"foobar".equals(string)) {
throw new IllegalStateException("Expected: foobar, got: " + string);
}
site = StringConcatFactory.makeConcatWithConstants(
MethodHandles.lookup(),
"foo",
MethodType.methodType(String.class),
"\u0002\u0002test\u0002\u0002",
"foo", 17.0f, 4711L, "bar"
);
string = (String)site.dynamicInvoker().invoke();
StringBuilder sb = new StringBuilder();
sb.append("foo").append(17.0f).append("test").append(4711L).append("bar");
if (!sb.toString().equals(string)) {
throw new IllegalStateException("Expected: " + sb.toString() + ", got: " + string);
}
}
}

View file

@ -0,0 +1,26 @@
# Copyright (c) 2015, 2016, 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
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#!/bin/bash
javac ImplicitStringConcatShapesTestGen.java
java ImplicitStringConcatShapesTestGen > ImplicitStringConcatShapes.java
rm ImplicitStringConcatShapesTestGen.class