From: <jik...@li...> - 2012-10-13 00:21:13
|
details: http://hg.code.sourceforge.net/p/jikesrvm/codecode/rev/f468849b03fa changeset: 10552:f468849b03fa user: Dave Grove <gr...@us...> date: Fri Oct 12 20:21:01 2012 -0400 description: Big fixes in annotation processing for empty arrays ({}). The existing code was buggy in two ways (a) if the type was known, it was creating a T[][] instead of a T[] and (b) if the type was unknown it was blindly creating an Object[], which results in a runtime checkcast failure when the annotation tried to read the value. Thanks to Matt Brown and Jens Palsberg at UCLA for the test case. diffstat: rvm/src/org/jikesrvm/classloader/RVMAnnotation.java | 17 +++++++++++++---- 1 files changed, 13 insertions(+), 4 deletions(-) diffs (34 lines): diff --git a/rvm/src/org/jikesrvm/classloader/RVMAnnotation.java b/rvm/src/org/jikesrvm/classloader/RVMAnnotation.java --- a/rvm/src/org/jikesrvm/classloader/RVMAnnotation.java +++ b/rvm/src/org/jikesrvm/classloader/RVMAnnotation.java @@ -232,7 +232,7 @@ int numValues = input.readUnsignedShort(); if (numValues == 0) { if (type != null) { - value = Array.newInstance(type.resolve().getClassForType(), 0); + value = Array.newInstance(type.getArrayElementType().resolve().getClassForType(), 0); } else { value = new Object[0]; } @@ -651,9 +651,18 @@ value = RVMAnnotation.readValue(meth.getReturnType(), constantPool, input, classLoader); } else { value = RVMAnnotation.readValue(null, constantPool, input, classLoader); - meth = MemberReference.findOrCreate(type, name, - Atom.findOrCreateAsciiAtom("()"+TypeReference.findOrCreate(value.getClass()).getName()) - ).asMethodReference(); + if (value instanceof Object[] && ((Object[])value).length == 0) { + // We blindly guessed Object[] in readValue. + // No choice but to force type to be resolved so we actually + // create an empty array of the appropriate type. + meth = type.resolve().asClass().findDeclaredMethod(name).getMemberRef().asMethodReference(); + value = Array.newInstance(meth.getReturnType().getArrayElementType().resolve().getClassForType(), 0); + } else { + // Reading the value lets us make a MemberReference that is likely to be correct. + meth = MemberReference.findOrCreate(type, name, + Atom.findOrCreateAsciiAtom("()"+TypeReference.findOrCreate(value.getClass()).getName()) + ).asMethodReference(); + } } return new AnnotationMember(meth, value); } |