ArrayIndexOutOfBoundsException in Java 8 Parameters Reflection

8

I was doing a code with reflection in Java 8 when I came across a strange behavior - an ArrayIndexOutOfBoundsException unexpected. Based on this, I've decided to create a minimal, complete, and verifiable example.

First look at this code:

import java.lang.reflect.Constructor;
import java.lang.reflect.Parameter;

public class BuggyReflection {
    public class Test {
        public Test(Class k) {
        }
    }

    public static void main(String[] args) throws Exception {
        for (Constructor<?> ctor : Test.class.getConstructors()) {
            for (Parameter p : ctor.getParameters()) {
                System.out.println(p.getParameterizedType());
            }
        }
    }
}

Here's the output:

class BuggyReflection
class java.lang.Class

Now, when I change the constructor parameter type from Class to Class<?> :

import java.lang.reflect.Constructor;
import java.lang.reflect.Parameter;

public class BuggyReflection {
    public class Test {
        public Test(Class<?> k) {
        }
    }

    public static void main(String[] args) throws Exception {
        for (Constructor<?> ctor : Test.class.getConstructors()) {
            for (Parameter p : ctor.getParameters()) {
                System.out.println(p.getParameterizedType());
            }
        }
    }
}

Then an unexpected exception occurs:

java.lang.Class<?>
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
    at java.lang.reflect.Parameter.getParameterizedType(Parameter.java:201)
    at BuggyReflection.main(BuggyReflection.java:14)

Am I doing something wrong? I see no point in making this mistake.

Investigating this code a little more:

import java.lang.reflect.Constructor;
import java.util.Arrays;

public class BuggyReflection {
    public class Test {
        public Test(Class k) {
        }
    }

    public static void main(String[] args) throws Exception {
        for (Constructor<?> ctor : Test.class.getConstructors()) {
            System.out.println(Arrays.toString(ctor.getGenericParameterTypes()) + ctor.getParameters().length);
        }
    }
}

Here is the output, demonstrating that for the JVM there are two parameters in the constructor (since this is a non-static inner class):

[class BuggyReflection, class java.lang.Class]2

Now, if I change the Class to Class<?> :

import java.lang.reflect.Constructor;
import java.util.Arrays;

public class BuggyReflection {
    public class Test {
        public Test(Class<?> k) {
        }
    }

    public static void main(String[] args) throws Exception {
        for (Constructor<?> ctor : Test.class.getConstructors()) {
            System.out.println(Arrays.toString(ctor.getGenericParameterTypes()) + ctor.getParameters().length);
        }
    }
}

The result is at least incoherent:

[java.lang.Class<?>]2

Here are the java and javac versions I'm using:

C:\projetos>javac -version
javac 1.8.0_25

C:\projetos>javac -fullversion
javac full version "1.8.0_25-b18"

C:\projetos>java -version
java version "1.8.0_40"
Java(TM) SE Runtime Environment (build 1.8.0_40-b25)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)

C:\projetos>java -fullversion
java full version "1.8.0_40-b25"

I'm strongly inclined to believe that this is a bug in Java, but I wonder if I'm actually doing something wrong or if this exception is somehow foreseen (I did not find anything about it in the documentation).

    
asked by anonymous 18.03.2015 / 15:21

1 answer

4

It's a Java bug:

link

To work around this bug, make sure that Constructor.getGenericParameterTypes() and Constructor.getParameters() return arrays of different sizes. If this occurs, it is deduced that there is the implicit parameter of the missing outer class.

    
19.03.2015 / 12:04