/** * Read the pair from the input stream and create object * * @param constantPool the constant pool for the class being read * @param input stream to read from * @param classLoader the class loader being used to load this annotation * @return a newly created annotation member */ static AnnotationMember readAnnotationMember( TypeReference type, int[] constantPool, DataInputStream input, ClassLoader classLoader) throws IOException, ClassNotFoundException { // Read name of pair int elemNameIndex = input.readUnsignedShort(); Atom name = RVMClass.getUtf(constantPool, elemNameIndex); MethodReference meth; Object value; if (type.isResolved()) { meth = type.resolve().asClass().findDeclaredMethod(name).getMemberRef().asMethodReference(); 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(); } return new AnnotationMember(meth, value); }
/** * Read an annotation attribute from the class file * * @param constantPool from constant pool being loaded * @param input the data being read */ static RVMAnnotation readAnnotation( int[] constantPool, DataInputStream input, ClassLoader classLoader) throws IOException, ClassNotFoundException { TypeReference type; // Read type int typeIndex = input.readUnsignedShort(); type = TypeReference.findOrCreate(classLoader, RVMClass.getUtf(constantPool, typeIndex)); // Read values int numAnnotationMembers = input.readUnsignedShort(); AnnotationMember[] elementValuePairs = new AnnotationMember[numAnnotationMembers]; for (int i = 0; i < numAnnotationMembers; i++) { elementValuePairs[i] = AnnotationMember.readAnnotationMember(type, constantPool, input, classLoader); } // Arrays.sort(elementValuePairs); RVMAnnotation result = new RVMAnnotation(type, elementValuePairs); RVMAnnotation unique = uniqueMap.get(result); if (unique != null) { return unique; } else { uniqueMap.put(result, result); return result; } }
private static <T> Object readValue( TypeReference type, int[] constantPool, DataInputStream input, ClassLoader classLoader, byte elementValue_tag) throws IOException, ClassNotFoundException { // decode Object value; switch (elementValue_tag) { case 'B': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Byte); Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); value = (byte) Statics.getSlotContentsAsInt(offset); break; } case 'C': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Char); Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); value = (char) Statics.getSlotContentsAsInt(offset); break; } case 'D': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Double); Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); long longValue = Statics.getSlotContentsAsLong(offset); value = Double.longBitsToDouble(longValue); break; } case 'F': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Float); Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); int intValue = Statics.getSlotContentsAsInt(offset); value = Float.intBitsToFloat(intValue); break; } case 'I': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Int); Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); value = Statics.getSlotContentsAsInt(offset); break; } case 'J': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Long); Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); value = Statics.getSlotContentsAsLong(offset); break; } case 'S': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Short); Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); value = (short) Statics.getSlotContentsAsInt(offset); break; } case 'Z': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.Boolean); Offset offset = RVMClass.getLiteralOffset(constantPool, input.readUnsignedShort()); value = Statics.getSlotContentsAsInt(offset) == 1; break; } case 's': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.JavaLangString); value = RVMClass.getUtf(constantPool, input.readUnsignedShort()).toString(); break; } case 'e': { int typeNameIndex = input.readUnsignedShort(); @SuppressWarnings("unchecked") Class enumType = TypeReference.findOrCreate(classLoader, RVMClass.getUtf(constantPool, typeNameIndex)) .resolve() .getClassForType(); int constNameIndex = input.readUnsignedShort(); //noinspection unchecked value = Enum.valueOf(enumType, RVMClass.getUtf(constantPool, constNameIndex).toString()); break; } case 'c': { if (VM.VerifyAssertions) VM._assert(type == null || type == TypeReference.JavaLangClass); int classInfoIndex = input.readUnsignedShort(); // Value should be a class but resolving the class at this point could cause infinite // recursion in class loading TypeReference unresolvedValue = TypeReference.findOrCreate( classLoader, RVMClass.getUtf(constantPool, classInfoIndex)); if (unresolvedValue.peekType() != null) { value = unresolvedValue.peekType().getClassForType(); } else { value = unresolvedValue; } break; } case '@': value = RVMAnnotation.readAnnotation(constantPool, input, classLoader); break; case '[': { int numValues = input.readUnsignedShort(); if (numValues == 0) { if (type != null) { value = Array.newInstance(type.resolve().getClassForType(), 0); } else { value = new Object[0]; } } else { byte innerElementValue_tag = input.readByte(); TypeReference innerType = type == null ? null : type.getArrayElementType(); switch (innerElementValue_tag) { case 'B': { byte[] array = new byte[numValues]; array[0] = (Byte) readValue( innerType, constantPool, input, classLoader, innerElementValue_tag); for (int i = 1; i < numValues; i++) { array[i] = (Byte) readValue(innerType, constantPool, input, classLoader); } value = array; break; } case 'C': { char[] array = new char[numValues]; array[0] = (Character) readValue( innerType, constantPool, input, classLoader, innerElementValue_tag); for (int i = 1; i < numValues; i++) { array[i] = (Character) readValue(innerType, constantPool, input, classLoader); } value = array; break; } case 'D': { double[] array = new double[numValues]; array[0] = (Double) readValue( innerType, constantPool, input, classLoader, innerElementValue_tag); for (int i = 1; i < numValues; i++) { array[i] = (Double) readValue(innerType, constantPool, input, classLoader); } value = array; break; } case 'F': { float[] array = new float[numValues]; array[0] = (Float) readValue( innerType, constantPool, input, classLoader, innerElementValue_tag); for (int i = 1; i < numValues; i++) { array[i] = (Float) readValue(innerType, constantPool, input, classLoader); } value = array; break; } case 'I': { int[] array = new int[numValues]; array[0] = (Integer) readValue( innerType, constantPool, input, classLoader, innerElementValue_tag); for (int i = 1; i < numValues; i++) { array[i] = (Integer) readValue(innerType, constantPool, input, classLoader); } value = array; break; } case 'J': { long[] array = new long[numValues]; array[0] = (Long) readValue( innerType, constantPool, input, classLoader, innerElementValue_tag); for (int i = 1; i < numValues; i++) { array[i] = (Long) readValue(innerType, constantPool, input, classLoader); } value = array; break; } case 'S': { short[] array = new short[numValues]; array[0] = (Short) readValue( innerType, constantPool, input, classLoader, innerElementValue_tag); for (int i = 1; i < numValues; i++) { array[i] = (Short) readValue( innerType, constantPool, input, classLoader, innerElementValue_tag); } value = array; break; } case 'Z': { boolean[] array = new boolean[numValues]; array[0] = (Boolean) readValue( innerType, constantPool, input, classLoader, innerElementValue_tag); for (int i = 1; i < numValues; i++) { array[i] = (Boolean) readValue(innerType, constantPool, input, classLoader); } value = array; break; } case 's': case '@': case 'e': case '[': { Object value1 = readValue(innerType, constantPool, input, classLoader, innerElementValue_tag); value = Array.newInstance(value1.getClass(), numValues); Array.set(value, 0, value1); for (int i = 1; i < numValues; i++) { Array.set(value, i, readValue(innerType, constantPool, input, classLoader)); } break; } case 'c': { Object value1 = readValue(innerType, constantPool, input, classLoader, innerElementValue_tag); Object[] values = new Object[numValues]; values[0] = value1; boolean allClasses = value1 instanceof Class; for (int i = 1; i < numValues; i++) { values[i] = readValue(innerType, constantPool, input, classLoader); if (allClasses && !(values[i] instanceof Class)) { allClasses = false; } } if (allClasses == true) { Class<?>[] newValues = new Class[numValues]; for (int i = 0; i < numValues; i++) { newValues[i] = (Class<?>) values[i]; } value = newValues; } else { value = values; } break; } default: throw new ClassFormatError( "Unknown element_value tag '" + (char) innerElementValue_tag + "'"); } } break; } default: throw new ClassFormatError("Unknown element_value tag '" + (char) elementValue_tag + "'"); } return value; }