JDK-8146458 : Improve exception reporting for Objects.checkIndex/checkFromToIndex/checkFromIndexSize
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.util
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2016-01-05
  • Updated: 2019-07-17
  • Resolved: 2016-04-13
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9 Other
9 b115Fixed openjdk7uFixed
Related Reports
Relates :  
Description
Objects.checkIndex/checkFromToIndex/checkFromIndexSize methods check if arguments passed are within bounds, and if not an exception is thrown. That exception can be produced by an additional BiFunction argument that accepts, in certain cases, some but not all bounds arguments. Thus unless capture of additional variables are performed information is lost when producing the exception and a corresponding error message. Further more, it's not possible to reuse a function instance across all methods since information on what bounds checking was performed is also lost. Unfortunately capturing has a cost that cannot currently be reliably elided with escape analysis, therefore it is considered desirable to avoid capture and ensure full fidelity of the bounds arguments and the kind of failed check. 

The current state of affairs is as follows:

1) checkIndex ->reporting index, length
    [index, index +1) is not within [0, length)

2) checkFromToIndex ->reporting fromIndex, toIndex
    [fromIndex, toIndex) is not within [0, length)

3) checkFromIndexSize ->reporting fromIndex, size
    [fromIndex, fromIndex + size) is not within [0, length)

Rather than defining BiFunction<Integer, Integer, RuntimeException> a more "reflective" signature is required to ensure full fidelity of both the check and it's arguments, such as BiFunction<String, List<Integer>>, where the first argument of the function corresponds to the bounds check kind (e.g. the corresponding method name), and the second argument corresponds to the list of bounds values (corresponding to the method arguments, in order).

Given this approach the constructors recently added to IndexOutOfBoundsException, StringIndexOutOfBoundsException and ArrayIndexOutOfBoundsException should be revisited. While convenient in the current context when used in constructor references the constructor arguments are ambiguous.
Comments
With BiFunction<String, List<Integer>> it is possible to write a generic exception reporting function as follows: BiFunction<String, List<Integer>> reporter = (kind, args) -> { String message = null; switch (kind) { case "checkIndex: message = String.format("Index %d out of bounds for length %d", args.get(0), args.get(1)); break; case "checkFromToIndex": message = String.format("Range [%d, %d) out of bounds for length %d", args.get(0), args.get(1), args.get(2)); break; case "checkFromIndexSize": message = String.format("Range [%d, %<d + %d) out of bounds for length %d", args.get(0), args.get(1), args.get(2)); break; case default: } return new IndexOutOfBoundsException(message); };
05-01-2016