diff --git a/src/share/classes/java/lang/System.java b/src/share/classes/java/lang/System.java index c7f69f5e49660adda8844073e0d73601f2bac4fa..bd72188c6b03e7065c24ac463b245306e28d6f90 100644 --- a/src/share/classes/java/lang/System.java +++ b/src/share/classes/java/lang/System.java @@ -1246,6 +1246,9 @@ public final class System { public StackTraceElement getStackTraceElement(Throwable t, int i) { return t.getStackTraceElement(i); } + public String newStringUnsafe(char[] chars) { + return new String(chars, true); + } }); } } diff --git a/src/share/classes/sun/misc/JavaLangAccess.java b/src/share/classes/sun/misc/JavaLangAccess.java index db8d8213179bee2c0d142dbc8e657dc5ac64eac7..888d4ea8c46427039e91e0da0dee5f74eb328c62 100644 --- a/src/share/classes/sun/misc/JavaLangAccess.java +++ b/src/share/classes/sun/misc/JavaLangAccess.java @@ -97,4 +97,14 @@ public interface JavaLangAccess { * Returns the ith StackTraceElement for the given throwable. */ StackTraceElement getStackTraceElement(Throwable t, int i); + + /** + * Returns a new string backed by the provided character array. The + * character array is not copied and must never be modified after the + * String is created, in order to fulfill String's contract. + * + * @param chars the character array to back the string + * @return a newly created string whose content is the character array + */ + String newStringUnsafe(char[] chars); } diff --git a/test/sun/misc/JavaLangAccess/NewUnsafeString.java b/test/sun/misc/JavaLangAccess/NewUnsafeString.java new file mode 100644 index 0000000000000000000000000000000000000000..930d57bee80f52f07d0c5d0fe4999e8ca21e8112 --- /dev/null +++ b/test/sun/misc/JavaLangAccess/NewUnsafeString.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2012, 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.util.Objects; +import java.util.Comparators; +import sun.misc.JavaLangAccess; +import sun.misc.SharedSecrets; + +/* + * @test + * @summary Test JavaLangAccess.newUnsafeString + * @bug 8013528 + * @compile -XDignore.symbol.file NewUnsafeString.java + */ +public class NewUnsafeString { + + static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); + + public static void testNewUnsafeString() { + String benchmark = "exemplar"; + String constructorCopy = new String(benchmark); + char[] jlaChars = benchmark.toCharArray(); + String jlaCopy = jla.newStringUnsafe(jlaChars); + + if (benchmark == constructorCopy) { + throw new Error("should be different instances"); + } + if (!benchmark.equals(constructorCopy)) { + throw new Error("Copy not equal"); + } + if (0 != Objects.compare(benchmark, constructorCopy, Comparators.naturalOrder())) { + throw new Error("Copy not equal"); + } + + if (benchmark == jlaCopy) { + throw new Error("should be different instances"); + } + if (!benchmark.equals(jlaCopy)) { + throw new Error("Copy not equal"); + } + if (0 != Objects.compare(benchmark, jlaCopy, Comparators.naturalOrder())) { + throw new Error("Copy not equal"); + } + + if (constructorCopy == jlaCopy) { + throw new Error("should be different instances"); + } + if (!constructorCopy.equals(jlaCopy)) { + throw new Error("Copy not equal"); + } + if (0 != Objects.compare(constructorCopy, jlaCopy, Comparators.naturalOrder())) { + throw new Error("Copy not equal"); + } + + // The following is extremely "evil". Never ever do this in non-test code. + jlaChars[0] = 'X'; + if (!"Xxemplar".equals(jlaCopy)) { + throw new Error("jla.newStringUnsafe did not use provided string"); + } + + } + + public static void main(String[] args) { + testNewUnsafeString(); + } +}