/* * ProGuard -- shrinking, optimization, obfuscation, and preverification * of Java bytecode. * * Copyright (c) 2002-2011 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package proguard.classfile.io; import proguard.classfile.*; import proguard.classfile.attribute.*; import proguard.classfile.attribute.annotation.*; import proguard.classfile.attribute.annotation.visitor.*; import proguard.classfile.attribute.preverification.*; import proguard.classfile.attribute.preverification.visitor.*; import proguard.classfile.attribute.visitor.*; import proguard.classfile.constant.*; import proguard.classfile.constant.visitor.ConstantVisitor; import proguard.classfile.util.*; import proguard.classfile.visitor.*; import java.io.DataInput; /** * This ClassVisitor fills out the ProgramClass objects that it visits with data * from the given DataInput object. * * @author Eric Lafortune */ public class ProgramClassReader extends SimplifiedVisitor implements ClassVisitor, MemberVisitor, ConstantVisitor, AttributeVisitor, BootstrapMethodInfoVisitor, InnerClassesInfoVisitor, ExceptionInfoVisitor, StackMapFrameVisitor, VerificationTypeVisitor, LineNumberInfoVisitor, LocalVariableInfoVisitor, LocalVariableTypeInfoVisitor, AnnotationVisitor, ElementValueVisitor { private final RuntimeDataInput dataInput; /** * Creates a new ProgramClassReader for reading from the given DataInput. */ public ProgramClassReader(DataInput dataInput) { this.dataInput = new RuntimeDataInput(dataInput); } // Implementations for ClassVisitor. public void visitProgramClass(ProgramClass programClass) { // Read and check the magic number. programClass.u4magic = dataInput.readInt(); ClassUtil.checkMagicNumber(programClass.u4magic); // Read and check the version numbers. int u2minorVersion = dataInput.readUnsignedShort(); int u2majorVersion = dataInput.readUnsignedShort(); programClass.u4version = ClassUtil.internalClassVersion(u2majorVersion, u2minorVersion); ClassUtil.checkVersionNumbers(programClass.u4version); // Read the constant pool. Note that the first entry is not used. programClass.u2constantPoolCount = dataInput.readUnsignedShort(); programClass.constantPool = new Constant[programClass.u2constantPoolCount]; for (int index = 1; index < programClass.u2constantPoolCount; index++) { Constant constant = createConstant(); constant.accept(programClass, this); programClass.constantPool[index] = constant; // Long constants and double constants take up two entries in the // constant pool. int tag = constant.getTag(); if (tag == ClassConstants.CONSTANT_Long || tag == ClassConstants.CONSTANT_Double) { programClass.constantPool[++index] = null; } } // Read the general class information. programClass.u2accessFlags = dataInput.readUnsignedShort(); programClass.u2thisClass = dataInput.readUnsignedShort(); programClass.u2superClass = dataInput.readUnsignedShort(); // Read the interfaces. programClass.u2interfacesCount = dataInput.readUnsignedShort(); programClass.u2interfaces = new int[programClass.u2interfacesCount]; for (int index = 0; index < programClass.u2interfacesCount; index++) { programClass.u2interfaces[index] = dataInput.readUnsignedShort(); } // Read the fields. programClass.u2fieldsCount = dataInput.readUnsignedShort(); programClass.fields = new ProgramField[programClass.u2fieldsCount]; for (int index = 0; index < programClass.u2fieldsCount; index++) { ProgramField programField = new ProgramField(); this.visitProgramField(programClass, programField); programClass.fields[index] = programField; } // Read the methods. programClass.u2methodsCount = dataInput.readUnsignedShort(); programClass.methods = new ProgramMethod[programClass.u2methodsCount]; for (int index = 0; index < programClass.u2methodsCount; index++) { ProgramMethod programMethod = new ProgramMethod(); this.visitProgramMethod(programClass, programMethod); programClass.methods[index] = programMethod; } // Read the class attributes. programClass.u2attributesCount = dataInput.readUnsignedShort(); programClass.attributes = new Attribute[programClass.u2attributesCount]; for (int index = 0; index < programClass.u2attributesCount; index++) { Attribute attribute = createAttribute(programClass); attribute.accept(programClass, this); programClass.attributes[index] = attribute; } } public void visitLibraryClass(LibraryClass libraryClass) { } // Implementations for MemberVisitor. public void visitProgramField(ProgramClass programClass, ProgramField programField) { // Read the general field information. programField.u2accessFlags = dataInput.readUnsignedShort(); programField.u2nameIndex = dataInput.readUnsignedShort(); programField.u2descriptorIndex = dataInput.readUnsignedShort(); // Read the field attributes. programField.u2attributesCount = dataInput.readUnsignedShort(); programField.attributes = new Attribute[programField.u2attributesCount]; for (int index = 0; index < programField.u2attributesCount; index++) { Attribute attribute = createAttribute(programClass); attribute.accept(programClass, programField, this); programField.attributes[index] = attribute; } } public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) { // Read the general method information. programMethod.u2accessFlags = dataInput.readUnsignedShort(); programMethod.u2nameIndex = dataInput.readUnsignedShort(); programMethod.u2descriptorIndex = dataInput.readUnsignedShort(); // Read the method attributes. programMethod.u2attributesCount = dataInput.readUnsignedShort(); programMethod.attributes = new Attribute[programMethod.u2attributesCount]; for (int index = 0; index < programMethod.u2attributesCount; index++) { Attribute attribute = createAttribute(programClass); attribute.accept(programClass, programMethod, this); programMethod.attributes[index] = attribute; } } public void visitLibraryMember(LibraryClass libraryClass, LibraryMember libraryMember) { } // Implementations for ConstantVisitor. public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant) { integerConstant.u4value = dataInput.readInt(); } public void visitLongConstant(Clazz clazz, LongConstant longConstant) { longConstant.u8value = dataInput.readLong(); } public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant) { floatConstant.f4value = dataInput.readFloat(); } public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant) { doubleConstant.f8value = dataInput.readDouble(); } public void visitStringConstant(Clazz clazz, StringConstant stringConstant) { stringConstant.u2stringIndex = dataInput.readUnsignedShort(); } public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant) { int u2length = dataInput.readUnsignedShort(); // Read the UTF-8 bytes. byte[] bytes = new byte[u2length]; dataInput.readFully(bytes); utf8Constant.setBytes(bytes); } public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant) { invokeDynamicConstant.u2bootstrapMethodAttributeIndex = dataInput.readUnsignedShort(); invokeDynamicConstant.u2nameAndTypeIndex = dataInput.readUnsignedShort(); } public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant) { methodHandleConstant.u1referenceKind = dataInput.readUnsignedByte(); methodHandleConstant.u2referenceIndex = dataInput.readUnsignedShort(); } public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant) { refConstant.u2classIndex = dataInput.readUnsignedShort(); refConstant.u2nameAndTypeIndex = dataInput.readUnsignedShort(); } public void visitClassConstant(Clazz clazz, ClassConstant classConstant) { classConstant.u2nameIndex = dataInput.readUnsignedShort(); } public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant) { methodTypeConstant.u2descriptorIndex = dataInput.readUnsignedShort(); } public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant) { nameAndTypeConstant.u2nameIndex = dataInput.readUnsignedShort(); nameAndTypeConstant.u2descriptorIndex = dataInput.readUnsignedShort(); } // Implementations for AttributeVisitor. public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute) { // Read the unknown information. byte[] info = new byte[unknownAttribute.u4attributeLength]; dataInput.readFully(info); unknownAttribute.info = info; } public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute) { // Read the bootstrap methods. bootstrapMethodsAttribute.u2bootstrapMethodsCount = dataInput.readUnsignedShort(); bootstrapMethodsAttribute.bootstrapMethods = new BootstrapMethodInfo[bootstrapMethodsAttribute.u2bootstrapMethodsCount]; for (int index = 0; index < bootstrapMethodsAttribute.u2bootstrapMethodsCount; index++) { BootstrapMethodInfo bootstrapMethodInfo = new BootstrapMethodInfo(); visitBootstrapMethodInfo(clazz, bootstrapMethodInfo); bootstrapMethodsAttribute.bootstrapMethods[index] = bootstrapMethodInfo; } } public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute) { sourceFileAttribute.u2sourceFileIndex = dataInput.readUnsignedShort(); } public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute) { sourceDirAttribute.u2sourceDirIndex = dataInput.readUnsignedShort(); } public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute) { // Read the inner classes. innerClassesAttribute.u2classesCount = dataInput.readUnsignedShort(); innerClassesAttribute.classes = new InnerClassesInfo[innerClassesAttribute.u2classesCount]; for (int index = 0; index < innerClassesAttribute.u2classesCount; index++) { InnerClassesInfo innerClassesInfo = new InnerClassesInfo(); visitInnerClassesInfo(clazz, innerClassesInfo); innerClassesAttribute.classes[index] = innerClassesInfo; } } public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute) { enclosingMethodAttribute.u2classIndex = dataInput.readUnsignedShort(); enclosingMethodAttribute.u2nameAndTypeIndex = dataInput.readUnsignedShort(); } public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute) { // This attribute does not contain any additional information. } public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute) { // This attribute does not contain any additional information. } public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) { signatureAttribute.u2signatureIndex = dataInput.readUnsignedShort(); } public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute) { constantValueAttribute.u2constantValueIndex = dataInput.readUnsignedShort(); } public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute) { // Read the exceptions. exceptionsAttribute.u2exceptionIndexTableLength = dataInput.readUnsignedShort(); exceptionsAttribute.u2exceptionIndexTable = new int[exceptionsAttribute.u2exceptionIndexTableLength]; for (int index = 0; index < exceptionsAttribute.u2exceptionIndexTableLength; index++) { exceptionsAttribute.u2exceptionIndexTable[index] = dataInput.readUnsignedShort(); } } public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) { // Read the stack size and local variable frame size. codeAttribute.u2maxStack = dataInput.readUnsignedShort(); codeAttribute.u2maxLocals = dataInput.readUnsignedShort(); // Read the byte code. codeAttribute.u4codeLength = dataInput.readInt(); byte[] code = new byte[codeAttribute.u4codeLength]; dataInput.readFully(code); codeAttribute.code = code; // Read the exceptions. codeAttribute.u2exceptionTableLength = dataInput.readUnsignedShort(); codeAttribute.exceptionTable = new ExceptionInfo[codeAttribute.u2exceptionTableLength]; for (int index = 0; index < codeAttribute.u2exceptionTableLength; index++) { ExceptionInfo exceptionInfo = new ExceptionInfo(); visitExceptionInfo(clazz, method, codeAttribute, exceptionInfo); codeAttribute.exceptionTable[index] = exceptionInfo; } // Read the code attributes. codeAttribute.u2attributesCount = dataInput.readUnsignedShort(); codeAttribute.attributes = new Attribute[codeAttribute.u2attributesCount]; for (int index = 0; index < codeAttribute.u2attributesCount; index++) { Attribute attribute = createAttribute(clazz); attribute.accept(clazz, method, codeAttribute, this); codeAttribute.attributes[index] = attribute; } } public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute) { // Read the stack map frames (only full frames, without tag). stackMapAttribute.u2stackMapFramesCount = dataInput.readUnsignedShort(); stackMapAttribute.stackMapFrames = new FullFrame[stackMapAttribute.u2stackMapFramesCount]; for (int index = 0; index < stackMapAttribute.u2stackMapFramesCount; index++) { FullFrame stackMapFrame = new FullFrame(); visitFullFrame(clazz, method, codeAttribute, index, stackMapFrame); stackMapAttribute.stackMapFrames[index] = stackMapFrame; } } public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute) { // Read the stack map frames. stackMapTableAttribute.u2stackMapFramesCount = dataInput.readUnsignedShort(); stackMapTableAttribute.stackMapFrames = new StackMapFrame[stackMapTableAttribute.u2stackMapFramesCount]; for (int index = 0; index < stackMapTableAttribute.u2stackMapFramesCount; index++) { StackMapFrame stackMapFrame = createStackMapFrame(); stackMapFrame.accept(clazz, method, codeAttribute, 0, this); stackMapTableAttribute.stackMapFrames[index] = stackMapFrame; } } public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute) { // Read the line numbers. lineNumberTableAttribute.u2lineNumberTableLength = dataInput.readUnsignedShort(); lineNumberTableAttribute.lineNumberTable = new LineNumberInfo[lineNumberTableAttribute.u2lineNumberTableLength]; for (int index = 0; index < lineNumberTableAttribute.u2lineNumberTableLength; index++) { LineNumberInfo lineNumberInfo = new LineNumberInfo(); visitLineNumberInfo(clazz, method, codeAttribute, lineNumberInfo); lineNumberTableAttribute.lineNumberTable[index] = lineNumberInfo; } } public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute) { // Read the local variables. localVariableTableAttribute.u2localVariableTableLength = dataInput.readUnsignedShort(); localVariableTableAttribute.localVariableTable = new LocalVariableInfo[localVariableTableAttribute.u2localVariableTableLength]; for (int index = 0; index < localVariableTableAttribute.u2localVariableTableLength; index++) { LocalVariableInfo localVariableInfo = new LocalVariableInfo(); visitLocalVariableInfo(clazz, method, codeAttribute, localVariableInfo); localVariableTableAttribute.localVariableTable[index] = localVariableInfo; } } public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute) { // Read the local variable types. localVariableTypeTableAttribute.u2localVariableTypeTableLength = dataInput.readUnsignedShort(); localVariableTypeTableAttribute.localVariableTypeTable = new LocalVariableTypeInfo[localVariableTypeTableAttribute.u2localVariableTypeTableLength]; for (int index = 0; index < localVariableTypeTableAttribute.u2localVariableTypeTableLength; index++) { LocalVariableTypeInfo localVariableTypeInfo = new LocalVariableTypeInfo(); visitLocalVariableTypeInfo(clazz, method, codeAttribute, localVariableTypeInfo); localVariableTypeTableAttribute.localVariableTypeTable[index] = localVariableTypeInfo; } } public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute) { // Read the annotations. annotationsAttribute.u2annotationsCount = dataInput.readUnsignedShort(); annotationsAttribute.annotations = new Annotation[annotationsAttribute.u2annotationsCount]; for (int index = 0; index < annotationsAttribute.u2annotationsCount; index++) { Annotation annotation = new Annotation(); visitAnnotation(clazz, annotation); annotationsAttribute.annotations[index] = annotation; } } public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) { // Read the parameter annotations. parameterAnnotationsAttribute.u2parametersCount = dataInput.readUnsignedByte(); // The java compilers of JDK 1.5, JDK 1.6, and Eclipse all count the // number of parameters of constructors of non-static inner classes // incorrectly. Fix it right here. int parameterStart = 0; if (method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)) { int realParametersCount = ClassUtil.internalMethodParameterCount(method.getDescriptor(clazz)); parameterStart = realParametersCount - parameterAnnotationsAttribute.u2parametersCount; parameterAnnotationsAttribute.u2parametersCount = realParametersCount; } parameterAnnotationsAttribute.u2parameterAnnotationsCount = new int[parameterAnnotationsAttribute.u2parametersCount]; parameterAnnotationsAttribute.parameterAnnotations = new Annotation[parameterAnnotationsAttribute.u2parametersCount][]; for (int parameterIndex = parameterStart; parameterIndex < parameterAnnotationsAttribute.u2parametersCount; parameterIndex++) { // Read the parameter annotations of the given parameter. int u2annotationsCount = dataInput.readUnsignedShort(); Annotation[] annotations = new Annotation[u2annotationsCount]; for (int index = 0; index < u2annotationsCount; index++) { Annotation annotation = new Annotation(); visitAnnotation(clazz, annotation); annotations[index] = annotation; } parameterAnnotationsAttribute.u2parameterAnnotationsCount[parameterIndex] = u2annotationsCount; parameterAnnotationsAttribute.parameterAnnotations[parameterIndex] = annotations; } } public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute) { // Read the default element value. ElementValue elementValue = createElementValue(); elementValue.accept(clazz, null, this); annotationDefaultAttribute.defaultValue = elementValue; } // Implementations for BootstrapMethodInfoVisitor. public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo) { bootstrapMethodInfo.u2methodHandleIndex = dataInput.readUnsignedShort(); // Read the bootstrap method arguments. bootstrapMethodInfo.u2methodArgumentCount = dataInput.readUnsignedShort(); bootstrapMethodInfo.u2methodArguments = new int[bootstrapMethodInfo.u2methodArgumentCount]; for (int index = 0; index < bootstrapMethodInfo.u2methodArgumentCount; index++) { bootstrapMethodInfo.u2methodArguments[index] = dataInput.readUnsignedShort(); } } // Implementations for InnerClassesInfoVisitor. public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo) { innerClassesInfo.u2innerClassIndex = dataInput.readUnsignedShort(); innerClassesInfo.u2outerClassIndex = dataInput.readUnsignedShort(); innerClassesInfo.u2innerNameIndex = dataInput.readUnsignedShort(); innerClassesInfo.u2innerClassAccessFlags = dataInput.readUnsignedShort(); } // Implementations for ExceptionInfoVisitor. public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo) { exceptionInfo.u2startPC = dataInput.readUnsignedShort(); exceptionInfo.u2endPC = dataInput.readUnsignedShort(); exceptionInfo.u2handlerPC = dataInput.readUnsignedShort(); exceptionInfo.u2catchType = dataInput.readUnsignedShort(); } // Implementations for StackMapFrameVisitor. public void visitSameZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameZeroFrame sameZeroFrame) { if (sameZeroFrame.getTag() == StackMapFrame.SAME_ZERO_FRAME_EXTENDED) { sameZeroFrame.u2offsetDelta = dataInput.readUnsignedShort(); } } public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame) { if (sameOneFrame.getTag() == StackMapFrame.SAME_ONE_FRAME_EXTENDED) { sameOneFrame.u2offsetDelta = dataInput.readUnsignedShort(); } // Read the verification type of the stack entry. VerificationType verificationType = createVerificationType(); verificationType.accept(clazz, method, codeAttribute, offset, this); sameOneFrame.stackItem = verificationType; } public void visitLessZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LessZeroFrame lessZeroFrame) { lessZeroFrame.u2offsetDelta = dataInput.readUnsignedShort(); } public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame) { moreZeroFrame.u2offsetDelta = dataInput.readUnsignedShort(); // Read the verification types of the additional local variables. moreZeroFrame.additionalVariables = new VerificationType[moreZeroFrame.additionalVariablesCount]; for (int index = 0; index < moreZeroFrame.additionalVariablesCount; index++) { VerificationType verificationType = createVerificationType(); verificationType.accept(clazz, method, codeAttribute, offset, this); moreZeroFrame.additionalVariables[index] = verificationType; } } public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame) { fullFrame.u2offsetDelta = dataInput.readUnsignedShort(); // Read the verification types of the local variables. fullFrame.variablesCount = dataInput.readUnsignedShort(); fullFrame.variables = new VerificationType[fullFrame.variablesCount]; for (int index = 0; index < fullFrame.variablesCount; index++) { VerificationType verificationType = createVerificationType(); verificationType.variablesAccept(clazz, method, codeAttribute, offset, index, this); fullFrame.variables[index] = verificationType; } // Read the verification types of the stack entries. fullFrame.stackCount = dataInput.readUnsignedShort(); fullFrame.stack = new VerificationType[fullFrame.stackCount]; for (int index = 0; index < fullFrame.stackCount; index++) { VerificationType verificationType = createVerificationType(); verificationType.stackAccept(clazz, method, codeAttribute, offset, index, this); fullFrame.stack[index] = verificationType; } } // Implementations for VerificationTypeVisitor. public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) { // Most verification types don't contain any additional information. } public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType) { objectType.u2classIndex = dataInput.readUnsignedShort(); } public void visitUninitializedType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, UninitializedType uninitializedType) { uninitializedType.u2newInstructionOffset = dataInput.readUnsignedShort(); } // Implementations for LineNumberInfoVisitor. public void visitLineNumberInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberInfo lineNumberInfo) { lineNumberInfo.u2startPC = dataInput.readUnsignedShort(); lineNumberInfo.u2lineNumber = dataInput.readUnsignedShort(); } // Implementations for LocalVariableInfoVisitor. public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo) { localVariableInfo.u2startPC = dataInput.readUnsignedShort(); localVariableInfo.u2length = dataInput.readUnsignedShort(); localVariableInfo.u2nameIndex = dataInput.readUnsignedShort(); localVariableInfo.u2descriptorIndex = dataInput.readUnsignedShort(); localVariableInfo.u2index = dataInput.readUnsignedShort(); } // Implementations for LocalVariableTypeInfoVisitor. public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo) { localVariableTypeInfo.u2startPC = dataInput.readUnsignedShort(); localVariableTypeInfo.u2length = dataInput.readUnsignedShort(); localVariableTypeInfo.u2nameIndex = dataInput.readUnsignedShort(); localVariableTypeInfo.u2signatureIndex = dataInput.readUnsignedShort(); localVariableTypeInfo.u2index = dataInput.readUnsignedShort(); } // Implementations for AnnotationVisitor. public void visitAnnotation(Clazz clazz, Annotation annotation) { // Read the annotation type. annotation.u2typeIndex = dataInput.readUnsignedShort(); // Read the element value pairs. annotation.u2elementValuesCount = dataInput.readUnsignedShort(); annotation.elementValues = new ElementValue[annotation.u2elementValuesCount]; for (int index = 0; index < annotation.u2elementValuesCount; index++) { int u2elementNameIndex = dataInput.readUnsignedShort(); ElementValue elementValue = createElementValue(); elementValue.u2elementNameIndex = u2elementNameIndex; elementValue.accept(clazz, annotation, this); annotation.elementValues[index] = elementValue; } } // Implementations for ElementValueVisitor. public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue) { constantElementValue.u2constantValueIndex = dataInput.readUnsignedShort(); } public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue) { enumConstantElementValue.u2typeNameIndex = dataInput.readUnsignedShort(); enumConstantElementValue.u2constantNameIndex = dataInput.readUnsignedShort(); } public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue) { classElementValue.u2classInfoIndex = dataInput.readUnsignedShort(); } public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue) { // Read the annotation. Annotation annotationValue = new Annotation(); visitAnnotation(clazz, annotationValue); annotationElementValue.annotationValue = annotationValue; } public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue) { // Read the element values. arrayElementValue.u2elementValuesCount = dataInput.readUnsignedShort(); arrayElementValue.elementValues = new ElementValue[arrayElementValue.u2elementValuesCount]; for (int index = 0; index < arrayElementValue.u2elementValuesCount; index++) { ElementValue elementValue = createElementValue(); elementValue.accept(clazz, annotation, this); arrayElementValue.elementValues[index] = elementValue; } } // Small utility methods. private Constant createConstant() { int u1tag = dataInput.readUnsignedByte(); switch (u1tag) { case ClassConstants.CONSTANT_Integer: return new IntegerConstant(); case ClassConstants.CONSTANT_Float: return new FloatConstant(); case ClassConstants.CONSTANT_Long: return new LongConstant(); case ClassConstants.CONSTANT_Double: return new DoubleConstant(); case ClassConstants.CONSTANT_String: return new StringConstant(); case ClassConstants.CONSTANT_Utf8: return new Utf8Constant(); case ClassConstants.CONSTANT_InvokeDynamic: return new InvokeDynamicConstant(); case ClassConstants.CONSTANT_MethodHandle: return new MethodHandleConstant(); case ClassConstants.CONSTANT_Fieldref: return new FieldrefConstant(); case ClassConstants.CONSTANT_Methodref: return new MethodrefConstant(); case ClassConstants.CONSTANT_InterfaceMethodref: return new InterfaceMethodrefConstant(); case ClassConstants.CONSTANT_Class: return new ClassConstant(); case ClassConstants.CONSTANT_MethodType : return new MethodTypeConstant(); case ClassConstants.CONSTANT_NameAndType: return new NameAndTypeConstant(); default: throw new RuntimeException("Unknown constant type ["+u1tag+"] in constant pool"); } } private Attribute createAttribute(Clazz clazz) { int u2attributeNameIndex = dataInput.readUnsignedShort(); int u4attributeLength = dataInput.readInt(); String attributeName = clazz.getString(u2attributeNameIndex); Attribute attribute = attributeName.equals(ClassConstants.ATTR_BootstrapMethods) ? (Attribute)new BootstrapMethodsAttribute(): attributeName.equals(ClassConstants.ATTR_SourceFile) ? (Attribute)new SourceFileAttribute(): attributeName.equals(ClassConstants.ATTR_SourceDir) ? (Attribute)new SourceDirAttribute(): attributeName.equals(ClassConstants.ATTR_InnerClasses) ? (Attribute)new InnerClassesAttribute(): attributeName.equals(ClassConstants.ATTR_EnclosingMethod) ? (Attribute)new EnclosingMethodAttribute(): attributeName.equals(ClassConstants.ATTR_Deprecated) ? (Attribute)new DeprecatedAttribute(): attributeName.equals(ClassConstants.ATTR_Synthetic) ? (Attribute)new SyntheticAttribute(): attributeName.equals(ClassConstants.ATTR_Signature) ? (Attribute)new SignatureAttribute(): attributeName.equals(ClassConstants.ATTR_ConstantValue) ? (Attribute)new ConstantValueAttribute(): attributeName.equals(ClassConstants.ATTR_Exceptions) ? (Attribute)new ExceptionsAttribute(): attributeName.equals(ClassConstants.ATTR_Code) ? (Attribute)new CodeAttribute(): attributeName.equals(ClassConstants.ATTR_StackMap) ? (Attribute)new StackMapAttribute(): attributeName.equals(ClassConstants.ATTR_StackMapTable) ? (Attribute)new StackMapTableAttribute(): attributeName.equals(ClassConstants.ATTR_LineNumberTable) ? (Attribute)new LineNumberTableAttribute(): attributeName.equals(ClassConstants.ATTR_LocalVariableTable) ? (Attribute)new LocalVariableTableAttribute(): attributeName.equals(ClassConstants.ATTR_LocalVariableTypeTable) ? (Attribute)new LocalVariableTypeTableAttribute(): attributeName.equals(ClassConstants.ATTR_RuntimeVisibleAnnotations) ? (Attribute)new RuntimeVisibleAnnotationsAttribute(): attributeName.equals(ClassConstants.ATTR_RuntimeInvisibleAnnotations) ? (Attribute)new RuntimeInvisibleAnnotationsAttribute(): attributeName.equals(ClassConstants.ATTR_RuntimeVisibleParameterAnnotations) ? (Attribute)new RuntimeVisibleParameterAnnotationsAttribute(): attributeName.equals(ClassConstants.ATTR_RuntimeInvisibleParameterAnnotations) ? (Attribute)new RuntimeInvisibleParameterAnnotationsAttribute(): attributeName.equals(ClassConstants.ATTR_AnnotationDefault) ? (Attribute)new AnnotationDefaultAttribute(): (Attribute)new UnknownAttribute(u4attributeLength); attribute.u2attributeNameIndex = u2attributeNameIndex; return attribute; } private StackMapFrame createStackMapFrame() { int u1tag = dataInput.readUnsignedByte(); return u1tag < StackMapFrame.SAME_ONE_FRAME ? (StackMapFrame)new SameZeroFrame(u1tag) : u1tag < StackMapFrame.SAME_ONE_FRAME_EXTENDED ? (StackMapFrame)new SameOneFrame(u1tag) : u1tag < StackMapFrame.LESS_ZERO_FRAME ? (StackMapFrame)new SameOneFrame(u1tag) : u1tag < StackMapFrame.SAME_ZERO_FRAME_EXTENDED ? (StackMapFrame)new LessZeroFrame(u1tag) : u1tag < StackMapFrame.MORE_ZERO_FRAME ? (StackMapFrame)new SameZeroFrame(u1tag) : u1tag < StackMapFrame.FULL_FRAME ? (StackMapFrame)new MoreZeroFrame(u1tag) : (StackMapFrame)new FullFrame(); } private VerificationType createVerificationType() { int u1tag = dataInput.readUnsignedByte(); switch (u1tag) { case VerificationType.INTEGER_TYPE: return new IntegerType(); case VerificationType.FLOAT_TYPE: return new FloatType(); case VerificationType.LONG_TYPE: return new LongType(); case VerificationType.DOUBLE_TYPE: return new DoubleType(); case VerificationType.TOP_TYPE: return new TopType(); case VerificationType.OBJECT_TYPE: return new ObjectType(); case VerificationType.NULL_TYPE: return new NullType(); case VerificationType.UNINITIALIZED_TYPE: return new UninitializedType(); case VerificationType.UNINITIALIZED_THIS_TYPE: return new UninitializedThisType(); default: throw new RuntimeException("Unknown verification type ["+u1tag+"] in stack map frame"); } } private ElementValue createElementValue() { int u1tag = dataInput.readUnsignedByte(); switch (u1tag) { case ClassConstants.INTERNAL_TYPE_BOOLEAN: case ClassConstants.INTERNAL_TYPE_BYTE: case ClassConstants.INTERNAL_TYPE_CHAR: case ClassConstants.INTERNAL_TYPE_SHORT: case ClassConstants.INTERNAL_TYPE_INT: case ClassConstants.INTERNAL_TYPE_FLOAT: case ClassConstants.INTERNAL_TYPE_LONG: case ClassConstants.INTERNAL_TYPE_DOUBLE: case ClassConstants.ELEMENT_VALUE_STRING_CONSTANT: return new ConstantElementValue(u1tag); case ClassConstants.ELEMENT_VALUE_ENUM_CONSTANT: return new EnumConstantElementValue(); case ClassConstants.ELEMENT_VALUE_CLASS: return new ClassElementValue(); case ClassConstants.ELEMENT_VALUE_ANNOTATION: return new AnnotationElementValue(); case ClassConstants.ELEMENT_VALUE_ARRAY: return new ArrayElementValue(); default: throw new IllegalArgumentException("Unknown element value tag ["+u1tag+"]"); } } }