Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JVM bug? Cached Object field value cause ArrayIndexOutOfBoundsException

This is kind of strange, but code speaks more then words, so look at the test to see what I'm doing. In my current setup (Java 7 update 21 on Windows 64 bit) this test fails with ArrayIndexOutOfBoundsException, but replacing the test method code with the commented code, it the works. And I wonder if there is any part of the Java specification that would explain why.

It seems to me, as "michael nesterenko" suggested, that the value of the array field is cached in the stack, before calling the method, and not updated on return from the call. I can't tell if it's a JVM bug or a documented "optimisation". No multi-threading or "magic" involved.

public class TestAIOOB {
    private String[] array = new String[0];
    private int grow(final String txt) {
        final int index = array.length;
        array = Arrays.copyOf(array, index + 1);
        array[index] = txt;
        return index;
    }
    @Test
    public void testGrow() {
        //final int index = grow("test");
        //System.out.println(array[index]);
        System.out.println(array[grow("test")]);
    }
}
like image 970
Sebastien Diot Avatar asked Jun 22 '13 21:06

Sebastien Diot


2 Answers

This is well defined by the Java Language Specification: to evaluate x[y], first x is evaluated, and then y is evaluated. In your case, x evaluates to a String[] with zero elements. Then, y modifies a member variable, and evaluates to 0. Trying to access the 0th element of the already-returned array fails. The fact that the member array changes has no bearing on the array lookup, because we're looking at the String[] that array referenced at the time we evaluated it.

like image 173
amalloy Avatar answered Nov 05 '22 22:11

amalloy


This behavior is mandated by the JLS. Per 15.13.1, "An array access expression is evaluated using the following procedure: First, the array reference expression is evaluated. If this evaluation completes abruptly, then the array access completes abruptly for the same reason and the index expression is not evaluated. Otherwise, the index expression is evaluated. [...]".

like image 33
Michał Kosmulski Avatar answered Nov 05 '22 20:11

Michał Kosmulski