Why does IndexOutOfBoundsException now have a constructor with a long index as a parameter in Java 16? Why does IndexOutOfBoundsException now have a constructor with a long index as a parameter in Java 16? arrays arrays

Why does IndexOutOfBoundsException now have a constructor with a long index as a parameter in Java 16?


Quoting from the comments for future reference:

This was precipitated by Project Panama, which brings better nativeheap access to Java. The Foreign Memory API (a replacement for directbyte buffers) allows long-indexed heap access to native memorysegments, motivating this change to IOOBE. – Brian Goetz

TL;DR It is related with the following feature Enhancement (JDK-8255150) : Add utility methods to check long indexes and ranges

Description
This is related to JDK-8135248. The goal is to add asimilar set of methods but rather than operate on int arguments, thenew methods operate on long arguments.

The new methods in Objects are:

public static long checkIndex(long index, long length) public staticlong checkFromToIndex(long fromIndex, long toIndex, long length)public static long checkFromIndexSize(long fromIndex, long size, longlength)

They mirror the int utility methods.

As is the case with the int checkIndex(), the long checkIndex() methodwill be JIT compiled as an intrinsic. That allows the JIT to compilecheckIndex to an unsigned comparison and properly recognize it asrange check that then becomes a candidate for the existing range checkoptimizations. This has proven to be important for panama'sMemorySegment and a prototype of this change (with some extra c2improvements) showed that panama micro benchmark results improvesignificantly.

From another source about the subject : JDK 16: Checking Indexes and Ranges of Longs:

In my last post, I described the day period support added with JDK 16Early Access Build 25. That same build also added methods for checkingindexes and ranges of long values, which is the subject of this post.JDK-8255150 (“Add utility methods to check long indexes and ranges”)is the Enhancement used to add utility methods for checking longindexes and ranges similar to what JDK-8135248 (“Add utility methodsto check indexes and ranges”) added for integers with JDK 9.JDK-8255150 states, “The goal is to add a similar set of methods [asJDK-8135248] but rather than operate on int arguments, the new methodsoperate on long arguments.”

The greatest beneficiary of these newly added long-supporting methodsmay be the authors, maintainers, and users of the foreign memoryaccess API as described in this mailing list message: “We have to jumpthrough quite a few hoops in the implementation of the foreign memoryaccess API in order to leverage the intrinsification of int-basedindex checks, and even then we are not covering the cases where thenumbers are larger than ints. Looking forward to being able to removethose hacks!”


I have found another Ticket in OpenJdk which is relevant to that change. As stated there

Bounds checking is not difficult to write explicitly but it can beeasy to make trivial mistakes, such as introducing overflow bugs. Itis advantageous to consolidate such checks from a correctness andsecurity/integrity perspective. Further more in certain cases it is anopportunity to optimize, via an intrinsic, certain checks and guidehotspot towards unsigned comparisons.

Enhancements to the Java platform will enable optimizations of loopsover bounds greater than the minimum and maximum range of int values,requiring bounds checking operating on long values.

In the Foreign Memory Access API (JEP 393), the bounds of a memorysegments are expressed as long values. Since bound checks involvinglongs are not currently optimized, the implementation of the foreignmemory access API had to resort to several tricks to gauge whether amemory segment can be considered "small" (e.g. whose size fits in anint value) and then use int operations on small segments, accordingly.While in most cases, these workarounds are hidden inside the APIimplementation, they add a significant cost in terms of complexity andlong term maintenance.

Solution Overload the existing int accepting bounds check methodsdefined in java.util.Objects with long accepting bounds check methods.

The following static methods are added to java.util.Objects. The specification is identical to that of the existing int accepting bounds check methods of the same method name.

/** * Checks if the {@code index} is within the bounds of the range from * {@code 0} (inclusive) to {@code length} (exclusive). * * <p>The {@code index} is defined to be out of bounds if any of the * following inequalities is true: * <ul> *  <li>{@code index < 0}</li> *  <li>{@code index >= length}</li> *  <li>{@code length < 0}, which is implied from the former inequalities</li> * </ul> * * @param index the index * @param length the upper-bound (exclusive) of the range * @return {@code index} if it is within bounds of the range     * @throws IndexOutOfBoundsException if the {@code index} is out of bounds   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^      * @since 16 */public staticlong checkIndex(long index, long length)/** * Checks if the sub-range from {@code fromIndex} (inclusive) to * {@code toIndex} (exclusive) is within the bounds of range from {@code 0} * (inclusive) to {@code length} (exclusive). * * <p>The sub-range is defined to be out of bounds if any of the following * inequalities is true: * <ul> *  <li>{@code fromIndex < 0}</li> *  <li>{@code fromIndex > toIndex}</li> *  <li>{@code toIndex > length}</li> *  <li>{@code length < 0}, which is implied from the former inequalities</li> * </ul> * * @param fromIndex the lower-bound (inclusive) of the sub-range * @param toIndex the upper-bound (exclusive) of the sub-range * @param length the upper-bound (exclusive) the range * @return {@code fromIndex} if the sub-range within bounds of the range * @throws IndexOutOfBoundsException if the sub-range is out of bounds   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * @since 16 */public staticlong checkFromToIndex(long fromIndex, long toIndex, long length)/** * Checks if the sub-range from {@code fromIndex} (inclusive) to * {@code fromIndex + size} (exclusive) is within the bounds of range from * {@code 0} (inclusive) to {@code length} (exclusive). * * <p>The sub-range is defined to be out of bounds if any of the following * inequalities is true: * <ul> *  <li>{@code fromIndex < 0}</li> *  <li>{@code size < 0}</li> *  <li>{@code fromIndex + size > length}, taking into account integer overflow</li> *  <li>{@code length < 0}, which is implied from the former inequalities</li> * </ul> * * @param fromIndex the lower-bound (inclusive) of the sub-interval * @param size the size of the sub-range * @param length the upper-bound (exclusive) of the range * @return {@code fromIndex} if the sub-range within bounds of the range * @throws IndexOutOfBoundsException if the sub-range is out of bounds   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * @since 16 */public staticlong checkFromIndexSize(long fromIndex, long size, long length)

The following constructor is added to java.lang.IndexOutOfBoundsException:

/** * Constructs a new {@code IndexOutOfBoundsException} class with an * argument indicating the illegal index. * * <p>The index is included in this exception's detail message.  The * exact presentation format of the detail message is unspecified. * * @param index the illegal index. * @since 16 */public IndexOutOfBoundsException(long index)

Jira Issue: Add utility methods to check long indexes and ranges


An IndexOutOfBoundsException is not necessarily thrown only when accessing an array (there is the subclass ArrayIndexOutOfBoundsException for that) or a List; you can throw it from any of your own code, and it seems reasonable to allow user-written classes or third-party libraries to throw IndexOutOfBoundsException even if their indices are long rather than int.