result[i] = (byte) constPool.getIntAt(index); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseCharArray(int length, ByteBuffer buf, ConstantPool constPool) { char[] result = new char[length]; boolean typeMismatch = false; byte tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 'C') { int index = buf.getShort() & 0xFFFF; result[i] = (char) constPool.getIntAt(index); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseDoubleArray(int length, ByteBuffer buf, ConstantPool constPool) { double[] result = new double[length]; boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 'D') { int index = buf.getShort() & 0xFFFF; result[i] = constPool.getDoubleAt(index); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseFloatArray(int length, ByteBuffer buf, ConstantPool constPool) { float[] result = new float[length]; boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 'F') { int index = buf.getShort() & 0xFFFF; result[i] = constPool.getFloatAt(index); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseIntArray(int length, ByteBuffer buf, ConstantPool constPool) { int[] result = new int[length]; boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 'I') { int index = buf.getShort() & 0xFFFF; result[i] = constPool.getIntAt(index); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseLongArray(int length, ByteBuffer buf, ConstantPool constPool) { long[] result = new long[length]; boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 'J') { int index = buf.getShort() & 0xFFFF; result[i] = constPool.getLongAt(index); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseShortArray(int length, ByteBuffer buf, ConstantPool constPool) { short[] result = new short[length]; boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 'S') { int index = buf.getShort() & 0xFFFF; result[i] = (short) constPool.getIntAt(index); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseBooleanArray(int length, ByteBuffer buf, ConstantPool constPool) { boolean[] result = new boolean[length]; boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 'Z') { int index = buf.getShort() & 0xFFFF; result[i] = (constPool.getIntAt(index) != 0); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseStringArray(int length, ByteBuffer buf, ConstantPool constPool) { String[] result = new String[length]; boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 's') { int index = buf.getShort() & 0xFFFF; result[i] = constPool.getUTF8At(index); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseClassArray(int length, ByteBuffer buf, ConstantPool constPool, Class<?> container) { Object[] result = new Class<?>[length]; boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 'c') { result[i] = parseClassValue(buf, constPool, container); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseEnumArray(int length, Class<? extends Enum> enumType, ByteBuffer buf, ConstantPool constPool, Class<?> container) { Object[] result = (Object[]) Array.newInstance(enumType, length); boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 'e') { result[i] = parseEnumValue(enumType, buf, constPool, container); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseAnnotationArray(int length, Class<? extends Annotation> annotationType, ByteBuffer buf, ConstantPool constPool, Class<?> container) { Object[] result = (Object[]) Array.newInstance(annotationType, length); boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == '@') { result[i] = parseAnnotation(buf, constPool, container, true); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } /** * Return an appropriate exception proxy for a mismatching array * annotation where the erroneous array has the specified tag. */ private static ExceptionProxy exceptionProxy(int tag) { return new AnnotationTypeMismatchExceptionProxy( "Array with component tag: " + tag); } /** * Skips the annotation at the current position in the specified * byte buffer. The cursor of the byte buffer must point to * an "annotation structure" OR two bytes into an annotation * structure (i.e., after the type index). * * @parameter complete true if the byte buffer points to the beginning * of an annotation structure (rather than two bytes in). */ private static void skipAnnotation(ByteBuffer buf, boolean complete) { if (complete) buf.getShort(); // Skip type index int numMembers = buf.getShort() & 0xFFFF; for (int i = 0; i < numMembers; i++) { buf.getShort(); // Skip memberNameIndex skipMemberValue(buf); } } /** * Skips the annotation member value at the current position in the * specified byte buffer. The cursor of the byte buffer must point to a * "member_value structure." */ private static void skipMemberValue(ByteBuffer buf) { int tag = buf.get(); skipMemberValue(tag, buf); } /** * Skips the annotation member value at the current position in the * specified byte buffer. The cursor of the byte buffer must point * immediately after the tag in a "member_value structure." */ private static void skipMemberValue(int tag, ByteBuffer buf) { switch(tag) { case 'e': // Enum value buf.getInt(); // (Two shorts, actually.) break; case '@': skipAnnotation(buf, true); break; case '[': skipArray(buf); break; default: // Class, primitive, or String buf.getShort(); } } /** * Skips the array value at the current position in the specified byte * buffer. The cursor of the byte buffer must point to an array value * struct. */ private static void skipArray(ByteBuffer buf) { int length = buf.getShort() & 0xFFFF; for (int i = 0; i < length; i++) skipMemberValue(buf); } /* * This method converts the annotation map returned by the parseAnnotations() * method to an array. It is called by Field.getDeclaredAnnotations(), * Method.getDeclaredAnnotations(), and Constructor.getDeclaredAnnotations(). * This avoids the reflection classes to load the Annotation class until * it is needed. */ private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0]; public static Annotation[] toArray(Map<Class<? extends Annotation>, Annotation> annotations) { return annotations.values().toArray(EMPTY_ANNOTATION_ARRAY); }}Lines 501–805 of 805. Previous lines
result[i] = (byte) constPool.getIntAt(index); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseCharArray(int length, ByteBuffer buf, ConstantPool constPool) { char[] result = new char[length]; boolean typeMismatch = false; byte tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 'C') { int index = buf.getShort() & 0xFFFF; result[i] = (char) constPool.getIntAt(index); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseDoubleArray(int length, ByteBuffer buf, ConstantPool constPool) { double[] result = new double[length]; boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 'D') { int index = buf.getShort() & 0xFFFF; result[i] = constPool.getDoubleAt(index); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseFloatArray(int length, ByteBuffer buf, ConstantPool constPool) { float[] result = new float[length]; boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 'F') { int index = buf.getShort() & 0xFFFF; result[i] = constPool.getFloatAt(index); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseIntArray(int length, ByteBuffer buf, ConstantPool constPool) { int[] result = new int[length]; boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 'I') { int index = buf.getShort() & 0xFFFF; result[i] = constPool.getIntAt(index); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseLongArray(int length, ByteBuffer buf, ConstantPool constPool) { long[] result = new long[length]; boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 'J') { int index = buf.getShort() & 0xFFFF; result[i] = constPool.getLongAt(index); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseShortArray(int length, ByteBuffer buf, ConstantPool constPool) { short[] result = new short[length]; boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 'S') { int index = buf.getShort() & 0xFFFF; result[i] = (short) constPool.getIntAt(index); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseBooleanArray(int length, ByteBuffer buf, ConstantPool constPool) { boolean[] result = new boolean[length]; boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 'Z') { int index = buf.getShort() & 0xFFFF; result[i] = (constPool.getIntAt(index) != 0); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseStringArray(int length, ByteBuffer buf, ConstantPool constPool) { String[] result = new String[length]; boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 's') { int index = buf.getShort() & 0xFFFF; result[i] = constPool.getUTF8At(index); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseClassArray(int length, ByteBuffer buf, ConstantPool constPool, Class<?> container) { Object[] result = new Class<?>[length]; boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 'c') { result[i] = parseClassValue(buf, constPool, container); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseEnumArray(int length, Class<? extends Enum> enumType, ByteBuffer buf, ConstantPool constPool, Class<?> container) { Object[] result = (Object[]) Array.newInstance(enumType, length); boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == 'e') { result[i] = parseEnumValue(enumType, buf, constPool, container); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } private static Object parseAnnotationArray(int length, Class<? extends Annotation> annotationType, ByteBuffer buf, ConstantPool constPool, Class<?> container) { Object[] result = (Object[]) Array.newInstance(annotationType, length); boolean typeMismatch = false; int tag = 0; for (int i = 0; i < length; i++) { tag = buf.get(); if (tag == '@') { result[i] = parseAnnotation(buf, constPool, container, true); } else { skipMemberValue(tag, buf); typeMismatch = true; } } return typeMismatch ? exceptionProxy(tag) : result; } /** * Return an appropriate exception proxy for a mismatching array * annotation where the erroneous array has the specified tag. */ private static ExceptionProxy exceptionProxy(int tag) { return new AnnotationTypeMismatchExceptionProxy( "Array with component tag: " + tag); } /** * Skips the annotation at the current position in the specified * byte buffer. The cursor of the byte buffer must point to * an "annotation structure" OR two bytes into an annotation * structure (i.e., after the type index). * * @parameter complete true if the byte buffer points to the beginning * of an annotation structure (rather than two bytes in). */ private static void skipAnnotation(ByteBuffer buf, boolean complete) { if (complete) buf.getShort(); // Skip type index int numMembers = buf.getShort() & 0xFFFF; for (int i = 0; i < numMembers; i++) { buf.getShort(); // Skip memberNameIndex skipMemberValue(buf); } } /** * Skips the annotation member value at the current position in the * specified byte buffer. The cursor of the byte buffer must point to a * "member_value structure." */ private static void skipMemberValue(ByteBuffer buf) { int tag = buf.get(); skipMemberValue(tag, buf); } /** * Skips the annotation member value at the current position in the * specified byte buffer. The cursor of the byte buffer must point * immediately after the tag in a "member_value structure." */ private static void skipMemberValue(int tag, ByteBuffer buf) { switch(tag) { case 'e': // Enum value buf.getInt(); // (Two shorts, actually.) break; case '@': skipAnnotation(buf, true); break; case '[': skipArray(buf); break; default: // Class, primitive, or String buf.getShort(); } } /** * Skips the array value at the current position in the specified byte * buffer. The cursor of the byte buffer must point to an array value * struct. */ private static void skipArray(ByteBuffer buf) { int length = buf.getShort() & 0xFFFF; for (int i = 0; i < length; i++) skipMemberValue(buf); } /* * This method converts the annotation map returned by the parseAnnotations() * method to an array. It is called by Field.getDeclaredAnnotations(), * Method.getDeclaredAnnotations(), and Constructor.getDeclaredAnnotations(). * This avoids the reflection classes to load the Annotation class until * it is needed. */ private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0]; public static Annotation[] toArray(Map<Class<? extends Annotation>, Annotation> annotations) { return annotations.values().toArray(EMPTY_ANNOTATION_ARRAY); } }