RFR: 8268698: Use Objects.check{Index, FromToIndex, FromIndexSize} where possible [v2]
Yi Yang
yyang at openjdk.java.net
Fri Jun 18 06:10:27 UTC 2021
On Thu, 17 Jun 2021 15:45:47 GMT, Paul Sandoz <psandoz at openjdk.org> wrote:
>> src/java.base/share/classes/java/util/Base64.java line 934:
>>
>>> 932: if (closed)
>>> 933: throw new IOException("Stream is closed");
>>> 934: Preconditions.checkFromIndexSize(len, off, b.length, (xa, xb) -> new ArrayIndexOutOfBoundsException());
>>
>> You might want to split this really long line too, to avoid inconsistent line length in this source file.
>
> I would suggest factoring out `(xa, xb) -> new ArrayIndexOutOfBoundsException()` as a reusable component on `Preconditions`, and maybe even supplying an exception message (since it is rather useful, and way better than no message).
>
> See the usages of `Preconditions.outOfBoundsExceptionFormatter` (where there just happens to be many repeated cases of supplying AIOOBE with a message, that could also be consolidated, separate fix perhaps).
Ok, I've replaced
Preconditions.checkFromIndexSize(len, off, b.length, (xa, xb) -> new ArrayIndexOutOfBoundsException());
with
Preconditions.checkFromIndexSize(len, off, b.length,
Preconditions.outOfBoundsExceptionFormatter(ArrayIndexOutOfBoundsException::new));
----
I am curious about the motivations of current APIs:
public static <X extends RuntimeException>
int checkIndex(int index, int length,
BiFunction<String, List<Number>, X> oobef) {
if (index < 0 || index >= length)
throw outOfBoundsCheckIndex(oobef, index, length);
return index;
}
Are they over-engineered? When I checked all checkIndex-like patterns in the whole jdk codebase, I found that in most cases, providing an API that accepts custom exception should be enough for scalability:
int checkIndex(int index, int length, IndexOutOfBoundException iooe) {
if (index < 0 || index >= length)
throw iooe;
return index;
}
In addition to the ease-of-use problem, there is another problem with the current API design.
Some methods in j.l.String are good replacement candidates for Preconditions.check{Index,...}:
https://github.com/openjdk/jdk/blob/a051e735cda0d5ee5cb6ce0738aa549a7319a28c/src/java.base/share/classes/java/lang/String.java#L4558-L4604
But we **can not** do such replacement after my practice.
The third parameter of Preconditions.checkIndex is a BiFunction, which can be passed a lambda as its argument. The generated lambda method exercises many other codes like MethodHandles, j.l.Package, etc, eventually it called j.l.String.checkIndex itself, so if we replace j.l.String.checkIndex with `Preconditions.checkIndex(a,b,(x1,x2)->....)`, a StackOverflowError would occur at VM startup.
If there is an API that accepts user-defined exceptions, I think we can apply Preconditions in more places.
-------------
PR: https://git.openjdk.java.net/jdk/pull/4507
More information about the serviceability-dev
mailing list