The problem I have discovered is that
AnnotationVisitor.visit(String name, Object value)
is being called with incorrect value objects. According to the specification,
name is the name of the primitive value of the annotation with the given value.
As the specification states, value must be of a primitive type. However, I
have found that array types are being passed into this method, so that the type
of value is "int[" or rather,
value.getClass().getComponentType() returns int.class. I believe the proper
way to have an AnnotationVisitor visit an array value is to call
visitArray(name) and have the AnnotationVisitor that is returned visit the
array values in order. Looking at ClassReader.java (from version 2.2.2, I
believe, but I have discovered the same flaw in the 3.0_RC1 distribution), in
readAnnotationValue(...), the last case after primitives, enum, class tokens
and annotations, is array values, which are special cased depending on the base
type of the array as follows:
case '[': // array_value
int size = readUnsignedShort(v);
v += 2;
if (size == 0) {
av.visitArray(name).visitEnd();
return v;
}
switch (readByte(v++)) {
case 'B':
byte[] bv = new byte[size];
for (i = 0; i < size; i++) {
bv[i] = (byte) readInt(items[readUnsignedShort(v)]);
v += 3;
}
av.visit(name, bv);
--v;
break;
// ... extra cases ...
default:
v--;
AnnotationVisitor aav = av.visitArray(name);
for (i = size; i > 0; --i) {
v = readAnnotationValue(v, buf, null, aav);
}
aav.visitEnd();
Here, bv is clearly of type byte[], rather than of the primitive type byte.
The 0-element array case is handled correctly. I believe the default in the
switch statement is what should be called for all arrays, and I'm not sure what
the other cases are doing, since they all should be doing exactly what the
default case is doing. Or am I misunderstanding something in the documentation?