1 /*
2  * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.reflect.annotation;
27 
28 import java.lang.annotation.*;
29 import java.lang.reflect.*;
30 import java.nio.BufferUnderflowException;
31 import java.nio.ByteBuffer;
32 import java.util.*;
33 import java.util.function.Supplier;
34 import java.security.AccessController;
35 import java.security.PrivilegedAction;
36 import jdk.internal.reflect.ConstantPool;
37 
38 import sun.reflect.generics.parser.SignatureParser;
39 import sun.reflect.generics.tree.TypeSignature;
40 import sun.reflect.generics.factory.GenericsFactory;
41 import sun.reflect.generics.factory.CoreReflectionFactory;
42 import sun.reflect.generics.visitor.Reifier;
43 import sun.reflect.generics.scope.ClassScope;
44 
45 /**
46  * Parser for Java programming language annotations.  Translates
47  * annotation byte streams emitted by compiler into annotation objects.
48  *
49  * @author  Josh Bloch
50  * @since   1.5
51  */
52 public class AnnotationParser {
53     /**
54      * Parses the annotations described by the specified byte array.
55      * resolving constant references in the specified constant pool.
56      * The array must contain an array of annotations as described
57      * in the RuntimeVisibleAnnotations_attribute:
58      *
59      *   u2 num_annotations;
60      *   annotation annotations[num_annotations];
61      *
62      * @throws AnnotationFormatError if an annotation is found to be
63      *         malformed.
64      */
parseAnnotations( byte[] rawAnnotations, ConstantPool constPool, Class<?> container)65     public static Map<Class<? extends Annotation>, Annotation> parseAnnotations(
66                 byte[] rawAnnotations,
67                 ConstantPool constPool,
68                 Class<?> container) {
69         if (rawAnnotations == null)
70             return Collections.emptyMap();
71 
72         try {
73             return parseAnnotations2(rawAnnotations, constPool, container, null);
74         } catch(BufferUnderflowException e) {
75             throw new AnnotationFormatError("Unexpected end of annotations.");
76         } catch(IllegalArgumentException e) {
77             // Type mismatch in constant pool
78             throw new AnnotationFormatError(e);
79         }
80     }
81 
82     /**
83      * Like {@link #parseAnnotations(byte[], sun.reflect.ConstantPool, Class)}
84      * with an additional parameter {@code selectAnnotationClasses} which selects the
85      * annotation types to parse (other than selected are quickly skipped).<p>
86      * This method is only used to parse select meta annotations in the construction
87      * phase of {@link AnnotationType} instances to prevent infinite recursion.
88      *
89      * @param selectAnnotationClasses an array of annotation types to select when parsing
90      */
91     @SafeVarargs
92     @SuppressWarnings("varargs") // selectAnnotationClasses is used safely
parseSelectAnnotations( byte[] rawAnnotations, ConstantPool constPool, Class<?> container, Class<? extends Annotation> ... selectAnnotationClasses)93     static Map<Class<? extends Annotation>, Annotation> parseSelectAnnotations(
94                 byte[] rawAnnotations,
95                 ConstantPool constPool,
96                 Class<?> container,
97                 Class<? extends Annotation> ... selectAnnotationClasses) {
98         if (rawAnnotations == null)
99             return Collections.emptyMap();
100 
101         try {
102             return parseAnnotations2(rawAnnotations, constPool, container, selectAnnotationClasses);
103         } catch(BufferUnderflowException e) {
104             throw new AnnotationFormatError("Unexpected end of annotations.");
105         } catch(IllegalArgumentException e) {
106             // Type mismatch in constant pool
107             throw new AnnotationFormatError(e);
108         }
109     }
110 
parseAnnotations2( byte[] rawAnnotations, ConstantPool constPool, Class<?> container, Class<? extends Annotation>[] selectAnnotationClasses)111     private static Map<Class<? extends Annotation>, Annotation> parseAnnotations2(
112                 byte[] rawAnnotations,
113                 ConstantPool constPool,
114                 Class<?> container,
115                 Class<? extends Annotation>[] selectAnnotationClasses) {
116         Map<Class<? extends Annotation>, Annotation> result =
117             new LinkedHashMap<Class<? extends Annotation>, Annotation>();
118         ByteBuffer buf = ByteBuffer.wrap(rawAnnotations);
119         int numAnnotations = buf.getShort() & 0xFFFF;
120         for (int i = 0; i < numAnnotations; i++) {
121             Annotation a = parseAnnotation2(buf, constPool, container, false, selectAnnotationClasses);
122             if (a != null) {
123                 Class<? extends Annotation> klass = a.annotationType();
124                 if (AnnotationType.getInstance(klass).retention() == RetentionPolicy.RUNTIME &&
125                     result.put(klass, a) != null) {
126                         throw new AnnotationFormatError(
127                             "Duplicate annotation for class: "+klass+": " + a);
128             }
129         }
130         }
131         return result;
132     }
133 
134     /**
135      * Parses the parameter annotations described by the specified byte array.
136      * resolving constant references in the specified constant pool.
137      * The array must contain an array of annotations as described
138      * in the RuntimeVisibleParameterAnnotations_attribute:
139      *
140      *    u1 num_parameters;
141      *    {
142      *        u2 num_annotations;
143      *        annotation annotations[num_annotations];
144      *    } parameter_annotations[num_parameters];
145      *
146      * Unlike parseAnnotations, rawAnnotations must not be null!
147      * A null value must be handled by the caller.  This is so because
148      * we cannot determine the number of parameters if rawAnnotations
149      * is null.  Also, the caller should check that the number
150      * of parameters indicated by the return value of this method
151      * matches the actual number of method parameters.  A mismatch
152      * indicates that an AnnotationFormatError should be thrown.
153      *
154      * @throws AnnotationFormatError if an annotation is found to be
155      *         malformed.
156      */
parseParameterAnnotations( byte[] rawAnnotations, ConstantPool constPool, Class<?> container)157     public static Annotation[][] parseParameterAnnotations(
158                     byte[] rawAnnotations,
159                     ConstantPool constPool,
160                     Class<?> container) {
161         try {
162             return parseParameterAnnotations2(rawAnnotations, constPool, container);
163         } catch(BufferUnderflowException e) {
164             throw new AnnotationFormatError(
165                 "Unexpected end of parameter annotations.");
166         } catch(IllegalArgumentException e) {
167             // Type mismatch in constant pool
168             throw new AnnotationFormatError(e);
169         }
170     }
171 
parseParameterAnnotations2( byte[] rawAnnotations, ConstantPool constPool, Class<?> container)172     private static Annotation[][] parseParameterAnnotations2(
173                     byte[] rawAnnotations,
174                     ConstantPool constPool,
175                     Class<?> container) {
176         ByteBuffer buf = ByteBuffer.wrap(rawAnnotations);
177         int numParameters = buf.get() & 0xFF;
178         Annotation[][] result = new Annotation[numParameters][];
179 
180         for (int i = 0; i < numParameters; i++) {
181             int numAnnotations = buf.getShort() & 0xFFFF;
182             List<Annotation> annotations =
183                 new ArrayList<Annotation>(numAnnotations);
184             for (int j = 0; j < numAnnotations; j++) {
185                 Annotation a = parseAnnotation(buf, constPool, container, false);
186                 if (a != null) {
187                     AnnotationType type = AnnotationType.getInstance(
188                                               a.annotationType());
189                     if (type.retention() == RetentionPolicy.RUNTIME)
190                         annotations.add(a);
191                 }
192             }
193             result[i] = annotations.toArray(EMPTY_ANNOTATIONS_ARRAY);
194         }
195         return result;
196     }
197 
198     private static final Annotation[] EMPTY_ANNOTATIONS_ARRAY =
199                     new Annotation[0];
200 
201     /**
202      * Parses the annotation at the current position in the specified
203      * byte buffer, resolving constant references in the specified constant
204      * pool.  The cursor of the byte buffer must point to an "annotation
205      * structure" as described in the RuntimeVisibleAnnotations_attribute:
206      *
207      * annotation {
208      *    u2    type_index;
209      *       u2    num_member_value_pairs;
210      *       {    u2    member_name_index;
211      *             member_value value;
212      *       }    member_value_pairs[num_member_value_pairs];
213      *    }
214      * }
215      *
216      * Returns the annotation, or null if the annotation's type cannot
217      * be found by the VM, or is not a valid annotation type.
218      *
219      * @param exceptionOnMissingAnnotationClass if true, throw
220      * TypeNotPresentException if a referenced annotation type is not
221      * available at runtime
222      */
parseAnnotation(ByteBuffer buf, ConstantPool constPool, Class<?> container, boolean exceptionOnMissingAnnotationClass)223     static Annotation parseAnnotation(ByteBuffer buf,
224                                               ConstantPool constPool,
225                                               Class<?> container,
226                                               boolean exceptionOnMissingAnnotationClass) {
227        return parseAnnotation2(buf, constPool, container, exceptionOnMissingAnnotationClass, null);
228     }
229 
230     @SuppressWarnings("unchecked")
parseAnnotation2(ByteBuffer buf, ConstantPool constPool, Class<?> container, boolean exceptionOnMissingAnnotationClass, Class<? extends Annotation>[] selectAnnotationClasses)231     private static Annotation parseAnnotation2(ByteBuffer buf,
232                                               ConstantPool constPool,
233                                               Class<?> container,
234                                               boolean exceptionOnMissingAnnotationClass,
235                                               Class<? extends Annotation>[] selectAnnotationClasses) {
236         int typeIndex = buf.getShort() & 0xFFFF;
237         Class<? extends Annotation> annotationClass = null;
238         String sig = "[unknown]";
239         try {
240             sig = constPool.getUTF8At(typeIndex);
241             annotationClass = (Class<? extends Annotation>)parseSig(sig, container);
242         } catch (NoClassDefFoundError e) {
243             if (exceptionOnMissingAnnotationClass)
244                 // note: at this point sig is "[unknown]" or VM-style
245                 // name instead of a binary name
246                 throw new TypeNotPresentException(sig, e);
247             skipAnnotation(buf, false);
248             return null;
249         }
250         catch (TypeNotPresentException e) {
251             if (exceptionOnMissingAnnotationClass)
252                 throw e;
253             skipAnnotation(buf, false);
254             return null;
255         }
256         if (selectAnnotationClasses != null && !contains(selectAnnotationClasses, annotationClass)) {
257             skipAnnotation(buf, false);
258             return null;
259         }
260         AnnotationType type = null;
261         try {
262             type = AnnotationType.getInstance(annotationClass);
263         } catch (IllegalArgumentException e) {
264             skipAnnotation(buf, false);
265             return null;
266         }
267 
268         Map<String, Class<?>> memberTypes = type.memberTypes();
269         Map<String, Object> memberValues =
270             new LinkedHashMap<String, Object>(type.memberDefaults());
271 
272         int numMembers = buf.getShort() & 0xFFFF;
273         for (int i = 0; i < numMembers; i++) {
274             int memberNameIndex = buf.getShort() & 0xFFFF;
275             String memberName = constPool.getUTF8At(memberNameIndex);
276             Class<?> memberType = memberTypes.get(memberName);
277 
278             if (memberType == null) {
279                 // Member is no longer present in annotation type; ignore it
280                 skipMemberValue(buf);
281             } else {
282                 Object value = parseMemberValue(memberType, buf, constPool, container);
283                 if (value instanceof AnnotationTypeMismatchExceptionProxy)
284                     ((AnnotationTypeMismatchExceptionProxy) value).
285                         setMember(type.members().get(memberName));
286                 memberValues.put(memberName, value);
287             }
288         }
289         return annotationForMap(annotationClass, memberValues);
290     }
291 
292     /**
293      * Returns an annotation of the given type backed by the given
294      * member {@literal ->} value map.
295      */
296     @SuppressWarnings("removal")
annotationForMap(final Class<? extends Annotation> type, final Map<String, Object> memberValues)297     public static Annotation annotationForMap(final Class<? extends Annotation> type,
298                                               final Map<String, Object> memberValues)
299     {
300         return AccessController.doPrivileged(new PrivilegedAction<Annotation>() {
301             public Annotation run() {
302                 return (Annotation) Proxy.newProxyInstance(
303                     type.getClassLoader(), new Class<?>[] { type },
304                     new AnnotationInvocationHandler(type, memberValues));
305             }});
306     }
307 
308     /**
309      * Parses the annotation member value at the current position in the
310      * specified byte buffer, resolving constant references in the specified
311      * constant pool.  The cursor of the byte buffer must point to a
312      * "member_value structure" as described in the
313      * RuntimeVisibleAnnotations_attribute:
314      *
315      *  member_value {
316      *    u1 tag;
317      *    union {
318      *       u2   const_value_index;
319      *       {
320      *           u2   type_name_index;
321      *           u2   const_name_index;
322      *       } enum_const_value;
323      *       u2   class_info_index;
324      *       annotation annotation_value;
325      *       {
326      *           u2    num_values;
327      *           member_value values[num_values];
328      *       } array_value;
329      *    } value;
330      * }
331      *
332      * The member must be of the indicated type. If it is not, this
333      * method returns an AnnotationTypeMismatchExceptionProxy.
334      */
335     @SuppressWarnings("unchecked")
336     public static Object parseMemberValue(Class<?> memberType,
337                                           ByteBuffer buf,
338                                           ConstantPool constPool,
339                                           Class<?> container) {
340         Object result = null;
341         int tag = buf.get();
342         switch(tag) {
343           case 'e':
344               return parseEnumValue((Class<? extends Enum<?>>)memberType, buf, constPool, container);
345           case 'c':
346               result = parseClassValue(buf, constPool, container);
347               break;
348           case '@':
349               result = parseAnnotation(buf, constPool, container, true);
350               break;
351           case '[':
352               return parseArray(memberType, buf, constPool, container);
353           default:
354               result = parseConst(tag, buf, constPool);
355         }
356 
357         if (result == null) {
358             result = new AnnotationTypeMismatchExceptionProxy(
359                 Proxy.isProxyClass(memberType)
360                         ? memberType.getInterfaces()[0].getName()
361                         : memberType.getName());
362         } else if (!(result instanceof ExceptionProxy) &&
363             !memberType.isInstance(result)) {
364             if (result instanceof Annotation) {
365                 result = new AnnotationTypeMismatchExceptionProxy(
366                     result.toString());
367             } else {
368                 result = new AnnotationTypeMismatchExceptionProxy(
369                     result.getClass().getName() + "[" + result + "]");
370             }
371         }
372         return result;
373     }
374 
375     /**
376      * Parses the primitive or String annotation member value indicated by
377      * the specified tag byte at the current position in the specified byte
378      * buffer, resolving constant reference in the specified constant pool.
379      * The cursor of the byte buffer must point to an annotation member value
380      * of the type indicated by the specified tag, as described in the
381      * RuntimeVisibleAnnotations_attribute:
382      *
383      *       u2   const_value_index;
384      */
385     private static Object parseConst(int tag,
386                                      ByteBuffer buf, ConstantPool constPool) {
387         int constIndex = buf.getShort() & 0xFFFF;
388         switch(tag) {
389           case 'B':
390             return Byte.valueOf((byte) constPool.getIntAt(constIndex));
391           case 'C':
392             return Character.valueOf((char) constPool.getIntAt(constIndex));
393           case 'D':
394             return Double.valueOf(constPool.getDoubleAt(constIndex));
395           case 'F':
396             return Float.valueOf(constPool.getFloatAt(constIndex));
397           case 'I':
398             return Integer.valueOf(constPool.getIntAt(constIndex));
399           case 'J':
400             return Long.valueOf(constPool.getLongAt(constIndex));
401           case 'S':
402             return Short.valueOf((short) constPool.getIntAt(constIndex));
403           case 'Z':
404             return Boolean.valueOf(constPool.getIntAt(constIndex) != 0);
405           case 's':
406             return constPool.getUTF8At(constIndex);
407           default:
408             throw new AnnotationFormatError(
409                 "Invalid member-value tag in annotation: " + tag);
410         }
411     }
412 
413     /**
414      * Parses the Class member value at the current position in the
415      * specified byte buffer, resolving constant references in the specified
416      * constant pool.  The cursor of the byte buffer must point to a "class
417      * info index" as described in the RuntimeVisibleAnnotations_attribute:
418      *
419      *       u2   class_info_index;
420      */
421     private static Object parseClassValue(ByteBuffer buf,
422                                           ConstantPool constPool,
423                                           Class<?> container) {
424         int classIndex = buf.getShort() & 0xFFFF;
425         try {
426             String sig = constPool.getUTF8At(classIndex);
427             return parseSig(sig, container);
428         } catch (NoClassDefFoundError e) {
429             return new TypeNotPresentExceptionProxy("[unknown]", e);
430         } catch (TypeNotPresentException e) {
431             return new TypeNotPresentExceptionProxy(e.typeName(), e.getCause());
432         }
433     }
434 
435     private static Class<?> parseSig(String sig, Class<?> container) {
436         if (sig.equals("V")) return void.class;
437         SignatureParser parser = SignatureParser.make();
438         TypeSignature typeSig = parser.parseTypeSig(sig);
439         GenericsFactory factory = CoreReflectionFactory.make(container, ClassScope.make(container));
440         Reifier reify = Reifier.make(factory);
441         typeSig.accept(reify);
442         Type result = reify.getResult();
443         return toClass(result);
444     }
445     static Class<?> toClass(Type o) {
446         if (o instanceof GenericArrayType)
447             return Array.newInstance(toClass(((GenericArrayType)o).getGenericComponentType()),
448                                      0)
449                 .getClass();
450         return (Class)o;
451     }
452 
453     /**
454      * Parses the enum constant member value at the current position in the
455      * specified byte buffer, resolving constant references in the specified
456      * constant pool.  The cursor of the byte buffer must point to a
457      * "enum_const_value structure" as described in the
458      * RuntimeVisibleAnnotations_attribute:
459      *
460      *       {
461      *           u2   type_name_index;
462      *           u2   const_name_index;
463      *       } enum_const_value;
464      */
465     @SuppressWarnings({"rawtypes", "unchecked"})
466     private static Object parseEnumValue(Class<? extends Enum> enumType, ByteBuffer buf,
467                                          ConstantPool constPool,
468                                          Class<?> container) {
469         int typeNameIndex = buf.getShort() & 0xFFFF;
470         String typeName  = constPool.getUTF8At(typeNameIndex);
471         int constNameIndex = buf.getShort() & 0xFFFF;
472         String constName = constPool.getUTF8At(constNameIndex);
473         if (!enumType.isEnum() || enumType != parseSig(typeName, container)) {
474             return new AnnotationTypeMismatchExceptionProxy(
475                     typeName.substring(1, typeName.length() - 1).replace('/', '.') + "." + constName);
476         }
477 
478         try {
479             return  Enum.valueOf(enumType, constName);
480         } catch(IllegalArgumentException e) {
481             return new EnumConstantNotPresentExceptionProxy(
482                 (Class<? extends Enum<?>>)enumType, constName);
483         }
484     }
485 
486     /**
487      * Parses the array value at the current position in the specified byte
488      * buffer, resolving constant references in the specified constant pool.
489      * The cursor of the byte buffer must point to an array value struct
490      * as specified in the RuntimeVisibleAnnotations_attribute:
491      *
492      *       {
493      *           u2    num_values;
494      *           member_value values[num_values];
495      *       } array_value;
496      *
497      * If the array values do not match arrayType, an
498      * AnnotationTypeMismatchExceptionProxy will be returned.
499      */
500     @SuppressWarnings("unchecked")
501     private static Object parseArray(Class<?> arrayType,
502                                      ByteBuffer buf,
503                                      ConstantPool constPool,
504                                      Class<?> container) {
505         int length = buf.getShort() & 0xFFFF;  // Number of array components
506         Class<?> componentType = arrayType.getComponentType();
507 
508         if (componentType == byte.class) {
509             return parseByteArray(length, buf, constPool);
510         } else if (componentType == char.class) {
511             return parseCharArray(length, buf, constPool);
512         } else if (componentType == double.class) {
513             return parseDoubleArray(length, buf, constPool);
514         } else if (componentType == float.class) {
515             return parseFloatArray(length, buf, constPool);
516         } else if (componentType == int.class) {
517             return parseIntArray(length, buf, constPool);
518         } else if (componentType == long.class) {
519             return parseLongArray(length, buf, constPool);
520         } else if (componentType == short.class) {
521             return parseShortArray(length, buf, constPool);
522         } else if (componentType == boolean.class) {
523             return parseBooleanArray(length, buf, constPool);
524         } else if (componentType == String.class) {
525             return parseStringArray(length, buf, constPool);
526         } else if (componentType == Class.class) {
527             return parseClassArray(length, buf, constPool, container);
528         } else if (componentType.isEnum()) {
529             return parseEnumArray(length, (Class<? extends Enum<?>>)componentType, buf,
530                                   constPool, container);
531         } else if (componentType.isAnnotation()) {
532             return parseAnnotationArray(length, (Class <? extends Annotation>)componentType, buf,
533                                         constPool, container);
534         } else {
535             return parseUnknownArray(length, buf);
536         }
537     }
538 
539     private static Object parseByteArray(int length,
540                                   ByteBuffer buf, ConstantPool constPool) {
541         byte[] result = new byte[length];
542         boolean typeMismatch = false;
543         int tag = 0;
544 
545         for (int i = 0; i < length; i++) {
546             tag = buf.get();
547             if (tag == 'B') {
548                 int index = buf.getShort() & 0xFFFF;
549                 result[i] = (byte) constPool.getIntAt(index);
550             } else {
551                 skipMemberValue(tag, buf);
552                 typeMismatch = true;
553             }
554         }
555         return typeMismatch ? exceptionProxy(tag) : result;
556     }
557 
558     private static Object parseCharArray(int length,
559                                   ByteBuffer buf, ConstantPool constPool) {
560         char[] result = new char[length];
561         boolean typeMismatch = false;
562         byte tag = 0;
563 
564         for (int i = 0; i < length; i++) {
565             tag = buf.get();
566             if (tag == 'C') {
567                 int index = buf.getShort() & 0xFFFF;
568                 result[i] = (char) constPool.getIntAt(index);
569             } else {
570                 skipMemberValue(tag, buf);
571                 typeMismatch = true;
572             }
573         }
574         return typeMismatch ? exceptionProxy(tag) : result;
575     }
576 
577     private static Object parseDoubleArray(int length,
578                                     ByteBuffer buf, ConstantPool constPool) {
579         double[] result = new  double[length];
580         boolean typeMismatch = false;
581         int tag = 0;
582 
583         for (int i = 0; i < length; i++) {
584             tag = buf.get();
585             if (tag == 'D') {
586                 int index = buf.getShort() & 0xFFFF;
587                 result[i] = constPool.getDoubleAt(index);
588             } else {
589                 skipMemberValue(tag, buf);
590                 typeMismatch = true;
591             }
592         }
593         return typeMismatch ? exceptionProxy(tag) : result;
594     }
595 
596     private static Object parseFloatArray(int length,
597                                    ByteBuffer buf, ConstantPool constPool) {
598         float[] result = new float[length];
599         boolean typeMismatch = false;
600         int tag = 0;
601 
602         for (int i = 0; i < length; i++) {
603             tag = buf.get();
604             if (tag == 'F') {
605                 int index = buf.getShort() & 0xFFFF;
606                 result[i] = constPool.getFloatAt(index);
607             } else {
608                 skipMemberValue(tag, buf);
609                 typeMismatch = true;
610             }
611         }
612         return typeMismatch ? exceptionProxy(tag) : result;
613     }
614 
615     private static Object parseIntArray(int length,
616                                  ByteBuffer buf, ConstantPool constPool) {
617         int[] result = new  int[length];
618         boolean typeMismatch = false;
619         int tag = 0;
620 
621         for (int i = 0; i < length; i++) {
622             tag = buf.get();
623             if (tag == 'I') {
624                 int index = buf.getShort() & 0xFFFF;
625                 result[i] = constPool.getIntAt(index);
626             } else {
627                 skipMemberValue(tag, buf);
628                 typeMismatch = true;
629             }
630         }
631         return typeMismatch ? exceptionProxy(tag) : result;
632     }
633 
634     private static Object parseLongArray(int length,
635                                   ByteBuffer buf, ConstantPool constPool) {
636         long[] result = new long[length];
637         boolean typeMismatch = false;
638         int tag = 0;
639 
640         for (int i = 0; i < length; i++) {
641             tag = buf.get();
642             if (tag == 'J') {
643                 int index = buf.getShort() & 0xFFFF;
644                 result[i] = constPool.getLongAt(index);
645             } else {
646                 skipMemberValue(tag, buf);
647                 typeMismatch = true;
648             }
649         }
650         return typeMismatch ? exceptionProxy(tag) : result;
651     }
652 
653     private static Object parseShortArray(int length,
654                                    ByteBuffer buf, ConstantPool constPool) {
655         short[] result = new short[length];
656         boolean typeMismatch = false;
657         int tag = 0;
658 
659         for (int i = 0; i < length; i++) {
660             tag = buf.get();
661             if (tag == 'S') {
662                 int index = buf.getShort() & 0xFFFF;
663                 result[i] = (short) constPool.getIntAt(index);
664             } else {
665                 skipMemberValue(tag, buf);
666                 typeMismatch = true;
667             }
668         }
669         return typeMismatch ? exceptionProxy(tag) : result;
670     }
671 
672     private static Object parseBooleanArray(int length,
673                                      ByteBuffer buf, ConstantPool constPool) {
674         boolean[] result = new boolean[length];
675         boolean typeMismatch = false;
676         int tag = 0;
677 
678         for (int i = 0; i < length; i++) {
679             tag = buf.get();
680             if (tag == 'Z') {
681                 int index = buf.getShort() & 0xFFFF;
682                 result[i] = (constPool.getIntAt(index) != 0);
683             } else {
684                 skipMemberValue(tag, buf);
685                 typeMismatch = true;
686             }
687         }
688         return typeMismatch ? exceptionProxy(tag) : result;
689     }
690 
691     private static Object parseStringArray(int length,
692                                     ByteBuffer buf,  ConstantPool constPool) {
693         String[] result = new String[length];
694         boolean typeMismatch = false;
695         int tag = 0;
696 
697         for (int i = 0; i < length; i++) {
698             tag = buf.get();
699             if (tag == 's') {
700                 int index = buf.getShort() & 0xFFFF;
701                 result[i] = constPool.getUTF8At(index);
702             } else {
703                 skipMemberValue(tag, buf);
704                 typeMismatch = true;
705             }
706         }
707         return typeMismatch ? exceptionProxy(tag) : result;
708     }
709 
710     private static Object parseClassArray(int length,
711                                           ByteBuffer buf,
712                                           ConstantPool constPool,
713                                           Class<?> container) {
714         return parseArrayElements(new Class<?>[length],
715                 buf, 'c', () -> parseClassValue(buf, constPool, container));
716     }
717 
718     private static Object parseEnumArray(int length, Class<? extends Enum<?>> enumType,
719                                          ByteBuffer buf,
720                                          ConstantPool constPool,
721                                          Class<?> container) {
722         return parseArrayElements((Object[]) Array.newInstance(enumType, length),
723                 buf, 'e', () -> parseEnumValue(enumType, buf, constPool, container));
724     }
725 
726     private static Object parseAnnotationArray(int length,
727                                                Class<? extends Annotation> annotationType,
728                                                ByteBuffer buf,
729                                                ConstantPool constPool,
730                                                Class<?> container) {
731         return parseArrayElements((Object[]) Array.newInstance(annotationType, length),
732                 buf, '@', () -> parseAnnotation(buf, constPool, container, true));
733     }
734 
735     private static Object parseArrayElements(Object[] result,
736                                              ByteBuffer buf,
737                                              int expectedTag,
738                                              Supplier<Object> parseElement) {
739         Object exceptionProxy = null;
740         for (int i = 0; i < result.length; i++) {
741             int tag = buf.get();
742             if (tag == expectedTag) {
743                 Object value = parseElement.get();
744                 if (value instanceof ExceptionProxy) {
745                     if (exceptionProxy == null) exceptionProxy = (ExceptionProxy) value;
746                 } else {
747                     result[i] = value;
748                 }
749             } else {
750                 skipMemberValue(tag, buf);
751                 if (exceptionProxy == null) exceptionProxy = exceptionProxy(tag);
752             }
753         }
754         return (exceptionProxy != null) ? exceptionProxy : result;
755     }
756 
757     private static Object parseUnknownArray(int length,
758                                             ByteBuffer buf) {
759         int tag = 0;
760 
761         for (int i = 0; i < length; i++) {
762             tag = buf.get();
763             skipMemberValue(tag, buf);
764         }
765 
766         return exceptionProxy(tag);
767     }
768 
769     /**
770      * Returns an appropriate exception proxy for a mismatching array
771      * annotation where the erroneous array has the specified tag.
772      */
773     private static ExceptionProxy exceptionProxy(int tag) {
774         return new AnnotationTypeMismatchExceptionProxy(
775             "Array with component tag: " + (tag == 0 ? "0" : (char) tag));
776     }
777 
778     /**
779      * Skips the annotation at the current position in the specified
780      * byte buffer.  The cursor of the byte buffer must point to
781      * an "annotation structure" OR two bytes into an annotation
782      * structure (i.e., after the type index).
783      *
784      * @param complete true if the byte buffer points to the beginning
785      *     of an annotation structure (rather than two bytes in).
786      */
787     private static void skipAnnotation(ByteBuffer buf, boolean complete) {
788         if (complete)
789             buf.getShort();   // Skip type index
790         int numMembers = buf.getShort() & 0xFFFF;
791         for (int i = 0; i < numMembers; i++) {
792             buf.getShort();   // Skip memberNameIndex
793             skipMemberValue(buf);
794         }
795     }
796 
797     /**
798      * Skips the annotation member value at the current position in the
799      * specified byte buffer.  The cursor of the byte buffer must point to a
800      * "member_value structure."
801      */
802     private static void skipMemberValue(ByteBuffer buf) {
803         int tag = buf.get();
804         skipMemberValue(tag, buf);
805     }
806 
807     /**
808      * Skips the annotation member value at the current position in the
809      * specified byte buffer.  The cursor of the byte buffer must point
810      * immediately after the tag in a "member_value structure."
811      */
812     private static void skipMemberValue(int tag, ByteBuffer buf) {
813         switch(tag) {
814           case 'e': // Enum value
815             buf.getInt();  // (Two shorts, actually.)
816             break;
817           case '@':
818             skipAnnotation(buf, true);
819             break;
820           case '[':
821             skipArray(buf);
822             break;
823           default:
824             // Class, primitive, or String
825             buf.getShort();
826         }
827     }
828 
829     /**
830      * Skips the array value at the current position in the specified byte
831      * buffer.  The cursor of the byte buffer must point to an array value
832      * struct.
833      */
834     private static void skipArray(ByteBuffer buf) {
835         int length = buf.getShort() & 0xFFFF;
836         for (int i = 0; i < length; i++)
837             skipMemberValue(buf);
838     }
839 
840     /**
841      * Searches for given {@code element} in given {@code array} by identity.
842      * Returns {@code true} if found {@code false} if not.
843      */
844     private static boolean contains(Object[] array, Object element) {
845         for (Object e : array)
846             if (e == element)
847                 return true;
848         return false;
849     }
850 
851     /*
852      * This method converts the annotation map returned by the parseAnnotations()
853      * method to an array.  It is called by Field.getDeclaredAnnotations(),
854      * Method.getDeclaredAnnotations(), and Constructor.getDeclaredAnnotations().
855      * This avoids the reflection classes to load the Annotation class until
856      * it is needed.
857      */
858     private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
859     public static Annotation[] toArray(Map<Class<? extends Annotation>, Annotation> annotations) {
860         return annotations.values().toArray(EMPTY_ANNOTATION_ARRAY);
861     }
862 
863     static Annotation[] getEmptyAnnotationArray() { return EMPTY_ANNOTATION_ARRAY; }
864 }
865