Skip to content

Commit

Permalink
8289908: Skip bounds check for cases when String is constructed from …
Browse files Browse the repository at this point in the history
…entirely used byte[]

Reviewed-by: prr, rriggs, aturbanov
  • Loading branch information
stsypanov authored and prrace committed Jul 18, 2022
1 parent b2010a7 commit efed7a7
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 13 deletions.
29 changes: 19 additions & 10 deletions src/java.base/share/classes/java/lang/String.java
Expand Up @@ -484,7 +484,7 @@ public String(byte[] ascii, int hibyte) {
*/
public String(byte[] bytes, int offset, int length, String charsetName)
throws UnsupportedEncodingException {
this(bytes, offset, length, lookupCharset(charsetName));
this(lookupCharset(charsetName), bytes, checkBoundsOffCount(offset, length, bytes.length), length);
}

/**
Expand Down Expand Up @@ -517,10 +517,18 @@ public String(byte[] bytes, int offset, int length, String charsetName)
*
* @since 1.6
*/
@SuppressWarnings("removal")
public String(byte[] bytes, int offset, int length, Charset charset) {
Objects.requireNonNull(charset);
checkBoundsOffCount(offset, length, bytes.length);
this(Objects.requireNonNull(charset), bytes, checkBoundsOffCount(offset, length, bytes.length), length);
}

/**
* This method does not do any precondition checks on its arguments.
* <p>
* Important: parameter order of this method is deliberately changed in order to
* disambiguate it against other similar methods of this class.
*/
@SuppressWarnings("removal")
private String(Charset charset, byte[] bytes, int offset, int length) {
if (length == 0) {
this.value = "".value;
this.coder = "".coder;
Expand Down Expand Up @@ -1370,7 +1378,7 @@ private static byte[] encodeUTF8_UTF16(byte[] val, boolean doReplace) {
*/
public String(byte[] bytes, String charsetName)
throws UnsupportedEncodingException {
this(bytes, 0, bytes.length, charsetName);
this(lookupCharset(charsetName), bytes, 0, bytes.length);
}

/**
Expand All @@ -1394,7 +1402,7 @@ public String(byte[] bytes, String charsetName)
* @since 1.6
*/
public String(byte[] bytes, Charset charset) {
this(bytes, 0, bytes.length, charset);
this(Objects.requireNonNull(charset), bytes, 0, bytes.length);
}

/**
Expand Down Expand Up @@ -1424,7 +1432,7 @@ public String(byte[] bytes, Charset charset) {
* @since 1.1
*/
public String(byte[] bytes, int offset, int length) {
this(bytes, offset, length, Charset.defaultCharset());
this(Charset.defaultCharset(), bytes, checkBoundsOffCount(offset, length, bytes.length), length);
}

/**
Expand All @@ -1444,7 +1452,7 @@ public String(byte[] bytes, int offset, int length) {
* @since 1.1
*/
public String(byte[] bytes) {
this(bytes, 0, bytes.length);
this(Charset.defaultCharset(), bytes, 0, bytes.length);
}

/**
Expand Down Expand Up @@ -4582,12 +4590,13 @@ static void checkOffset(int offset, int length) {
* Check {@code offset}, {@code count} against {@code 0} and {@code length}
* bounds.
*
* @return {@code offset} if the sub-range within bounds of the range
* @throws StringIndexOutOfBoundsException
* If {@code offset} is negative, {@code count} is negative,
* or {@code offset} is greater than {@code length - count}
*/
static void checkBoundsOffCount(int offset, int count, int length) {
Preconditions.checkFromIndexSize(offset, count, length, Preconditions.SIOOBE_FORMATTER);
static int checkBoundsOffCount(int offset, int count, int length) {
return Preconditions.checkFromIndexSize(offset, count, length, Preconditions.SIOOBE_FORMATTER);
}

/*
Expand Down
2 changes: 1 addition & 1 deletion src/java.base/share/classes/java/util/jar/Manifest.java
Expand Up @@ -336,7 +336,7 @@ private void read(InputStream is, String jarFilename) throws IOException {
lastline = buf;
continue;
}
name = new String(buf, 0, buf.length, UTF_8.INSTANCE);
name = new String(buf, UTF_8.INSTANCE);
lastline = null;
}
Attributes attr = getAttributes(name);
Expand Down
Expand Up @@ -114,7 +114,7 @@ public char[] getData() {
* @return the data as a <code>String</code>
*/
public String getString() {
return new String(data, 0, data.length);
return new String(data);
}


Expand Down
Expand Up @@ -241,7 +241,7 @@ public Object translateBytes(byte[] bytes, DataFlavor flavor, long format,
if (bytes == null || !DataFlavor.javaFileListFlavor.equals(flavor)) {
throw new IOException("data translation failed");
}
String st = new String(bytes, 0, bytes.length, UTF_16LE);
String st = new String(bytes, UTF_16LE);
String[] filenames = st.split("\0");
if( 0 == filenames.length ){
return null;
Expand Down
74 changes: 74 additions & 0 deletions test/micro/org/openjdk/bench/java/lang/StringConstructor.java
@@ -0,0 +1,74 @@
/*
* Copyright (c) 2018, 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.
*/

package micro.org.openjdk.bench.java.lang;

import org.openjdk.jmh.annotations.*;

import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

@Fork(5)
@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 5, time = 5)
@Measurement(iterations = 10, time = 5)
public class StringConstructor {
private byte[] array;

@Setup
public void setup() {
array = "".getBytes(StandardCharsets.UTF_8);
}

@Benchmark
public String newStringFromArray() {
return new String(array);
}

@Benchmark
public String newStringFromArrayWithCharset() {
return new String(array, StandardCharsets.UTF_8);
}

@Benchmark
public String newStringFromArrayWithCharsetName() throws Exception {
return new String(array, StandardCharsets.UTF_8.name());
}

@Benchmark
public String newStringFromRangedArray() {
return new String(array, 0, 0);
}

@Benchmark
public String newStringFromRangedArrayWithCharset() {
return new String(array, 0, 0, StandardCharsets.UTF_8);
}

@Benchmark
public String newStringFromRangedArrayWithCharsetName() throws Exception {
return new String(array, 0, 0, StandardCharsets.UTF_8.name());
}
}

1 comment on commit efed7a7

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.