Skip to content

8356439: Rename JavaLangAccess::*NoRepl methods #26413

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/java.base/share/classes/java/io/DataInputStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ public static final String readUTF(DataInput in) throws IOException {
if (ascii == utflen) {
String str;
if (trusted) {
str = JLA.uncheckedNewStringNoRepl(bytearr, StandardCharsets.ISO_8859_1);
str = JLA.uncheckedNewString(bytearr, StandardCharsets.ISO_8859_1);
} else {
str = new String(bytearr, 0, utflen, StandardCharsets.ISO_8859_1);
}
Expand Down
168 changes: 102 additions & 66 deletions src/java.base/share/classes/java/lang/String.java
Original file line number Diff line number Diff line change
Expand Up @@ -557,7 +557,7 @@ private String(Charset charset, byte[] bytes, int offset, int length) {
if (length == 0) {
str = "";
} else if (charset == UTF_8.INSTANCE) {
str = utf8(bytes, offset, length);
str = utf8ThrowingIae(bytes, offset, length);
} else if (charset == ISO_8859_1.INSTANCE) {
str = iso88591(bytes, offset, length);
} else if (charset == US_ASCII.INSTANCE) {
Expand All @@ -568,7 +568,35 @@ private String(Charset charset, byte[] bytes, int offset, int length) {
this(str);
}

private static String utf8(byte[] bytes, int offset, int length) {
private static String utf8ThrowingIae(byte[] bytes, int offset, int length) {
try {
return utf8(bytes, offset, length);
} catch (CharacterCodingException cce) {
throw cce2iae(cce);
}
}

private static IllegalArgumentException cce2iae(CharacterCodingException cce) {
Throwable cause = cce.getCause();
// If the CCE is caused by an IAE, it implies that IAE is injected by
// us to provide more context into CCE. Try swapping them to obtain an
// IAE caused by a CCE.
if (cause instanceof IllegalArgumentException iae) {
if (cce instanceof MalformedInputException mie) {
return new IllegalArgumentException(
iae.getMessage(),
new MalformedInputException(mie.getInputLength()));
}
if (cce instanceof UnmappableCharacterException uce) {
return new IllegalArgumentException(
iae.getMessage(),
new UnmappableCharacterException(uce.getInputLength()));
}
}
return new IllegalArgumentException(cce);
}

private static String utf8(byte[] bytes, int offset, int length) throws CharacterCodingException {
if (COMPACT_STRINGS) {
int dp = StringCoding.countPositives(bytes, offset, length);
if (dp == length) {
Expand Down Expand Up @@ -689,15 +717,22 @@ private static String decode(Charset charset, byte[] bytes, int offset, int leng
}

/*
* Throws iae, instead of replacing, if malformed or unmappable.
* {@return a new string by decoding from the given UTF-8 bytes array}
*
* @param offset the index of the first byte to decode
* @param length the number of bytes to decode
* @param noShare
* {@code true} if the resulting string MUST NOT share the byte array,
* {@code false} if the byte array can be exclusively used to construct
* the string and is not modified or used for any other purpose.
* @throws NullPointerException If {@code bytes} is null
* @throws StringIndexOutOfBoundsException If {@code offset} is negative,
* {@code length} is negative, or {@code offset} is greater than
* {@code bytes.length - length}
* @throws CharacterCodingException for malformed input or unmappable characters
*/
static String newStringUTF8NoRepl(byte[] bytes, int offset, int length, boolean noShare) {
checkBoundsOffCount(offset, length, bytes.length);
static String newStringUTF8(byte[] bytes, int offset, int length, boolean noShare) throws CharacterCodingException {
checkBoundsOffCount(offset, length, bytes.length); // Implicit null check on `bytes`
if (length == 0) {
return "";
}
Expand Down Expand Up @@ -759,26 +794,13 @@ static String newStringUTF8NoRepl(byte[] bytes, int offset, int length, boolean
return new String(dst, UTF16);
}

static String newStringNoRepl(byte[] src, Charset cs) throws CharacterCodingException {
try {
return newStringNoRepl1(src, cs);
} catch (IllegalArgumentException e) {
//newStringNoRepl1 throws IAE with MalformedInputException or CCE as the cause
Throwable cause = e.getCause();
if (cause instanceof MalformedInputException mie) {
throw mie;
}
throw (CharacterCodingException)cause;
}
}

private static String newStringNoRepl1(byte[] src, Charset cs) {
static String newString(byte[] src, Charset cs) throws CharacterCodingException {
int len = src.length;
if (len == 0) {
return "";
}
if (cs == UTF_8.INSTANCE) {
return newStringUTF8NoRepl(src, 0, src.length, false);
return newStringUTF8(src, 0, src.length, false);
}
if (cs == ISO_8859_1.INSTANCE) {
if (COMPACT_STRINGS)
Expand Down Expand Up @@ -806,13 +828,7 @@ private static String newStringNoRepl1(byte[] src, Charset cs) {
}
int en = scale(len, cd.maxCharsPerByte());
char[] ca = new char[en];
int caLen;
try {
caLen = decodeWithDecoder(cd, ca, src, 0, src.length);
} catch (CharacterCodingException x) {
// throw via IAE
throw new IllegalArgumentException(x);
}
int caLen = decodeWithDecoder(cd, ca, src, 0, src.length);
if (COMPACT_STRINGS) {
byte[] val = StringUTF16.compress(ca, 0, caLen);
byte coder = StringUTF16.coderFromArrayLen(val, caLen);
Expand Down Expand Up @@ -847,7 +863,7 @@ private static Charset lookupCharset(String csn) throws UnsupportedEncodingExcep
}
}

private static byte[] encode(Charset cs, byte coder, byte[] val) {
private static byte[] encode(Charset cs, byte coder, byte[] val) throws CharacterCodingException {
if (cs == UTF_8.INSTANCE) {
return encodeUTF8(coder, val, true);
}
Expand All @@ -860,7 +876,7 @@ private static byte[] encode(Charset cs, byte coder, byte[] val) {
return encodeWithEncoder(cs, coder, val, true);
}

private static byte[] encodeWithEncoder(Charset cs, byte coder, byte[] val, boolean doReplace) {
private static byte[] encodeWithEncoder(Charset cs, byte coder, byte[] val, boolean doReplace) throws CharacterCodingException {
CharsetEncoder ce = cs.newEncoder();
int len = val.length >> coder; // assume LATIN1=0/UTF16=1;
int en = scale(len, ce.maxBytesPerChar());
Expand Down Expand Up @@ -905,42 +921,45 @@ private static byte[] encodeWithEncoder(Charset cs, byte coder, byte[] val, bool
cr.throwException();
} catch (CharacterCodingException x) {
if (!doReplace) {
throw new IllegalArgumentException(x);
throw x;
} else {
throw new Error(x);
}
}
return trimArray(ba, bb.position());
}

/*
* Throws iae, instead of replacing, if unmappable.
/**
* {@return the sequence of bytes obtained by encoding the given string in UTF-8}
*
* @param s the string to encode
* @throws NullPointerException If {@code s} is null
* @throws CharacterCodingException For malformed input or unmappable characters
*/
static byte[] getBytesUTF8NoRepl(String s) {
return encodeUTF8(s.coder(), s.value(), false);
static byte[] getBytesUTF8(String s) throws CharacterCodingException {
return encodeUTF8(s.coder(), s.value(), false); // Implicit null check on `s`
}

private static boolean isASCII(byte[] src) {
return !StringCoding.hasNegatives(src, 0, src.length);
}

/*
* Throws CCE, instead of replacing, if unmappable.
/**
* {@return the sequence of bytes obtained by encoding the given string in
* the specified {@linkplain java.nio.charset.Charset charset}}
* <p>
* <b>WARNING: This method returns the {@code byte[]} backing the provided
* {@code String}, if the input is ASCII. Hence, the returned byte array
* must not be modified.</b>
*
* @param s the string to encode
* @param cs the charset
* @throws NullPointerException If {@code s} or {@code cs} is null
* @throws CharacterCodingException For malformed input or unmappable characters
*/
static byte[] getBytesNoRepl(String s, Charset cs) throws CharacterCodingException {
try {
return getBytesNoRepl1(s, cs);
} catch (IllegalArgumentException e) {
//getBytesNoRepl1 throws IAE with UnmappableCharacterException or CCE as the cause
Throwable cause = e.getCause();
if (cause instanceof UnmappableCharacterException) {
throw (UnmappableCharacterException)cause;
}
throw (CharacterCodingException)cause;
}
}

private static byte[] getBytesNoRepl1(String s, Charset cs) {
static byte[] getBytes(String s, Charset cs) throws CharacterCodingException {
Objects.requireNonNull(s, "s");
Objects.requireNonNull(cs, "cs");
byte[] val = s.value();
byte coder = s.coder();
if (cs == UTF_8.INSTANCE) {
Expand Down Expand Up @@ -1005,11 +1024,11 @@ private static void replaceNegatives(byte[] val, int fromIndex) {
}
}

private static byte[] encode8859_1(byte coder, byte[] val) {
private static byte[] encode8859_1(byte coder, byte[] val) throws UnmappableCharacterException {
return encode8859_1(coder, val, true);
}

private static byte[] encode8859_1(byte coder, byte[] val, boolean doReplace) {
private static byte[] encode8859_1(byte coder, byte[] val, boolean doReplace) throws UnmappableCharacterException {
if (coder == LATIN1) {
return val.clone();
}
Expand Down Expand Up @@ -1118,7 +1137,8 @@ private static int decode4(int b1, int b2, int b3, int b4) {
((byte) 0x80 << 0))));
}

private static int decodeUTF8_UTF16(byte[] src, int sp, int sl, byte[] dst, int dp, boolean doReplace) {
private static int decodeUTF8_UTF16(byte[] src, int sp, int sl, byte[] dst, int dp, boolean doReplace)
throws CharacterCodingException {
while (sp < sl) {
int b1 = src[sp++];
if (b1 >= 0) {
Expand Down Expand Up @@ -1259,27 +1279,31 @@ private static int malformed4(byte[] src, int sp) {
return 3;
}

private static void throwMalformed(int off, int nb) {
private static void throwMalformed(int off, int nb) throws MalformedInputException {
MalformedInputException mie = new MalformedInputException(nb);
String msg = "malformed input off : " + off + ", length : " + nb;
throw new IllegalArgumentException(msg, new MalformedInputException(nb));
mie.initCause(new IllegalArgumentException(msg));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Earlier throw(Malformed|Unmappable) methods were throwing IAE containing extra diagnostics information and wrapping a CCE as a cause. After switching methods to throw CCE, which doesn't have a ctor accepting a String message, to retain this extra diagnostics information, I've added swapped their causal chain placement, and wrapped IAE with a CCE this time.

This played well with CCE-throwing methods, yet there are other public methods which did not have throws CCE in their footprint. For backward compatibility, in those spots, I've used cce2iae to obtain, again, a IAE wrapping the CCE, which matched the old behavior.

throw mie;
}

private static void throwMalformed(byte[] val) {
private static void throwMalformed(byte[] val) throws MalformedInputException {
int dp = StringCoding.countPositives(val, 0, val.length);
throwMalformed(dp, 1);
}

private static void throwUnmappable(int off) {
private static void throwUnmappable(int off) throws UnmappableCharacterException {
UnmappableCharacterException uce = new UnmappableCharacterException(1);
String msg = "malformed input off : " + off + ", length : 1";
throw new IllegalArgumentException(msg, new UnmappableCharacterException(1));
uce.initCause(new IllegalArgumentException(msg, uce));
throw uce;
}

private static void throwUnmappable(byte[] val) {
private static void throwUnmappable(byte[] val) throws UnmappableCharacterException {
int dp = StringCoding.countPositives(val, 0, val.length);
throwUnmappable(dp);
}

private static byte[] encodeUTF8(byte coder, byte[] val, boolean doReplace) {
private static byte[] encodeUTF8(byte coder, byte[] val, boolean doReplace) throws UnmappableCharacterException {
if (coder == UTF16) {
return encodeUTF8_UTF16(val, doReplace);
}
Expand All @@ -1304,7 +1328,7 @@ private static byte[] encodeUTF8(byte coder, byte[] val, boolean doReplace) {
return Arrays.copyOf(dst, dp);
}

private static byte[] encodeUTF8_UTF16(byte[] val, boolean doReplace) {
private static byte[] encodeUTF8_UTF16(byte[] val, boolean doReplace) throws UnmappableCharacterException {
int dp = 0;
int sp = 0;
int sl = val.length >> 1;
Expand Down Expand Up @@ -1369,7 +1393,7 @@ private static byte[] encodeUTF8_UTF16(byte[] val, boolean doReplace) {
* @param val UTF16 encoded byte array
* @param doReplace true to replace unmappable characters
*/
private static long computeSizeUTF8_UTF16(byte[] val, boolean doReplace) {
private static long computeSizeUTF8_UTF16(byte[] val, boolean doReplace) throws UnmappableCharacterException {
long dp = 0L;
int sp = 0;
int sl = val.length >> 1;
Expand Down Expand Up @@ -1823,7 +1847,11 @@ public void getBytes(int srcBegin, int srcEnd, byte[] dst, int dstBegin) {
*/
public byte[] getBytes(String charsetName)
throws UnsupportedEncodingException {
return encode(lookupCharset(charsetName), coder(), value);
try {
return encode(lookupCharset(charsetName), coder(), value);
} catch (CharacterCodingException cce) {
throw cce2iae(cce);
}
}

/**
Expand All @@ -1846,8 +1874,12 @@ public byte[] getBytes(String charsetName)
*/
public byte[] getBytes(Charset charset) {
if (charset == null) throw new NullPointerException();
return encode(charset, coder(), value);
}
try {
return encode(charset, coder(), value);
} catch (CharacterCodingException cce) {
throw cce2iae(cce);
}
}

/**
* Encodes this {@code String} into a sequence of bytes using the
Expand All @@ -1864,7 +1896,11 @@ public byte[] getBytes(Charset charset) {
* @since 1.1
*/
public byte[] getBytes() {
return encode(Charset.defaultCharset(), coder(), value);
try {
return encode(Charset.defaultCharset(), coder(), value);
} catch (CharacterCodingException cce) {
throw cce2iae(cce);
}
}

boolean bytesCompatible(Charset charset) {
Expand Down
22 changes: 13 additions & 9 deletions src/java.base/share/classes/java/lang/System.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@
import java.util.ResourceBundle;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Supplier;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;
Expand Down Expand Up @@ -2121,28 +2120,33 @@ public Stream<ModuleLayer> layers(ClassLoader loader) {
public int countPositives(byte[] bytes, int offset, int length) {
return StringCoding.countPositives(bytes, offset, length);
}

public int countNonZeroAscii(String s) {
return StringCoding.countNonZeroAscii(s);
}
public String uncheckedNewStringNoRepl(byte[] bytes, Charset cs) throws CharacterCodingException {
return String.newStringNoRepl(bytes, cs);

public String uncheckedNewString(byte[] bytes, Charset cs) throws CharacterCodingException {
return String.newString(bytes, cs);
}

public char uncheckedGetUTF16Char(byte[] bytes, int index) {
return StringUTF16.getChar(bytes, index);
}

public void uncheckedPutCharUTF16(byte[] bytes, int index, int ch) {
StringUTF16.putChar(bytes, index, ch);
}
public byte[] uncheckedGetBytesNoRepl(String s, Charset cs) throws CharacterCodingException {
return String.getBytesNoRepl(s, cs);

public byte[] uncheckedGetBytes(String s, Charset cs) throws CharacterCodingException {
return String.getBytes(s, cs);
}

public String newStringUTF8NoRepl(byte[] bytes, int off, int len) {
return String.newStringUTF8NoRepl(bytes, off, len, true);
public String newStringUTF8(byte[] bytes, int off, int len) throws CharacterCodingException {
return String.newStringUTF8(bytes, off, len, true);
}

public byte[] getBytesUTF8NoRepl(String s) {
return String.getBytesUTF8NoRepl(s);
public byte[] getBytesUTF8(String s) throws CharacterCodingException {
return String.getBytesUTF8(s);
}

public void inflateBytesToChars(byte[] src, int srcOff, char[] dst, int dstOff, int len) {
Expand Down
2 changes: 1 addition & 1 deletion src/java.base/share/classes/java/math/BigDecimal.java
Original file line number Diff line number Diff line change
Expand Up @@ -4150,7 +4150,7 @@ private String layoutChars(boolean sci) {
buf[highIntSize] = '.';
DecimalDigits.uncheckedPutPairLatin1(buf, highIntSize + 1, lowInt);
try {
return JLA.uncheckedNewStringNoRepl(buf, StandardCharsets.ISO_8859_1);
return JLA.uncheckedNewString(buf, StandardCharsets.ISO_8859_1);
} catch (CharacterCodingException cce) {
throw new AssertionError(cce);
}
Expand Down
Loading