signature:
public class ClassReader { /** * Makes the given visitor visit the JVMS ClassFile structure passed to the constructor of this
 * { @ link ClassReader } .
 * @ param classVisitor the visitor that must visit this class .
 * @ param attributePrototypes prototypes of the attributes that must be parsed during the visit of
 * the class . Any attribute whose type is not equal to the type of one the prototypes will not
 * be parsed : its byte array value will be passed unchanged to the ClassWriter . < i > This may
 * corrupt it if this value contains references to the constant pool , or has syntactic or
 * semantic links with a class element that has been transformed by a class adapter between
 * the reader and the writer < / i > .
 * @ param parsingOptions the options to use to parse this class . One or more of { @ link
 * # SKIP _ CODE } , { @ link # SKIP _ DEBUG } , { @ link # SKIP _ FRAMES } or { @ link # EXPAND _ FRAMES } . */
public void accept ( final ClassVisitor classVisitor , final Attribute [ ] attributePrototypes , final int parsingOptions ) { } }

implementation:
Context context = new Context ( ) ; context . attributePrototypes = attributePrototypes ; context . parsingOptions = parsingOptions ; context . charBuffer = new char [ maxStringLength ] ; // Read the access _ flags , this _ class , super _ class , interface _ count and interfaces fields .
char [ ] charBuffer = context . charBuffer ; int currentOffset = header ; int accessFlags = readUnsignedShort ( currentOffset ) ; String thisClass = readClass ( currentOffset + 2 , charBuffer ) ; String superClass = readClass ( currentOffset + 4 , charBuffer ) ; String [ ] interfaces = new String [ readUnsignedShort ( currentOffset + 6 ) ] ; currentOffset += 8 ; for ( int i = 0 ; i < interfaces . length ; ++ i ) { interfaces [ i ] = readClass ( currentOffset , charBuffer ) ; currentOffset += 2 ; } // Read the class attributes ( the variables are ordered as in Section 4.7 of the JVMS ) .
// Attribute offsets exclude the attribute _ name _ index and attribute _ length fields .
// - The offset of the InnerClasses attribute , or 0.
int innerClassesOffset = 0 ; // - The offset of the EnclosingMethod attribute , or 0.
int enclosingMethodOffset = 0 ; // - The string corresponding to the Signature attribute , or null .
String signature = null ; // - The string corresponding to the SourceFile attribute , or null .
String sourceFile = null ; // - The string corresponding to the SourceDebugExtension attribute , or null .
String sourceDebugExtension = null ; // - The offset of the RuntimeVisibleAnnotations attribute , or 0.
int runtimeVisibleAnnotationsOffset = 0 ; // - The offset of the RuntimeInvisibleAnnotations attribute , or 0.
int runtimeInvisibleAnnotationsOffset = 0 ; // - The offset of the RuntimeVisibleTypeAnnotations attribute , or 0.
int runtimeVisibleTypeAnnotationsOffset = 0 ; // - The offset of the RuntimeInvisibleTypeAnnotations attribute , or 0.
int runtimeInvisibleTypeAnnotationsOffset = 0 ; // - The offset of the Module attribute , or 0.
int moduleOffset = 0 ; // - The offset of the ModulePackages attribute , or 0.
int modulePackagesOffset = 0 ; // - The string corresponding to the ModuleMainClass attribute , or null .
String moduleMainClass = null ; // - The string corresponding to the NestHost attribute , or null .
String nestHostClass = null ; // - The offset of the NestMembers attribute , or 0.
int nestMembersOffset = 0 ; // - The non standard attributes ( linked with their { @ link Attribute # nextAttribute } field ) .
// This list in the < i > reverse order < / i > or their order in the ClassFile structure .
Attribute attributes = null ; int currentAttributeOffset = getFirstAttributeOffset ( ) ; for ( int i = readUnsignedShort ( currentAttributeOffset - 2 ) ; i > 0 ; -- i ) { // Read the attribute _ info ' s attribute _ name and attribute _ length fields .
String attributeName = readUTF8 ( currentAttributeOffset , charBuffer ) ; int attributeLength = readInt ( currentAttributeOffset + 2 ) ; currentAttributeOffset += 6 ; // The tests are sorted in decreasing frequency order ( based on frequencies observed on
// typical classes ) .
if ( Constants . SOURCE_FILE . equals ( attributeName ) ) { sourceFile = readUTF8 ( currentAttributeOffset , charBuffer ) ; } else if ( Constants . INNER_CLASSES . equals ( attributeName ) ) { innerClassesOffset = currentAttributeOffset ; } else if ( Constants . ENCLOSING_METHOD . equals ( attributeName ) ) { enclosingMethodOffset = currentAttributeOffset ; } else if ( Constants . NEST_HOST . equals ( attributeName ) ) { nestHostClass = readClass ( currentAttributeOffset , charBuffer ) ; } else if ( Constants . NEST_MEMBERS . equals ( attributeName ) ) { nestMembersOffset = currentAttributeOffset ; } else if ( Constants . SIGNATURE . equals ( attributeName ) ) { signature = readUTF8 ( currentAttributeOffset , charBuffer ) ; } else if ( Constants . RUNTIME_VISIBLE_ANNOTATIONS . equals ( attributeName ) ) { runtimeVisibleAnnotationsOffset = currentAttributeOffset ; } else if ( Constants . RUNTIME_VISIBLE_TYPE_ANNOTATIONS . equals ( attributeName ) ) { runtimeVisibleTypeAnnotationsOffset = currentAttributeOffset ; } else if ( Constants . DEPRECATED . equals ( attributeName ) ) { accessFlags |= Opcodes . ACC_DEPRECATED ; } else if ( Constants . SYNTHETIC . equals ( attributeName ) ) { accessFlags |= Opcodes . ACC_SYNTHETIC ; } else if ( Constants . SOURCE_DEBUG_EXTENSION . equals ( attributeName ) ) { sourceDebugExtension = readUtf ( currentAttributeOffset , attributeLength , new char [ attributeLength ] ) ; } else if ( Constants . RUNTIME_INVISIBLE_ANNOTATIONS . equals ( attributeName ) ) { runtimeInvisibleAnnotationsOffset = currentAttributeOffset ; } else if ( Constants . RUNTIME_INVISIBLE_TYPE_ANNOTATIONS . equals ( attributeName ) ) { runtimeInvisibleTypeAnnotationsOffset = currentAttributeOffset ; } else if ( Constants . MODULE . equals ( attributeName ) ) { moduleOffset = currentAttributeOffset ; } else if ( Constants . MODULE_MAIN_CLASS . equals ( attributeName ) ) { moduleMainClass = readClass ( currentAttributeOffset , charBuffer ) ; } else if ( Constants . MODULE_PACKAGES . equals ( attributeName ) ) { modulePackagesOffset = currentAttributeOffset ; } else if ( ! Constants . BOOTSTRAP_METHODS . equals ( attributeName ) ) { // The BootstrapMethods attribute is read in the constructor .
Attribute attribute = readAttribute ( attributePrototypes , attributeName , currentAttributeOffset , attributeLength , charBuffer , - 1 , null ) ; attribute . nextAttribute = attributes ; attributes = attribute ; } currentAttributeOffset += attributeLength ; } // Visit the class declaration . The minor _ version and major _ version fields start 6 bytes before
// the first constant pool entry , which itself starts at cpInfoOffsets [ 1 ] - 1 ( by definition ) .
classVisitor . visit ( readInt ( cpInfoOffsets [ 1 ] - 7 ) , accessFlags , thisClass , signature , superClass , interfaces ) ; // Visit the SourceFile and SourceDebugExtenstion attributes .
if ( ( parsingOptions & SKIP_DEBUG ) == 0 && ( sourceFile != null || sourceDebugExtension != null ) ) { classVisitor . visitSource ( sourceFile , sourceDebugExtension ) ; } // Visit the Module , ModulePackages and ModuleMainClass attributes .
if ( moduleOffset != 0 ) { readModuleAttributes ( classVisitor , context , moduleOffset , modulePackagesOffset , moduleMainClass ) ; } // Visit the NestHost attribute .
if ( nestHostClass != null ) { classVisitor . visitNestHost ( nestHostClass ) ; } // Visit the EnclosingMethod attribute .
if ( enclosingMethodOffset != 0 ) { String className = readClass ( enclosingMethodOffset , charBuffer ) ; int methodIndex = readUnsignedShort ( enclosingMethodOffset + 2 ) ; String name = methodIndex == 0 ? null : readUTF8 ( cpInfoOffsets [ methodIndex ] , charBuffer ) ; String type = methodIndex == 0 ? null : readUTF8 ( cpInfoOffsets [ methodIndex ] + 2 , charBuffer ) ; classVisitor . visitOuterClass ( className , name , type ) ; } // Visit the RuntimeVisibleAnnotations attribute .
if ( runtimeVisibleAnnotationsOffset != 0 ) { int numAnnotations = readUnsignedShort ( runtimeVisibleAnnotationsOffset ) ; int currentAnnotationOffset = runtimeVisibleAnnotationsOffset + 2 ; while ( numAnnotations -- > 0 ) { // Parse the type _ index field .
String annotationDescriptor = readUTF8 ( currentAnnotationOffset , charBuffer ) ; currentAnnotationOffset += 2 ; // Parse num _ element _ value _ pairs and element _ value _ pairs and visit these values .
currentAnnotationOffset = readElementValues ( classVisitor . visitAnnotation ( annotationDescriptor , /* visible = */
true ) , currentAnnotationOffset , /* named = */
true , charBuffer ) ; } } // Visit the RuntimeInvisibleAnnotations attribute .
if ( runtimeInvisibleAnnotationsOffset != 0 ) { int numAnnotations = readUnsignedShort ( runtimeInvisibleAnnotationsOffset ) ; int currentAnnotationOffset = runtimeInvisibleAnnotationsOffset + 2 ; while ( numAnnotations -- > 0 ) { // Parse the type _ index field .
String annotationDescriptor = readUTF8 ( currentAnnotationOffset , charBuffer ) ; currentAnnotationOffset += 2 ; // Parse num _ element _ value _ pairs and element _ value _ pairs and visit these values .
currentAnnotationOffset = readElementValues ( classVisitor . visitAnnotation ( annotationDescriptor , /* visible = */
false ) , currentAnnotationOffset , /* named = */
true , charBuffer ) ; } } // Visit the RuntimeVisibleTypeAnnotations attribute .
if ( runtimeVisibleTypeAnnotationsOffset != 0 ) { int numAnnotations = readUnsignedShort ( runtimeVisibleTypeAnnotationsOffset ) ; int currentAnnotationOffset = runtimeVisibleTypeAnnotationsOffset + 2 ; while ( numAnnotations -- > 0 ) { // Parse the target _ type , target _ info and target _ path fields .
currentAnnotationOffset = readTypeAnnotationTarget ( context , currentAnnotationOffset ) ; // Parse the type _ index field .
String annotationDescriptor = readUTF8 ( currentAnnotationOffset , charBuffer ) ; currentAnnotationOffset += 2 ; // Parse num _ element _ value _ pairs and element _ value _ pairs and visit these values .
currentAnnotationOffset = readElementValues ( classVisitor . visitTypeAnnotation ( context . currentTypeAnnotationTarget , context . currentTypeAnnotationTargetPath , annotationDescriptor , /* visible = */
true ) , currentAnnotationOffset , /* named = */
true , charBuffer ) ; } } // Visit the RuntimeInvisibleTypeAnnotations attribute .
if ( runtimeInvisibleTypeAnnotationsOffset != 0 ) { int numAnnotations = readUnsignedShort ( runtimeInvisibleTypeAnnotationsOffset ) ; int currentAnnotationOffset = runtimeInvisibleTypeAnnotationsOffset + 2 ; while ( numAnnotations -- > 0 ) { // Parse the target _ type , target _ info and target _ path fields .
currentAnnotationOffset = readTypeAnnotationTarget ( context , currentAnnotationOffset ) ; // Parse the type _ index field .
String annotationDescriptor = readUTF8 ( currentAnnotationOffset , charBuffer ) ; currentAnnotationOffset += 2 ; // Parse num _ element _ value _ pairs and element _ value _ pairs and visit these values .
currentAnnotationOffset = readElementValues ( classVisitor . visitTypeAnnotation ( context . currentTypeAnnotationTarget , context . currentTypeAnnotationTargetPath , annotationDescriptor , /* visible = */
false ) , currentAnnotationOffset , /* named = */
true , charBuffer ) ; } } // Visit the non standard attributes .
while ( attributes != null ) { // Copy and reset the nextAttribute field so that it can also be used in ClassWriter .
Attribute nextAttribute = attributes . nextAttribute ; attributes . nextAttribute = null ; classVisitor . visitAttribute ( attributes ) ; attributes = nextAttribute ; } // Visit the NestedMembers attribute .
if ( nestMembersOffset != 0 ) { int numberOfNestMembers = readUnsignedShort ( nestMembersOffset ) ; int currentNestMemberOffset = nestMembersOffset + 2 ; while ( numberOfNestMembers -- > 0 ) { classVisitor . visitNestMember ( readClass ( currentNestMemberOffset , charBuffer ) ) ; currentNestMemberOffset += 2 ; } } // Visit the InnerClasses attribute .
if ( innerClassesOffset != 0 ) { int numberOfClasses = readUnsignedShort ( innerClassesOffset ) ; int currentClassesOffset = innerClassesOffset + 2 ; while ( numberOfClasses -- > 0 ) { classVisitor . visitInnerClass ( readClass ( currentClassesOffset , charBuffer ) , readClass ( currentClassesOffset + 2 , charBuffer ) , readUTF8 ( currentClassesOffset + 4 , charBuffer ) , readUnsignedShort ( currentClassesOffset + 6 ) ) ; currentClassesOffset += 8 ; } } // Visit the fields and methods .
int fieldsCount = readUnsignedShort ( currentOffset ) ; currentOffset += 2 ; while ( fieldsCount -- > 0 ) { currentOffset = readField ( classVisitor , context , currentOffset ) ; } int methodsCount = readUnsignedShort ( currentOffset ) ; currentOffset += 2 ; while ( methodsCount -- > 0 ) { currentOffset = readMethod ( classVisitor , context , currentOffset ) ; } // Visit the end of the class .
classVisitor . visitEnd ( ) ;


signature:
public class ClassReader { /** * Reads the Module , ModulePackages and ModuleMainClass attributes and visit them .
 * @ param classVisitor the current class visitor
 * @ param context information about the class being parsed .
 * @ param moduleOffset the offset of the Module attribute ( excluding the attribute _ info ' s
 * attribute _ name _ index and attribute _ length fields ) .
 * @ param modulePackagesOffset the offset of the ModulePackages attribute ( excluding the
 * attribute _ info ' s attribute _ name _ index and attribute _ length fields ) , or 0.
 * @ param moduleMainClass the string corresponding to the ModuleMainClass attribute , or null . */
private void readModuleAttributes ( final ClassVisitor classVisitor , final Context context , final int moduleOffset , final int modulePackagesOffset , final String moduleMainClass ) { } }

implementation:
char [ ] buffer = context . charBuffer ; // Read the module _ name _ index , module _ flags and module _ version _ index fields and visit them .
int currentOffset = moduleOffset ; String moduleName = readModule ( currentOffset , buffer ) ; int moduleFlags = readUnsignedShort ( currentOffset + 2 ) ; String moduleVersion = readUTF8 ( currentOffset + 4 , buffer ) ; currentOffset += 6 ; ModuleVisitor moduleVisitor = classVisitor . visitModule ( moduleName , moduleFlags , moduleVersion ) ; if ( moduleVisitor == null ) { return ; } // Visit the ModuleMainClass attribute .
if ( moduleMainClass != null ) { moduleVisitor . visitMainClass ( moduleMainClass ) ; } // Visit the ModulePackages attribute .
if ( modulePackagesOffset != 0 ) { int packageCount = readUnsignedShort ( modulePackagesOffset ) ; int currentPackageOffset = modulePackagesOffset + 2 ; while ( packageCount -- > 0 ) { moduleVisitor . visitPackage ( readPackage ( currentPackageOffset , buffer ) ) ; currentPackageOffset += 2 ; } } // Read the ' requires _ count ' and ' requires ' fields .
int requiresCount = readUnsignedShort ( currentOffset ) ; currentOffset += 2 ; while ( requiresCount -- > 0 ) { // Read the requires _ index , requires _ flags and requires _ version fields and visit them .
String requires = readModule ( currentOffset , buffer ) ; int requiresFlags = readUnsignedShort ( currentOffset + 2 ) ; String requiresVersion = readUTF8 ( currentOffset + 4 , buffer ) ; currentOffset += 6 ; moduleVisitor . visitRequire ( requires , requiresFlags , requiresVersion ) ; } // Read the ' exports _ count ' and ' exports ' fields .
int exportsCount = readUnsignedShort ( currentOffset ) ; currentOffset += 2 ; while ( exportsCount -- > 0 ) { // Read the exports _ index , exports _ flags , exports _ to _ count and exports _ to _ index fields
// and visit them .
String exports = readPackage ( currentOffset , buffer ) ; int exportsFlags = readUnsignedShort ( currentOffset + 2 ) ; int exportsToCount = readUnsignedShort ( currentOffset + 4 ) ; currentOffset += 6 ; String [ ] exportsTo = null ; if ( exportsToCount != 0 ) { exportsTo = new String [ exportsToCount ] ; for ( int i = 0 ; i < exportsToCount ; ++ i ) { exportsTo [ i ] = readModule ( currentOffset , buffer ) ; currentOffset += 2 ; } } moduleVisitor . visitExport ( exports , exportsFlags , exportsTo ) ; } // Reads the ' opens _ count ' and ' opens ' fields .
int opensCount = readUnsignedShort ( currentOffset ) ; currentOffset += 2 ; while ( opensCount -- > 0 ) { // Read the opens _ index , opens _ flags , opens _ to _ count and opens _ to _ index fields and visit them .
String opens = readPackage ( currentOffset , buffer ) ; int opensFlags = readUnsignedShort ( currentOffset + 2 ) ; int opensToCount = readUnsignedShort ( currentOffset + 4 ) ; currentOffset += 6 ; String [ ] opensTo = null ; if ( opensToCount != 0 ) { opensTo = new String [ opensToCount ] ; for ( int i = 0 ; i < opensToCount ; ++ i ) { opensTo [ i ] = readModule ( currentOffset , buffer ) ; currentOffset += 2 ; } } moduleVisitor . visitOpen ( opens , opensFlags , opensTo ) ; } // Read the ' uses _ count ' and ' uses ' fields .
int usesCount = readUnsignedShort ( currentOffset ) ; currentOffset += 2 ; while ( usesCount -- > 0 ) { moduleVisitor . visitUse ( readClass ( currentOffset , buffer ) ) ; currentOffset += 2 ; } // Read the ' provides _ count ' and ' provides ' fields .
int providesCount = readUnsignedShort ( currentOffset ) ; currentOffset += 2 ; while ( providesCount -- > 0 ) { // Read the provides _ index , provides _ with _ count and provides _ with _ index fields and visit them .
String provides = readClass ( currentOffset , buffer ) ; int providesWithCount = readUnsignedShort ( currentOffset + 2 ) ; currentOffset += 4 ; String [ ] providesWith = new String [ providesWithCount ] ; for ( int i = 0 ; i < providesWithCount ; ++ i ) { providesWith [ i ] = readClass ( currentOffset , buffer ) ; currentOffset += 2 ; } moduleVisitor . visitProvide ( provides , providesWith ) ; } // Visit the end of the module attributes .
moduleVisitor . visitEnd ( ) ;


signature:
public class ClassReader { /** * Reads a JVMS field _ info structure and makes the given visitor visit it .
 * @ param classVisitor the visitor that must visit the field .
 * @ param context information about the class being parsed .
 * @ param fieldInfoOffset the start offset of the field _ info structure .
 * @ return the offset of the first byte following the field _ info structure . */
private int readField ( final ClassVisitor classVisitor , final Context context , final int fieldInfoOffset ) { } }

implementation:
char [ ] charBuffer = context . charBuffer ; // Read the access _ flags , name _ index and descriptor _ index fields .
int currentOffset = fieldInfoOffset ; int accessFlags = readUnsignedShort ( currentOffset ) ; String name = readUTF8 ( currentOffset + 2 , charBuffer ) ; String descriptor = readUTF8 ( currentOffset + 4 , charBuffer ) ; currentOffset += 6 ; // Read the field attributes ( the variables are ordered as in Section 4.7 of the JVMS ) .
// Attribute offsets exclude the attribute _ name _ index and attribute _ length fields .
// - The value corresponding to the ConstantValue attribute , or null .
Object constantValue = null ; // - The string corresponding to the Signature attribute , or null .
String signature = null ; // - The offset of the RuntimeVisibleAnnotations attribute , or 0.
int runtimeVisibleAnnotationsOffset = 0 ; // - The offset of the RuntimeInvisibleAnnotations attribute , or 0.
int runtimeInvisibleAnnotationsOffset = 0 ; // - The offset of the RuntimeVisibleTypeAnnotations attribute , or 0.
int runtimeVisibleTypeAnnotationsOffset = 0 ; // - The offset of the RuntimeInvisibleTypeAnnotations attribute , or 0.
int runtimeInvisibleTypeAnnotationsOffset = 0 ; // - The non standard attributes ( linked with their { @ link Attribute # nextAttribute } field ) .
// This list in the < i > reverse order < / i > or their order in the ClassFile structure .
Attribute attributes = null ; int attributesCount = readUnsignedShort ( currentOffset ) ; currentOffset += 2 ; while ( attributesCount -- > 0 ) { // Read the attribute _ info ' s attribute _ name and attribute _ length fields .
String attributeName = readUTF8 ( currentOffset , charBuffer ) ; int attributeLength = readInt ( currentOffset + 2 ) ; currentOffset += 6 ; // The tests are sorted in decreasing frequency order ( based on frequencies observed on
// typical classes ) .
if ( Constants . CONSTANT_VALUE . equals ( attributeName ) ) { int constantvalueIndex = readUnsignedShort ( currentOffset ) ; constantValue = constantvalueIndex == 0 ? null : readConst ( constantvalueIndex , charBuffer ) ; } else if ( Constants . SIGNATURE . equals ( attributeName ) ) { signature = readUTF8 ( currentOffset , charBuffer ) ; } else if ( Constants . DEPRECATED . equals ( attributeName ) ) { accessFlags |= Opcodes . ACC_DEPRECATED ; } else if ( Constants . SYNTHETIC . equals ( attributeName ) ) { accessFlags |= Opcodes . ACC_SYNTHETIC ; } else if ( Constants . RUNTIME_VISIBLE_ANNOTATIONS . equals ( attributeName ) ) { runtimeVisibleAnnotationsOffset = currentOffset ; } else if ( Constants . RUNTIME_VISIBLE_TYPE_ANNOTATIONS . equals ( attributeName ) ) { runtimeVisibleTypeAnnotationsOffset = currentOffset ; } else if ( Constants . RUNTIME_INVISIBLE_ANNOTATIONS . equals ( attributeName ) ) { runtimeInvisibleAnnotationsOffset = currentOffset ; } else if ( Constants . RUNTIME_INVISIBLE_TYPE_ANNOTATIONS . equals ( attributeName ) ) { runtimeInvisibleTypeAnnotationsOffset = currentOffset ; } else { Attribute attribute = readAttribute ( context . attributePrototypes , attributeName , currentOffset , attributeLength , charBuffer , - 1 , null ) ; attribute . nextAttribute = attributes ; attributes = attribute ; } currentOffset += attributeLength ; } // Visit the field declaration .
FieldVisitor fieldVisitor = classVisitor . visitField ( accessFlags , name , descriptor , signature , constantValue ) ; if ( fieldVisitor == null ) { return currentOffset ; } // Visit the RuntimeVisibleAnnotations attribute .
if ( runtimeVisibleAnnotationsOffset != 0 ) { int numAnnotations = readUnsignedShort ( runtimeVisibleAnnotationsOffset ) ; int currentAnnotationOffset = runtimeVisibleAnnotationsOffset + 2 ; while ( numAnnotations -- > 0 ) { // Parse the type _ index field .
String annotationDescriptor = readUTF8 ( currentAnnotationOffset , charBuffer ) ; currentAnnotationOffset += 2 ; // Parse num _ element _ value _ pairs and element _ value _ pairs and visit these values .
currentAnnotationOffset = readElementValues ( fieldVisitor . visitAnnotation ( annotationDescriptor , /* visible = */
true ) , currentAnnotationOffset , /* named = */
true , charBuffer ) ; } } // Visit the RuntimeInvisibleAnnotations attribute .
if ( runtimeInvisibleAnnotationsOffset != 0 ) { int numAnnotations = readUnsignedShort ( runtimeInvisibleAnnotationsOffset ) ; int currentAnnotationOffset = runtimeInvisibleAnnotationsOffset + 2 ; while ( numAnnotations -- > 0 ) { // Parse the type _ index field .
String annotationDescriptor = readUTF8 ( currentAnnotationOffset , charBuffer ) ; currentAnnotationOffset += 2 ; // Parse num _ element _ value _ pairs and element _ value _ pairs and visit these values .
currentAnnotationOffset = readElementValues ( fieldVisitor . visitAnnotation ( annotationDescriptor , /* visible = */
false ) , currentAnnotationOffset , /* named = */
true , charBuffer ) ; } } // Visit the RuntimeVisibleTypeAnnotations attribute .
if ( runtimeVisibleTypeAnnotationsOffset != 0 ) { int numAnnotations = readUnsignedShort ( runtimeVisibleTypeAnnotationsOffset ) ; int currentAnnotationOffset = runtimeVisibleTypeAnnotationsOffset + 2 ; while ( numAnnotations -- > 0 ) { // Parse the target _ type , target _ info and target _ path fields .
currentAnnotationOffset = readTypeAnnotationTarget ( context , currentAnnotationOffset ) ; // Parse the type _ index field .
String annotationDescriptor = readUTF8 ( currentAnnotationOffset , charBuffer ) ; currentAnnotationOffset += 2 ; // Parse num _ element _ value _ pairs and element _ value _ pairs and visit these values .
currentAnnotationOffset = readElementValues ( fieldVisitor . visitTypeAnnotation ( context . currentTypeAnnotationTarget , context . currentTypeAnnotationTargetPath , annotationDescriptor , /* visible = */
true ) , currentAnnotationOffset , /* named = */
true , charBuffer ) ; } } // Visit the RuntimeInvisibleTypeAnnotations attribute .
if ( runtimeInvisibleTypeAnnotationsOffset != 0 ) { int numAnnotations = readUnsignedShort ( runtimeInvisibleTypeAnnotationsOffset ) ; int currentAnnotationOffset = runtimeInvisibleTypeAnnotationsOffset + 2 ; while ( numAnnotations -- > 0 ) { // Parse the target _ type , target _ info and target _ path fields .
currentAnnotationOffset = readTypeAnnotationTarget ( context , currentAnnotationOffset ) ; // Parse the type _ index field .
String annotationDescriptor = readUTF8 ( currentAnnotationOffset , charBuffer ) ; currentAnnotationOffset += 2 ; // Parse num _ element _ value _ pairs and element _ value _ pairs and visit these values .
currentAnnotationOffset = readElementValues ( fieldVisitor . visitTypeAnnotation ( context . currentTypeAnnotationTarget , context . currentTypeAnnotationTargetPath , annotationDescriptor , /* visible = */
false ) , currentAnnotationOffset , /* named = */
true , charBuffer ) ; } } // Visit the non standard attributes .
while ( attributes != null ) { // Copy and reset the nextAttribute field so that it can also be used in FieldWriter .
Attribute nextAttribute = attributes . nextAttribute ; attributes . nextAttribute = null ; fieldVisitor . visitAttribute ( attributes ) ; attributes = nextAttribute ; } // Visit the end of the field .
fieldVisitor . visitEnd ( ) ; return currentOffset ;


signature:
public class ClassReader { /** * Reads a JVMS method _ info structure and makes the given visitor visit it .
 * @ param classVisitor the visitor that must visit the method .
 * @ param context information about the class being parsed .
 * @ param methodInfoOffset the start offset of the method _ info structure .
 * @ return the offset of the first byte following the method _ info structure . */
private int readMethod ( final ClassVisitor classVisitor , final Context context , final int methodInfoOffset ) { } }

implementation:
char [ ] charBuffer = context . charBuffer ; // Read the access _ flags , name _ index and descriptor _ index fields .
int currentOffset = methodInfoOffset ; context . currentMethodAccessFlags = readUnsignedShort ( currentOffset ) ; context . currentMethodName = readUTF8 ( currentOffset + 2 , charBuffer ) ; context . currentMethodDescriptor = readUTF8 ( currentOffset + 4 , charBuffer ) ; currentOffset += 6 ; // Read the method attributes ( the variables are ordered as in Section 4.7 of the JVMS ) .
// Attribute offsets exclude the attribute _ name _ index and attribute _ length fields .
// - The offset of the Code attribute , or 0.
int codeOffset = 0 ; // - The offset of the Exceptions attribute , or 0.
int exceptionsOffset = 0 ; // - The strings corresponding to the Exceptions attribute , or null .
String [ ] exceptions = null ; // - Whether the method has a Synthetic attribute .
boolean synthetic = false ; // - The constant pool index contained in the Signature attribute , or 0.
int signatureIndex = 0 ; // - The offset of the RuntimeVisibleAnnotations attribute , or 0.
int runtimeVisibleAnnotationsOffset = 0 ; // - The offset of the RuntimeInvisibleAnnotations attribute , or 0.
int runtimeInvisibleAnnotationsOffset = 0 ; // - The offset of the RuntimeVisibleParameterAnnotations attribute , or 0.
int runtimeVisibleParameterAnnotationsOffset = 0 ; // - The offset of the RuntimeInvisibleParameterAnnotations attribute , or 0.
int runtimeInvisibleParameterAnnotationsOffset = 0 ; // - The offset of the RuntimeVisibleTypeAnnotations attribute , or 0.
int runtimeVisibleTypeAnnotationsOffset = 0 ; // - The offset of the RuntimeInvisibleTypeAnnotations attribute , or 0.
int runtimeInvisibleTypeAnnotationsOffset = 0 ; // - The offset of the AnnotationDefault attribute , or 0.
int annotationDefaultOffset = 0 ; // - The offset of the MethodParameters attribute , or 0.
int methodParametersOffset = 0 ; // - The non standard attributes ( linked with their { @ link Attribute # nextAttribute } field ) .
// This list in the < i > reverse order < / i > or their order in the ClassFile structure .
Attribute attributes = null ; int attributesCount = readUnsignedShort ( currentOffset ) ; currentOffset += 2 ; while ( attributesCount -- > 0 ) { // Read the attribute _ info ' s attribute _ name and attribute _ length fields .
String attributeName = readUTF8 ( currentOffset , charBuffer ) ; int attributeLength = readInt ( currentOffset + 2 ) ; currentOffset += 6 ; // The tests are sorted in decreasing frequency order ( based on frequencies observed on
// typical classes ) .
if ( Constants . CODE . equals ( attributeName ) ) { if ( ( context . parsingOptions & SKIP_CODE ) == 0 ) { codeOffset = currentOffset ; } } else if ( Constants . EXCEPTIONS . equals ( attributeName ) ) { exceptionsOffset = currentOffset ; exceptions = new String [ readUnsignedShort ( exceptionsOffset ) ] ; int currentExceptionOffset = exceptionsOffset + 2 ; for ( int i = 0 ; i < exceptions . length ; ++ i ) { exceptions [ i ] = readClass ( currentExceptionOffset , charBuffer ) ; currentExceptionOffset += 2 ; } } else if ( Constants . SIGNATURE . equals ( attributeName ) ) { signatureIndex = readUnsignedShort ( currentOffset ) ; } else if ( Constants . DEPRECATED . equals ( attributeName ) ) { context . currentMethodAccessFlags |= Opcodes . ACC_DEPRECATED ; } else if ( Constants . RUNTIME_VISIBLE_ANNOTATIONS . equals ( attributeName ) ) { runtimeVisibleAnnotationsOffset = currentOffset ; } else if ( Constants . RUNTIME_VISIBLE_TYPE_ANNOTATIONS . equals ( attributeName ) ) { runtimeVisibleTypeAnnotationsOffset = currentOffset ; } else if ( Constants . ANNOTATION_DEFAULT . equals ( attributeName ) ) { annotationDefaultOffset = currentOffset ; } else if ( Constants . SYNTHETIC . equals ( attributeName ) ) { synthetic = true ; context . currentMethodAccessFlags |= Opcodes . ACC_SYNTHETIC ; } else if ( Constants . RUNTIME_INVISIBLE_ANNOTATIONS . equals ( attributeName ) ) { runtimeInvisibleAnnotationsOffset = currentOffset ; } else if ( Constants . RUNTIME_INVISIBLE_TYPE_ANNOTATIONS . equals ( attributeName ) ) { runtimeInvisibleTypeAnnotationsOffset = currentOffset ; } else if ( Constants . RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS . equals ( attributeName ) ) { runtimeVisibleParameterAnnotationsOffset = currentOffset ; } else if ( Constants . RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS . equals ( attributeName ) ) { runtimeInvisibleParameterAnnotationsOffset = currentOffset ; } else if ( Constants . METHOD_PARAMETERS . equals ( attributeName ) ) { methodParametersOffset = currentOffset ; } else { Attribute attribute = readAttribute ( context . attributePrototypes , attributeName , currentOffset , attributeLength , charBuffer , - 1 , null ) ; attribute . nextAttribute = attributes ; attributes = attribute ; } currentOffset += attributeLength ; } // Visit the method declaration .
MethodVisitor methodVisitor = classVisitor . visitMethod ( context . currentMethodAccessFlags , context . currentMethodName , context . currentMethodDescriptor , signatureIndex == 0 ? null : readUtf ( signatureIndex , charBuffer ) , exceptions ) ; if ( methodVisitor == null ) { return currentOffset ; } // If the returned MethodVisitor is in fact a MethodWriter , it means there is no method
// adapter between the reader and the writer . In this case , it might be possible to copy
// the method attributes directly into the writer . If so , return early without visiting
// the content of these attributes .
if ( methodVisitor instanceof MethodWriter ) { MethodWriter methodWriter = ( MethodWriter ) methodVisitor ; if ( methodWriter . canCopyMethodAttributes ( this , methodInfoOffset , currentOffset - methodInfoOffset , synthetic , ( context . currentMethodAccessFlags & Opcodes . ACC_DEPRECATED ) != 0 , readUnsignedShort ( methodInfoOffset + 4 ) , signatureIndex , exceptionsOffset ) ) { return currentOffset ; } } // Visit the MethodParameters attribute .
if ( methodParametersOffset != 0 ) { int parametersCount = readByte ( methodParametersOffset ) ; int currentParameterOffset = methodParametersOffset + 1 ; while ( parametersCount -- > 0 ) { // Read the name _ index and access _ flags fields and visit them .
methodVisitor . visitParameter ( readUTF8 ( currentParameterOffset , charBuffer ) , readUnsignedShort ( currentParameterOffset + 2 ) ) ; currentParameterOffset += 4 ; } } // Visit the AnnotationDefault attribute .
if ( annotationDefaultOffset != 0 ) { AnnotationVisitor annotationVisitor = methodVisitor . visitAnnotationDefault ( ) ; readElementValue ( annotationVisitor , annotationDefaultOffset , null , charBuffer ) ; if ( annotationVisitor != null ) { annotationVisitor . visitEnd ( ) ; } } // Visit the RuntimeVisibleAnnotations attribute .
if ( runtimeVisibleAnnotationsOffset != 0 ) { int numAnnotations = readUnsignedShort ( runtimeVisibleAnnotationsOffset ) ; int currentAnnotationOffset = runtimeVisibleAnnotationsOffset + 2 ; while ( numAnnotations -- > 0 ) { // Parse the type _ index field .
String annotationDescriptor = readUTF8 ( currentAnnotationOffset , charBuffer ) ; currentAnnotationOffset += 2 ; // Parse num _ element _ value _ pairs and element _ value _ pairs and visit these values .
currentAnnotationOffset = readElementValues ( methodVisitor . visitAnnotation ( annotationDescriptor , /* visible = */
true ) , currentAnnotationOffset , /* named = */
true , charBuffer ) ; } } // Visit the RuntimeInvisibleAnnotations attribute .
if ( runtimeInvisibleAnnotationsOffset != 0 ) { int numAnnotations = readUnsignedShort ( runtimeInvisibleAnnotationsOffset ) ; int currentAnnotationOffset = runtimeInvisibleAnnotationsOffset + 2 ; while ( numAnnotations -- > 0 ) { // Parse the type _ index field .
String annotationDescriptor = readUTF8 ( currentAnnotationOffset , charBuffer ) ; currentAnnotationOffset += 2 ; // Parse num _ element _ value _ pairs and element _ value _ pairs and visit these values .
currentAnnotationOffset = readElementValues ( methodVisitor . visitAnnotation ( annotationDescriptor , /* visible = */
false ) , currentAnnotationOffset , /* named = */
true , charBuffer ) ; } } // Visit the RuntimeVisibleTypeAnnotations attribute .
if ( runtimeVisibleTypeAnnotationsOffset != 0 ) { int numAnnotations = readUnsignedShort ( runtimeVisibleTypeAnnotationsOffset ) ; int currentAnnotationOffset = runtimeVisibleTypeAnnotationsOffset + 2 ; while ( numAnnotations -- > 0 ) { // Parse the target _ type , target _ info and target _ path fields .
currentAnnotationOffset = readTypeAnnotationTarget ( context , currentAnnotationOffset ) ; // Parse the type _ index field .
String annotationDescriptor = readUTF8 ( currentAnnotationOffset , charBuffer ) ; currentAnnotationOffset += 2 ; // Parse num _ element _ value _ pairs and element _ value _ pairs and visit these values .
currentAnnotationOffset = readElementValues ( methodVisitor . visitTypeAnnotation ( context . currentTypeAnnotationTarget , context . currentTypeAnnotationTargetPath , annotationDescriptor , /* visible = */
true ) , currentAnnotationOffset , /* named = */
true , charBuffer ) ; } } // Visit the RuntimeInvisibleTypeAnnotations attribute .
if ( runtimeInvisibleTypeAnnotationsOffset != 0 ) { int numAnnotations = readUnsignedShort ( runtimeInvisibleTypeAnnotationsOffset ) ; int currentAnnotationOffset = runtimeInvisibleTypeAnnotationsOffset + 2 ; while ( numAnnotations -- > 0 ) { // Parse the target _ type , target _ info and target _ path fields .
currentAnnotationOffset = readTypeAnnotationTarget ( context , currentAnnotationOffset ) ; // Parse the type _ index field .
String annotationDescriptor = readUTF8 ( currentAnnotationOffset , charBuffer ) ; currentAnnotationOffset += 2 ; // Parse num _ element _ value _ pairs and element _ value _ pairs and visit these values .
currentAnnotationOffset = readElementValues ( methodVisitor . visitTypeAnnotation ( context . currentTypeAnnotationTarget , context . currentTypeAnnotationTargetPath , annotationDescriptor , /* visible = */
false ) , currentAnnotationOffset , /* named = */
true , charBuffer ) ; } } // Visit the RuntimeVisibleParameterAnnotations attribute .
if ( runtimeVisibleParameterAnnotationsOffset != 0 ) { readParameterAnnotations ( methodVisitor , context , runtimeVisibleParameterAnnotationsOffset , /* visible = */
true ) ; } // Visit the RuntimeInvisibleParameterAnnotations attribute .
if ( runtimeInvisibleParameterAnnotationsOffset != 0 ) { readParameterAnnotations ( methodVisitor , context , runtimeInvisibleParameterAnnotationsOffset , /* visible = */
false ) ; } // Visit the non standard attributes .
while ( attributes != null ) { // Copy and reset the nextAttribute field so that it can also be used in MethodWriter .
Attribute nextAttribute = attributes . nextAttribute ; attributes . nextAttribute = null ; methodVisitor . visitAttribute ( attributes ) ; attributes = nextAttribute ; } // Visit the Code attribute .
if ( codeOffset != 0 ) { methodVisitor . visitCode ( ) ; readCode ( methodVisitor , context , codeOffset ) ; } // Visit the end of the method .
methodVisitor . visitEnd ( ) ; return currentOffset ;


signature:
public class ClassReader { /** * Reads a JVMS ' Code ' attribute and makes the given visitor visit it .
 * @ param methodVisitor the visitor that must visit the Code attribute .
 * @ param context information about the class being parsed .
 * @ param codeOffset the start offset in { @ link # b } of the Code attribute , excluding its
 * attribute _ name _ index and attribute _ length fields . */
private void readCode ( final MethodVisitor methodVisitor , final Context context , final int codeOffset ) { } }

implementation:
int currentOffset = codeOffset ; // Read the max _ stack , max _ locals and code _ length fields .
final byte [ ] classFileBuffer = b ; final char [ ] charBuffer = context . charBuffer ; final int maxStack = readUnsignedShort ( currentOffset ) ; final int maxLocals = readUnsignedShort ( currentOffset + 2 ) ; final int codeLength = readInt ( currentOffset + 4 ) ; currentOffset += 8 ; // Read the bytecode ' code ' array to create a label for each referenced instruction .
final int bytecodeStartOffset = currentOffset ; final int bytecodeEndOffset = currentOffset + codeLength ; final Label [ ] labels = context . currentMethodLabels = new Label [ codeLength + 1 ] ; while ( currentOffset < bytecodeEndOffset ) { final int bytecodeOffset = currentOffset - bytecodeStartOffset ; final int opcode = classFileBuffer [ currentOffset ] & 0xFF ; switch ( opcode ) { case Constants . NOP : case Constants . ACONST_NULL : case Constants . ICONST_M1 : case Constants . ICONST_0 : case Constants . ICONST_1 : case Constants . ICONST_2 : case Constants . ICONST_3 : case Constants . ICONST_4 : case Constants . ICONST_5 : case Constants . LCONST_0 : case Constants . LCONST_1 : case Constants . FCONST_0 : case Constants . FCONST_1 : case Constants . FCONST_2 : case Constants . DCONST_0 : case Constants . DCONST_1 : case Constants . IALOAD : case Constants . LALOAD : case Constants . FALOAD : case Constants . DALOAD : case Constants . AALOAD : case Constants . BALOAD : case Constants . CALOAD : case Constants . SALOAD : case Constants . IASTORE : case Constants . LASTORE : case Constants . FASTORE : case Constants . DASTORE : case Constants . AASTORE : case Constants . BASTORE : case Constants . CASTORE : case Constants . SASTORE : case Constants . POP : case Constants . POP2 : case Constants . DUP : case Constants . DUP_X1 : case Constants . DUP_X2 : case Constants . DUP2 : case Constants . DUP2_X1 : case Constants . DUP2_X2 : case Constants . SWAP : case Constants . IADD : case Constants . LADD : case Constants . FADD : case Constants . DADD : case Constants . ISUB : case Constants . LSUB : case Constants . FSUB : case Constants . DSUB : case Constants . IMUL : case Constants . LMUL : case Constants . FMUL : case Constants . DMUL : case Constants . IDIV : case Constants . LDIV : case Constants . FDIV : case Constants . DDIV : case Constants . IREM : case Constants . LREM : case Constants . FREM : case Constants . DREM : case Constants . INEG : case Constants . LNEG : case Constants . FNEG : case Constants . DNEG : case Constants . ISHL : case Constants . LSHL : case Constants . ISHR : case Constants . LSHR : case Constants . IUSHR : case Constants . LUSHR : case Constants . IAND : case Constants . LAND : case Constants . IOR : case Constants . LOR : case Constants . IXOR : case Constants . LXOR : case Constants . I2L : case Constants . I2F : case Constants . I2D : case Constants . L2I : case Constants . L2F : case Constants . L2D : case Constants . F2I : case Constants . F2L : case Constants . F2D : case Constants . D2I : case Constants . D2L : case Constants . D2F : case Constants . I2B : case Constants . I2C : case Constants . I2S : case Constants . LCMP : case Constants . FCMPL : case Constants . FCMPG : case Constants . DCMPL : case Constants . DCMPG : case Constants . IRETURN : case Constants . LRETURN : case Constants . FRETURN : case Constants . DRETURN : case Constants . ARETURN : case Constants . RETURN : case Constants . ARRAYLENGTH : case Constants . ATHROW : case Constants . MONITORENTER : case Constants . MONITOREXIT : case Constants . ILOAD_0 : case Constants . ILOAD_1 : case Constants . ILOAD_2 : case Constants . ILOAD_3 : case Constants . LLOAD_0 : case Constants . LLOAD_1 : case Constants . LLOAD_2 : case Constants . LLOAD_3 : case Constants . FLOAD_0 : case Constants . FLOAD_1 : case Constants . FLOAD_2 : case Constants . FLOAD_3 : case Constants . DLOAD_0 : case Constants . DLOAD_1 : case Constants . DLOAD_2 : case Constants . DLOAD_3 : case Constants . ALOAD_0 : case Constants . ALOAD_1 : case Constants . ALOAD_2 : case Constants . ALOAD_3 : case Constants . ISTORE_0 : case Constants . ISTORE_1 : case Constants . ISTORE_2 : case Constants . ISTORE_3 : case Constants . LSTORE_0 : case Constants . LSTORE_1 : case Constants . LSTORE_2 : case Constants . LSTORE_3 : case Constants . FSTORE_0 : case Constants . FSTORE_1 : case Constants . FSTORE_2 : case Constants . FSTORE_3 : case Constants . DSTORE_0 : case Constants . DSTORE_1 : case Constants . DSTORE_2 : case Constants . DSTORE_3 : case Constants . ASTORE_0 : case Constants . ASTORE_1 : case Constants . ASTORE_2 : case Constants . ASTORE_3 : currentOffset += 1 ; break ; case Constants . IFEQ : case Constants . IFNE : case Constants . IFLT : case Constants . IFGE : case Constants . IFGT : case Constants . IFLE : case Constants . IF_ICMPEQ : case Constants . IF_ICMPNE : case Constants . IF_ICMPLT : case Constants . IF_ICMPGE : case Constants . IF_ICMPGT : case Constants . IF_ICMPLE : case Constants . IF_ACMPEQ : case Constants . IF_ACMPNE : case Constants . GOTO : case Constants . JSR : case Constants . IFNULL : case Constants . IFNONNULL : createLabel ( bytecodeOffset + readShort ( currentOffset + 1 ) , labels ) ; currentOffset += 3 ; break ; case Constants . ASM_IFEQ : case Constants . ASM_IFNE : case Constants . ASM_IFLT : case Constants . ASM_IFGE : case Constants . ASM_IFGT : case Constants . ASM_IFLE : case Constants . ASM_IF_ICMPEQ : case Constants . ASM_IF_ICMPNE : case Constants . ASM_IF_ICMPLT : case Constants . ASM_IF_ICMPGE : case Constants . ASM_IF_ICMPGT : case Constants . ASM_IF_ICMPLE : case Constants . ASM_IF_ACMPEQ : case Constants . ASM_IF_ACMPNE : case Constants . ASM_GOTO : case Constants . ASM_JSR : case Constants . ASM_IFNULL : case Constants . ASM_IFNONNULL : createLabel ( bytecodeOffset + readUnsignedShort ( currentOffset + 1 ) , labels ) ; currentOffset += 3 ; break ; case Constants . GOTO_W : case Constants . JSR_W : case Constants . ASM_GOTO_W : createLabel ( bytecodeOffset + readInt ( currentOffset + 1 ) , labels ) ; currentOffset += 5 ; break ; case Constants . WIDE : switch ( classFileBuffer [ currentOffset + 1 ] & 0xFF ) { case Constants . ILOAD : case Constants . FLOAD : case Constants . ALOAD : case Constants . LLOAD : case Constants . DLOAD : case Constants . ISTORE : case Constants . FSTORE : case Constants . ASTORE : case Constants . LSTORE : case Constants . DSTORE : case Constants . RET : currentOffset += 4 ; break ; case Constants . IINC : currentOffset += 6 ; break ; default : throw new IllegalArgumentException ( ) ; } break ; case Constants . TABLESWITCH : // Skip 0 to 3 padding bytes .
currentOffset += 4 - ( bytecodeOffset & 3 ) ; // Read the default label and the number of table entries .
createLabel ( bytecodeOffset + readInt ( currentOffset ) , labels ) ; int numTableEntries = readInt ( currentOffset + 8 ) - readInt ( currentOffset + 4 ) + 1 ; currentOffset += 12 ; // Read the table labels .
while ( numTableEntries -- > 0 ) { createLabel ( bytecodeOffset + readInt ( currentOffset ) , labels ) ; currentOffset += 4 ; } break ; case Constants . LOOKUPSWITCH : // Skip 0 to 3 padding bytes .
currentOffset += 4 - ( bytecodeOffset & 3 ) ; // Read the default label and the number of switch cases .
createLabel ( bytecodeOffset + readInt ( currentOffset ) , labels ) ; int numSwitchCases = readInt ( currentOffset + 4 ) ; currentOffset += 8 ; // Read the switch labels .
while ( numSwitchCases -- > 0 ) { createLabel ( bytecodeOffset + readInt ( currentOffset + 4 ) , labels ) ; currentOffset += 8 ; } break ; case Constants . ILOAD : case Constants . LLOAD : case Constants . FLOAD : case Constants . DLOAD : case Constants . ALOAD : case Constants . ISTORE : case Constants . LSTORE : case Constants . FSTORE : case Constants . DSTORE : case Constants . ASTORE : case Constants . RET : case Constants . BIPUSH : case Constants . NEWARRAY : case Constants . LDC : currentOffset += 2 ; break ; case Constants . SIPUSH : case Constants . LDC_W : case Constants . LDC2_W : case Constants . GETSTATIC : case Constants . PUTSTATIC : case Constants . GETFIELD : case Constants . PUTFIELD : case Constants . INVOKEVIRTUAL : case Constants . INVOKESPECIAL : case Constants . INVOKESTATIC : case Constants . NEW : case Constants . ANEWARRAY : case Constants . CHECKCAST : case Constants . INSTANCEOF : case Constants . IINC : currentOffset += 3 ; break ; case Constants . INVOKEINTERFACE : case Constants . INVOKEDYNAMIC : currentOffset += 5 ; break ; case Constants . MULTIANEWARRAY : currentOffset += 4 ; break ; default : throw new IllegalArgumentException ( ) ; } } // Read the ' exception _ table _ length ' and ' exception _ table ' field to create a label for each
// referenced instruction , and to make methodVisitor visit the corresponding try catch blocks .
int exceptionTableLength = readUnsignedShort ( currentOffset ) ; currentOffset += 2 ; while ( exceptionTableLength -- > 0 ) { Label start = createLabel ( readUnsignedShort ( currentOffset ) , labels ) ; Label end = createLabel ( readUnsignedShort ( currentOffset + 2 ) , labels ) ; Label handler = createLabel ( readUnsignedShort ( currentOffset + 4 ) , labels ) ; String catchType = readUTF8 ( cpInfoOffsets [ readUnsignedShort ( currentOffset + 6 ) ] , charBuffer ) ; currentOffset += 8 ; methodVisitor . visitTryCatchBlock ( start , end , handler , catchType ) ; } // Read the Code attributes to create a label for each referenced instruction ( the variables
// are ordered as in Section 4.7 of the JVMS ) . Attribute offsets exclude the
// attribute _ name _ index and attribute _ length fields .
// - The offset of the current ' stack _ map _ frame ' in the StackMap [ Table ] attribute , or 0.
// Initially , this is the offset of the first ' stack _ map _ frame ' entry . Then this offset is
// updated after each stack _ map _ frame is read .
int stackMapFrameOffset = 0 ; // - The end offset of the StackMap [ Table ] attribute , or 0.
int stackMapTableEndOffset = 0 ; // - Whether the stack map frames are compressed ( i . e . in a StackMapTable ) or not .
boolean compressedFrames = true ; // - The offset of the LocalVariableTable attribute , or 0.
int localVariableTableOffset = 0 ; // - The offset of the LocalVariableTypeTable attribute , or 0.
int localVariableTypeTableOffset = 0 ; // - The offset of each ' type _ annotation ' entry in the RuntimeVisibleTypeAnnotations
// attribute , or null .
int [ ] visibleTypeAnnotationOffsets = null ; // - The offset of each ' type _ annotation ' entry in the RuntimeInvisibleTypeAnnotations
// attribute , or null .
int [ ] invisibleTypeAnnotationOffsets = null ; // - The non standard attributes ( linked with their { @ link Attribute # nextAttribute } field ) .
// This list in the < i > reverse order < / i > or their order in the ClassFile structure .
Attribute attributes = null ; int attributesCount = readUnsignedShort ( currentOffset ) ; currentOffset += 2 ; while ( attributesCount -- > 0 ) { // Read the attribute _ info ' s attribute _ name and attribute _ length fields .
String attributeName = readUTF8 ( currentOffset , charBuffer ) ; int attributeLength = readInt ( currentOffset + 2 ) ; currentOffset += 6 ; if ( Constants . LOCAL_VARIABLE_TABLE . equals ( attributeName ) ) { if ( ( context . parsingOptions & SKIP_DEBUG ) == 0 ) { localVariableTableOffset = currentOffset ; // Parse the attribute to find the corresponding ( debug only ) labels .
int currentLocalVariableTableOffset = currentOffset ; int localVariableTableLength = readUnsignedShort ( currentLocalVariableTableOffset ) ; currentLocalVariableTableOffset += 2 ; while ( localVariableTableLength -- > 0 ) { int startPc = readUnsignedShort ( currentLocalVariableTableOffset ) ; createDebugLabel ( startPc , labels ) ; int length = readUnsignedShort ( currentLocalVariableTableOffset + 2 ) ; createDebugLabel ( startPc + length , labels ) ; // Skip the name _ index , descriptor _ index and index fields ( 2 bytes each ) .
currentLocalVariableTableOffset += 10 ; } } } else if ( Constants . LOCAL_VARIABLE_TYPE_TABLE . equals ( attributeName ) ) { localVariableTypeTableOffset = currentOffset ; // Here we do not extract the labels corresponding to the attribute content . We assume they
// are the same or a subset of those of the LocalVariableTable attribute .
} else if ( Constants . LINE_NUMBER_TABLE . equals ( attributeName ) ) { if ( ( context . parsingOptions & SKIP_DEBUG ) == 0 ) { // Parse the attribute to find the corresponding ( debug only ) labels .
int currentLineNumberTableOffset = currentOffset ; int lineNumberTableLength = readUnsignedShort ( currentLineNumberTableOffset ) ; currentLineNumberTableOffset += 2 ; while ( lineNumberTableLength -- > 0 ) { int startPc = readUnsignedShort ( currentLineNumberTableOffset ) ; int lineNumber = readUnsignedShort ( currentLineNumberTableOffset + 2 ) ; currentLineNumberTableOffset += 4 ; createDebugLabel ( startPc , labels ) ; labels [ startPc ] . addLineNumber ( lineNumber ) ; } } } else if ( Constants . RUNTIME_VISIBLE_TYPE_ANNOTATIONS . equals ( attributeName ) ) { visibleTypeAnnotationOffsets = readTypeAnnotations ( methodVisitor , context , currentOffset , /* visible = */
true ) ; // Here we do not extract the labels corresponding to the attribute content . This would
// require a full parsing of the attribute , which would need to be repeated when parsing
// the bytecode instructions ( see below ) . Instead , the content of the attribute is read one
// type annotation at a time ( i . e . after a type annotation has been visited , the next type
// annotation is read ) , and the labels it contains are also extracted one annotation at a
// time . This assumes that type annotations are ordered by increasing bytecode offset .
} else if ( Constants . RUNTIME_INVISIBLE_TYPE_ANNOTATIONS . equals ( attributeName ) ) { invisibleTypeAnnotationOffsets = readTypeAnnotations ( methodVisitor , context , currentOffset , /* visible = */
false ) ; // Same comment as above for the RuntimeVisibleTypeAnnotations attribute .
} else if ( Constants . STACK_MAP_TABLE . equals ( attributeName ) ) { if ( ( context . parsingOptions & SKIP_FRAMES ) == 0 ) { stackMapFrameOffset = currentOffset + 2 ; stackMapTableEndOffset = currentOffset + attributeLength ; } // Here we do not extract the labels corresponding to the attribute content . This would
// require a full parsing of the attribute , which would need to be repeated when parsing
// the bytecode instructions ( see below ) . Instead , the content of the attribute is read one
// frame at a time ( i . e . after a frame has been visited , the next frame is read ) , and the
// labels it contains are also extracted one frame at a time . Thanks to the ordering of
// frames , having only a " one frame lookahead " is not a problem , i . e . it is not possible to
// see an offset smaller than the offset of the current instruction and for which no Label
// exist . Except for UNINITIALIZED type offsets . We solve this by parsing the stack map
// table without a full decoding ( see below ) .
} else if ( "StackMap" . equals ( attributeName ) ) { if ( ( context . parsingOptions & SKIP_FRAMES ) == 0 ) { stackMapFrameOffset = currentOffset + 2 ; stackMapTableEndOffset = currentOffset + attributeLength ; compressedFrames = false ; } // IMPORTANT ! Here we assume that the frames are ordered , as in the StackMapTable attribute ,
// although this is not guaranteed by the attribute format . This allows an incremental
// extraction of the labels corresponding to this attribute ( see the comment above for the
// StackMapTable attribute ) .
} else { Attribute attribute = readAttribute ( context . attributePrototypes , attributeName , currentOffset , attributeLength , charBuffer , codeOffset , labels ) ; attribute . nextAttribute = attributes ; attributes = attribute ; } currentOffset += attributeLength ; } // Initialize the context fields related to stack map frames , and generate the first
// ( implicit ) stack map frame , if needed .
final boolean expandFrames = ( context . parsingOptions & EXPAND_FRAMES ) != 0 ; if ( stackMapFrameOffset != 0 ) { // The bytecode offset of the first explicit frame is not offset _ delta + 1 but only
// offset _ delta . Setting the implicit frame offset to - 1 allows us to use of the
// " offset _ delta + 1 " rule in all cases .
context . currentFrameOffset = - 1 ; context . currentFrameType = 0 ; context . currentFrameLocalCount = 0 ; context . currentFrameLocalCountDelta = 0 ; context . currentFrameLocalTypes = new Object [ maxLocals ] ; context . currentFrameStackCount = 0 ; context . currentFrameStackTypes = new Object [ maxStack ] ; if ( expandFrames ) { computeImplicitFrame ( context ) ; } // Find the labels for UNINITIALIZED frame types . Instead of decoding each element of the
// stack map table , we look for 3 consecutive bytes that " look like " an UNINITIALIZED type
// ( tag ITEM _ Uninitialized , offset within bytecode bounds , NEW instruction at this offset ) .
// We may find false positives ( i . e . not real UNINITIALIZED types ) , but this should be rare ,
// and the only consequence will be the creation of an unneeded label . This is better than
// creating a label for each NEW instruction , and faster than fully decoding the whole stack
// map table .
for ( int offset = stackMapFrameOffset ; offset < stackMapTableEndOffset - 2 ; ++ offset ) { if ( classFileBuffer [ offset ] == Frame . ITEM_UNINITIALIZED ) { int potentialBytecodeOffset = readUnsignedShort ( offset + 1 ) ; if ( potentialBytecodeOffset >= 0 && potentialBytecodeOffset < codeLength && ( classFileBuffer [ bytecodeStartOffset + potentialBytecodeOffset ] & 0xFF ) == Opcodes . NEW ) { createLabel ( potentialBytecodeOffset , labels ) ; } } } } if ( expandFrames && ( context . parsingOptions & EXPAND_ASM_INSNS ) != 0 ) { // Expanding the ASM specific instructions can introduce F _ INSERT frames , even if the method
// does not currently have any frame . These inserted frames must be computed by simulating the
// effect of the bytecode instructions , one by one , starting from the implicit first frame .
// For this , MethodWriter needs to know maxLocals before the first instruction is visited . To
// ensure this , we visit the implicit first frame here ( passing only maxLocals - the rest is
// computed in MethodWriter ) .
methodVisitor . visitFrame ( Opcodes . F_NEW , maxLocals , null , 0 , null ) ; } // Visit the bytecode instructions . First , introduce state variables for the incremental parsing
// of the type annotations .
// Index of the next runtime visible type annotation to read ( in the
// visibleTypeAnnotationOffsets array ) .
int currentVisibleTypeAnnotationIndex = 0 ; // The bytecode offset of the next runtime visible type annotation to read , or - 1.
int currentVisibleTypeAnnotationBytecodeOffset = getTypeAnnotationBytecodeOffset ( visibleTypeAnnotationOffsets , 0 ) ; // Index of the next runtime invisible type annotation to read ( in the
// invisibleTypeAnnotationOffsets array ) .
int currentInvisibleTypeAnnotationIndex = 0 ; // The bytecode offset of the next runtime invisible type annotation to read , or - 1.
int currentInvisibleTypeAnnotationBytecodeOffset = getTypeAnnotationBytecodeOffset ( invisibleTypeAnnotationOffsets , 0 ) ; // Whether a F _ INSERT stack map frame must be inserted before the current instruction .
boolean insertFrame = false ; // The delta to subtract from a goto _ w or jsr _ w opcode to get the corresponding goto or jsr
// opcode , or 0 if goto _ w and jsr _ w must be left unchanged ( i . e . when expanding ASM specific
// instructions ) .
final int wideJumpOpcodeDelta = ( context . parsingOptions & EXPAND_ASM_INSNS ) == 0 ? Constants . WIDE_JUMP_OPCODE_DELTA : 0 ; currentOffset = bytecodeStartOffset ; while ( currentOffset < bytecodeEndOffset ) { final int currentBytecodeOffset = currentOffset - bytecodeStartOffset ; // Visit the label and the line number ( s ) for this bytecode offset , if any .
Label currentLabel = labels [ currentBytecodeOffset ] ; if ( currentLabel != null ) { currentLabel . accept ( methodVisitor , ( context . parsingOptions & SKIP_DEBUG ) == 0 ) ; } // Visit the stack map frame for this bytecode offset , if any .
while ( stackMapFrameOffset != 0 && ( context . currentFrameOffset == currentBytecodeOffset || context . currentFrameOffset == - 1 ) ) { // If there is a stack map frame for this offset , make methodVisitor visit it , and read the
// next stack map frame if there is one .
if ( context . currentFrameOffset != - 1 ) { if ( ! compressedFrames || expandFrames ) { methodVisitor . visitFrame ( Opcodes . F_NEW , context . currentFrameLocalCount , context . currentFrameLocalTypes , context . currentFrameStackCount , context . currentFrameStackTypes ) ; } else { methodVisitor . visitFrame ( context . currentFrameType , context . currentFrameLocalCountDelta , context . currentFrameLocalTypes , context . currentFrameStackCount , context . currentFrameStackTypes ) ; } // Since there is already a stack map frame for this bytecode offset , there is no need to
// insert a new one .
insertFrame = false ; } if ( stackMapFrameOffset < stackMapTableEndOffset ) { stackMapFrameOffset = readStackMapFrame ( stackMapFrameOffset , compressedFrames , expandFrames , context ) ; } else { stackMapFrameOffset = 0 ; } } // Insert a stack map frame for this bytecode offset , if requested by setting insertFrame to
// true during the previous iteration . The actual frame content is computed in MethodWriter .
if ( insertFrame ) { if ( ( context . parsingOptions & EXPAND_FRAMES ) != 0 ) { methodVisitor . visitFrame ( Constants . F_INSERT , 0 , null , 0 , null ) ; } insertFrame = false ; } // Visit the instruction at this bytecode offset .
int opcode = classFileBuffer [ currentOffset ] & 0xFF ; switch ( opcode ) { case Constants . NOP : case Constants . ACONST_NULL : case Constants . ICONST_M1 : case Constants . ICONST_0 : case Constants . ICONST_1 : case Constants . ICONST_2 : case Constants . ICONST_3 : case Constants . ICONST_4 : case Constants . ICONST_5 : case Constants . LCONST_0 : case Constants . LCONST_1 : case Constants . FCONST_0 : case Constants . FCONST_1 : case Constants . FCONST_2 : case Constants . DCONST_0 : case Constants . DCONST_1 : case Constants . IALOAD : case Constants . LALOAD : case Constants . FALOAD : case Constants . DALOAD : case Constants . AALOAD : case Constants . BALOAD : case Constants . CALOAD : case Constants . SALOAD : case Constants . IASTORE : case Constants . LASTORE : case Constants . FASTORE : case Constants . DASTORE : case Constants . AASTORE : case Constants . BASTORE : case Constants . CASTORE : case Constants . SASTORE : case Constants . POP : case Constants . POP2 : case Constants . DUP : case Constants . DUP_X1 : case Constants . DUP_X2 : case Constants . DUP2 : case Constants . DUP2_X1 : case Constants . DUP2_X2 : case Constants . SWAP : case Constants . IADD : case Constants . LADD : case Constants . FADD : case Constants . DADD : case Constants . ISUB : case Constants . LSUB : case Constants . FSUB : case Constants . DSUB : case Constants . IMUL : case Constants . LMUL : case Constants . FMUL : case Constants . DMUL : case Constants . IDIV : case Constants . LDIV : case Constants . FDIV : case Constants . DDIV : case Constants . IREM : case Constants . LREM : case Constants . FREM : case Constants . DREM : case Constants . INEG : case Constants . LNEG : case Constants . FNEG : case Constants . DNEG : case Constants . ISHL : case Constants . LSHL : case Constants . ISHR : case Constants . LSHR : case Constants . IUSHR : case Constants . LUSHR : case Constants . IAND : case Constants . LAND : case Constants . IOR : case Constants . LOR : case Constants . IXOR : case Constants . LXOR : case Constants . I2L : case Constants . I2F : case Constants . I2D : case Constants . L2I : case Constants . L2F : case Constants . L2D : case Constants . F2I : case Constants . F2L : case Constants . F2D : case Constants . D2I : case Constants . D2L : case Constants . D2F : case Constants . I2B : case Constants . I2C : case Constants . I2S : case Constants . LCMP : case Constants . FCMPL : case Constants . FCMPG : case Constants . DCMPL : case Constants . DCMPG : case Constants . IRETURN : case Constants . LRETURN : case Constants . FRETURN : case Constants . DRETURN : case Constants . ARETURN : case Constants . RETURN : case Constants . ARRAYLENGTH : case Constants . ATHROW : case Constants . MONITORENTER : case Constants . MONITOREXIT : methodVisitor . visitInsn ( opcode ) ; currentOffset += 1 ; break ; case Constants . ILOAD_0 : case Constants . ILOAD_1 : case Constants . ILOAD_2 : case Constants . ILOAD_3 : case Constants . LLOAD_0 : case Constants . LLOAD_1 : case Constants . LLOAD_2 : case Constants . LLOAD_3 : case Constants . FLOAD_0 : case Constants . FLOAD_1 : case Constants . FLOAD_2 : case Constants . FLOAD_3 : case Constants . DLOAD_0 : case Constants . DLOAD_1 : case Constants . DLOAD_2 : case Constants . DLOAD_3 : case Constants . ALOAD_0 : case Constants . ALOAD_1 : case Constants . ALOAD_2 : case Constants . ALOAD_3 : opcode -= Constants . ILOAD_0 ; methodVisitor . visitVarInsn ( Opcodes . ILOAD + ( opcode >> 2 ) , opcode & 0x3 ) ; currentOffset += 1 ; break ; case Constants . ISTORE_0 : case Constants . ISTORE_1 : case Constants . ISTORE_2 : case Constants . ISTORE_3 : case Constants . LSTORE_0 : case Constants . LSTORE_1 : case Constants . LSTORE_2 : case Constants . LSTORE_3 : case Constants . FSTORE_0 : case Constants . FSTORE_1 : case Constants . FSTORE_2 : case Constants . FSTORE_3 : case Constants . DSTORE_0 : case Constants . DSTORE_1 : case Constants . DSTORE_2 : case Constants . DSTORE_3 : case Constants . ASTORE_0 : case Constants . ASTORE_1 : case Constants . ASTORE_2 : case Constants . ASTORE_3 : opcode -= Constants . ISTORE_0 ; methodVisitor . visitVarInsn ( Opcodes . ISTORE + ( opcode >> 2 ) , opcode & 0x3 ) ; currentOffset += 1 ; break ; case Constants . IFEQ : case Constants . IFNE : case Constants . IFLT : case Constants . IFGE : case Constants . IFGT : case Constants . IFLE : case Constants . IF_ICMPEQ : case Constants . IF_ICMPNE : case Constants . IF_ICMPLT : case Constants . IF_ICMPGE : case Constants . IF_ICMPGT : case Constants . IF_ICMPLE : case Constants . IF_ACMPEQ : case Constants . IF_ACMPNE : case Constants . GOTO : case Constants . JSR : case Constants . IFNULL : case Constants . IFNONNULL : methodVisitor . visitJumpInsn ( opcode , labels [ currentBytecodeOffset + readShort ( currentOffset + 1 ) ] ) ; currentOffset += 3 ; break ; case Constants . GOTO_W : case Constants . JSR_W : methodVisitor . visitJumpInsn ( opcode - wideJumpOpcodeDelta , labels [ currentBytecodeOffset + readInt ( currentOffset + 1 ) ] ) ; currentOffset += 5 ; break ; case Constants . ASM_IFEQ : case Constants . ASM_IFNE : case Constants . ASM_IFLT : case Constants . ASM_IFGE : case Constants . ASM_IFGT : case Constants . ASM_IFLE : case Constants . ASM_IF_ICMPEQ : case Constants . ASM_IF_ICMPNE : case Constants . ASM_IF_ICMPLT : case Constants . ASM_IF_ICMPGE : case Constants . ASM_IF_ICMPGT : case Constants . ASM_IF_ICMPLE : case Constants . ASM_IF_ACMPEQ : case Constants . ASM_IF_ACMPNE : case Constants . ASM_GOTO : case Constants . ASM_JSR : case Constants . ASM_IFNULL : case Constants . ASM_IFNONNULL : { // A forward jump with an offset > 32767 . In this case we automatically replace ASM _ GOTO
// with GOTO _ W , ASM _ JSR with JSR _ W and ASM _ IFxxx < l > with IFNOTxxx < L > GOTO _ W < l > L : . . . ,
// where IFNOTxxx is the " opposite " opcode of ASMS _ IFxxx ( e . g . IFNE for ASM _ IFEQ ) and
// where < L > designates the instruction just after the GOTO _ W .
// First , change the ASM specific opcodes ASM _ IFEQ . . . ASM _ JSR , ASM _ IFNULL and
// ASM _ IFNONNULL to IFEQ . . . JSR , IFNULL and IFNONNULL .
opcode = opcode < Constants . ASM_IFNULL ? opcode - Constants . ASM_OPCODE_DELTA : opcode - Constants . ASM_IFNULL_OPCODE_DELTA ; Label target = labels [ currentBytecodeOffset + readUnsignedShort ( currentOffset + 1 ) ] ; if ( opcode == Opcodes . GOTO || opcode == Opcodes . JSR ) { // Replace GOTO with GOTO _ W and JSR with JSR _ W .
methodVisitor . visitJumpInsn ( opcode + Constants . WIDE_JUMP_OPCODE_DELTA , target ) ; } else { // Compute the " opposite " of opcode . This can be done by flipping the least
// significant bit for IFNULL and IFNONNULL , and similarly for IFEQ . . . IF _ ACMPEQ
// ( with a pre and post offset by 1 ) .
opcode = opcode < Opcodes . GOTO ? ( ( opcode + 1 ) ^ 1 ) - 1 : opcode ^ 1 ; Label endif = createLabel ( currentBytecodeOffset + 3 , labels ) ; methodVisitor . visitJumpInsn ( opcode , endif ) ; methodVisitor . visitJumpInsn ( Constants . GOTO_W , target ) ; // endif designates the instruction just after GOTO _ W , and is visited as part of the
// next instruction . Since it is a jump target , we need to insert a frame here .
insertFrame = true ; } currentOffset += 3 ; break ; } case Constants . ASM_GOTO_W : { // Replace ASM _ GOTO _ W with GOTO _ W .
methodVisitor . visitJumpInsn ( Constants . GOTO_W , labels [ currentBytecodeOffset + readInt ( currentOffset + 1 ) ] ) ; // The instruction just after is a jump target ( because ASM _ GOTO _ W is used in patterns
// IFNOTxxx < L > ASM _ GOTO _ W < l > L : . . . , see MethodWriter ) , so we need to insert a frame
// here .
insertFrame = true ; currentOffset += 5 ; break ; } case Constants . WIDE : opcode = classFileBuffer [ currentOffset + 1 ] & 0xFF ; if ( opcode == Opcodes . IINC ) { methodVisitor . visitIincInsn ( readUnsignedShort ( currentOffset + 2 ) , readShort ( currentOffset + 4 ) ) ; currentOffset += 6 ; } else { methodVisitor . visitVarInsn ( opcode , readUnsignedShort ( currentOffset + 2 ) ) ; currentOffset += 4 ; } break ; case Constants . TABLESWITCH : { // Skip 0 to 3 padding bytes .
currentOffset += 4 - ( currentBytecodeOffset & 3 ) ; // Read the instruction .
Label defaultLabel = labels [ currentBytecodeOffset + readInt ( currentOffset ) ] ; int low = readInt ( currentOffset + 4 ) ; int high = readInt ( currentOffset + 8 ) ; currentOffset += 12 ; Label [ ] table = new Label [ high - low + 1 ] ; for ( int i = 0 ; i < table . length ; ++ i ) { table [ i ] = labels [ currentBytecodeOffset + readInt ( currentOffset ) ] ; currentOffset += 4 ; } methodVisitor . visitTableSwitchInsn ( low , high , defaultLabel , table ) ; break ; } case Constants . LOOKUPSWITCH : { // Skip 0 to 3 padding bytes .
currentOffset += 4 - ( currentBytecodeOffset & 3 ) ; // Read the instruction .
Label defaultLabel = labels [ currentBytecodeOffset + readInt ( currentOffset ) ] ; int numPairs = readInt ( currentOffset + 4 ) ; currentOffset += 8 ; int [ ] keys = new int [ numPairs ] ; Label [ ] values = new Label [ numPairs ] ; for ( int i = 0 ; i < numPairs ; ++ i ) { keys [ i ] = readInt ( currentOffset ) ; values [ i ] = labels [ currentBytecodeOffset + readInt ( currentOffset + 4 ) ] ; currentOffset += 8 ; } methodVisitor . visitLookupSwitchInsn ( defaultLabel , keys , values ) ; break ; } case Constants . ILOAD : case Constants . LLOAD : case Constants . FLOAD : case Constants . DLOAD : case Constants . ALOAD : case Constants . ISTORE : case Constants . LSTORE : case Constants . FSTORE : case Constants . DSTORE : case Constants . ASTORE : case Constants . RET : methodVisitor . visitVarInsn ( opcode , classFileBuffer [ currentOffset + 1 ] & 0xFF ) ; currentOffset += 2 ; break ; case Constants . BIPUSH : case Constants . NEWARRAY : methodVisitor . visitIntInsn ( opcode , classFileBuffer [ currentOffset + 1 ] ) ; currentOffset += 2 ; break ; case Constants . SIPUSH : methodVisitor . visitIntInsn ( opcode , readShort ( currentOffset + 1 ) ) ; currentOffset += 3 ; break ; case Constants . LDC : methodVisitor . visitLdcInsn ( readConst ( classFileBuffer [ currentOffset + 1 ] & 0xFF , charBuffer ) ) ; currentOffset += 2 ; break ; case Constants . LDC_W : case Constants . LDC2_W : methodVisitor . visitLdcInsn ( readConst ( readUnsignedShort ( currentOffset + 1 ) , charBuffer ) ) ; currentOffset += 3 ; break ; case Constants . GETSTATIC : case Constants . PUTSTATIC : case Constants . GETFIELD : case Constants . PUTFIELD : case Constants . INVOKEVIRTUAL : case Constants . INVOKESPECIAL : case Constants . INVOKESTATIC : case Constants . INVOKEINTERFACE : { int cpInfoOffset = cpInfoOffsets [ readUnsignedShort ( currentOffset + 1 ) ] ; int nameAndTypeCpInfoOffset = cpInfoOffsets [ readUnsignedShort ( cpInfoOffset + 2 ) ] ; String owner = readClass ( cpInfoOffset , charBuffer ) ; String name = readUTF8 ( nameAndTypeCpInfoOffset , charBuffer ) ; String descriptor = readUTF8 ( nameAndTypeCpInfoOffset + 2 , charBuffer ) ; if ( opcode < Opcodes . INVOKEVIRTUAL ) { methodVisitor . visitFieldInsn ( opcode , owner , name , descriptor ) ; } else { boolean isInterface = classFileBuffer [ cpInfoOffset - 1 ] == Symbol . CONSTANT_INTERFACE_METHODREF_TAG ; methodVisitor . visitMethodInsn ( opcode , owner , name , descriptor , isInterface ) ; } if ( opcode == Opcodes . INVOKEINTERFACE ) { currentOffset += 5 ; } else { currentOffset += 3 ; } break ; } case Constants . INVOKEDYNAMIC : { int cpInfoOffset = cpInfoOffsets [ readUnsignedShort ( currentOffset + 1 ) ] ; int nameAndTypeCpInfoOffset = cpInfoOffsets [ readUnsignedShort ( cpInfoOffset + 2 ) ] ; String name = readUTF8 ( nameAndTypeCpInfoOffset , charBuffer ) ; String descriptor = readUTF8 ( nameAndTypeCpInfoOffset + 2 , charBuffer ) ; int bootstrapMethodOffset = bootstrapMethodOffsets [ readUnsignedShort ( cpInfoOffset ) ] ; Handle handle = ( Handle ) readConst ( readUnsignedShort ( bootstrapMethodOffset ) , charBuffer ) ; Object [ ] bootstrapMethodArguments = new Object [ readUnsignedShort ( bootstrapMethodOffset + 2 ) ] ; bootstrapMethodOffset += 4 ; for ( int i = 0 ; i < bootstrapMethodArguments . length ; i ++ ) { bootstrapMethodArguments [ i ] = readConst ( readUnsignedShort ( bootstrapMethodOffset ) , charBuffer ) ; bootstrapMethodOffset += 2 ; } methodVisitor . visitInvokeDynamicInsn ( name , descriptor , handle , bootstrapMethodArguments ) ; currentOffset += 5 ; break ; } case Constants . NEW : case Constants . ANEWARRAY : case Constants . CHECKCAST : case Constants . INSTANCEOF : methodVisitor . visitTypeInsn ( opcode , readClass ( currentOffset + 1 , charBuffer ) ) ; currentOffset += 3 ; break ; case Constants . IINC : methodVisitor . visitIincInsn ( classFileBuffer [ currentOffset + 1 ] & 0xFF , classFileBuffer [ currentOffset + 2 ] ) ; currentOffset += 3 ; break ; case Constants . MULTIANEWARRAY : methodVisitor . visitMultiANewArrayInsn ( readClass ( currentOffset + 1 , charBuffer ) , classFileBuffer [ currentOffset + 3 ] & 0xFF ) ; currentOffset += 4 ; break ; default : throw new AssertionError ( ) ; } // Visit the runtime visible instruction annotations , if any .
while ( visibleTypeAnnotationOffsets != null && currentVisibleTypeAnnotationIndex < visibleTypeAnnotationOffsets . length && currentVisibleTypeAnnotationBytecodeOffset <= currentBytecodeOffset ) { if ( currentVisibleTypeAnnotationBytecodeOffset == currentBytecodeOffset ) { // Parse the target _ type , target _ info and target _ path fields .
int currentAnnotationOffset = readTypeAnnotationTarget ( context , visibleTypeAnnotationOffsets [ currentVisibleTypeAnnotationIndex ] ) ; // Parse the type _ index field .
String annotationDescriptor = readUTF8 ( currentAnnotationOffset , charBuffer ) ; currentAnnotationOffset += 2 ; // Parse num _ element _ value _ pairs and element _ value _ pairs and visit these values .
readElementValues ( methodVisitor . visitInsnAnnotation ( context . currentTypeAnnotationTarget , context . currentTypeAnnotationTargetPath , annotationDescriptor , /* visible = */
true ) , currentAnnotationOffset , /* named = */
true , charBuffer ) ; } currentVisibleTypeAnnotationBytecodeOffset = getTypeAnnotationBytecodeOffset ( visibleTypeAnnotationOffsets , ++ currentVisibleTypeAnnotationIndex ) ; } // Visit the runtime invisible instruction annotations , if any .
while ( invisibleTypeAnnotationOffsets != null && currentInvisibleTypeAnnotationIndex < invisibleTypeAnnotationOffsets . length && currentInvisibleTypeAnnotationBytecodeOffset <= currentBytecodeOffset ) { if ( currentInvisibleTypeAnnotationBytecodeOffset == currentBytecodeOffset ) { // Parse the target _ type , target _ info and target _ path fields .
int currentAnnotationOffset = readTypeAnnotationTarget ( context , invisibleTypeAnnotationOffsets [ currentInvisibleTypeAnnotationIndex ] ) ; // Parse the type _ index field .
String annotationDescriptor = readUTF8 ( currentAnnotationOffset , charBuffer ) ; currentAnnotationOffset += 2 ; // Parse num _ element _ value _ pairs and element _ value _ pairs and visit these values .
readElementValues ( methodVisitor . visitInsnAnnotation ( context . currentTypeAnnotationTarget , context . currentTypeAnnotationTargetPath , annotationDescriptor , /* visible = */
false ) , currentAnnotationOffset , /* named = */
true , charBuffer ) ; } currentInvisibleTypeAnnotationBytecodeOffset = getTypeAnnotationBytecodeOffset ( invisibleTypeAnnotationOffsets , ++ currentInvisibleTypeAnnotationIndex ) ; } } if ( labels [ codeLength ] != null ) { methodVisitor . visitLabel ( labels [ codeLength ] ) ; } // Visit LocalVariableTable and LocalVariableTypeTable attributes .
if ( localVariableTableOffset != 0 && ( context . parsingOptions & SKIP_DEBUG ) == 0 ) { // The ( start _ pc , index , signature _ index ) fields of each entry of the LocalVariableTypeTable .
int [ ] typeTable = null ; if ( localVariableTypeTableOffset != 0 ) { typeTable = new int [ readUnsignedShort ( localVariableTypeTableOffset ) * 3 ] ; currentOffset = localVariableTypeTableOffset + 2 ; int typeTableIndex = typeTable . length ; while ( typeTableIndex > 0 ) { // Store the offset of ' signature _ index ' , and the value of ' index ' and ' start _ pc ' .
typeTable [ -- typeTableIndex ] = currentOffset + 6 ; typeTable [ -- typeTableIndex ] = readUnsignedShort ( currentOffset + 8 ) ; typeTable [ -- typeTableIndex ] = readUnsignedShort ( currentOffset ) ; currentOffset += 10 ; } } int localVariableTableLength = readUnsignedShort ( localVariableTableOffset ) ; currentOffset = localVariableTableOffset + 2 ; while ( localVariableTableLength -- > 0 ) { int startPc = readUnsignedShort ( currentOffset ) ; int length = readUnsignedShort ( currentOffset + 2 ) ; String name = readUTF8 ( currentOffset + 4 , charBuffer ) ; String descriptor = readUTF8 ( currentOffset + 6 , charBuffer ) ; int index = readUnsignedShort ( currentOffset + 8 ) ; currentOffset += 10 ; String signature = null ; if ( typeTable != null ) { for ( int i = 0 ; i < typeTable . length ; i += 3 ) { if ( typeTable [ i ] == startPc && typeTable [ i + 1 ] == index ) { signature = readUTF8 ( typeTable [ i + 2 ] , charBuffer ) ; break ; } } } methodVisitor . visitLocalVariable ( name , descriptor , signature , labels [ startPc ] , labels [ startPc + length ] , index ) ; } } // Visit the local variable type annotations of the RuntimeVisibleTypeAnnotations attribute .
if ( visibleTypeAnnotationOffsets != null ) { for ( int typeAnnotationOffset : visibleTypeAnnotationOffsets ) { int targetType = readByte ( typeAnnotationOffset ) ; if ( targetType == TypeReference . LOCAL_VARIABLE || targetType == TypeReference . RESOURCE_VARIABLE ) { // Parse the target _ type , target _ info and target _ path fields .
currentOffset = readTypeAnnotationTarget ( context , typeAnnotationOffset ) ; // Parse the type _ index field .
String annotationDescriptor = readUTF8 ( currentOffset , charBuffer ) ; currentOffset += 2 ; // Parse num _ element _ value _ pairs and element _ value _ pairs and visit these values .
readElementValues ( methodVisitor . visitLocalVariableAnnotation ( context . currentTypeAnnotationTarget , context . currentTypeAnnotationTargetPath , context . currentLocalVariableAnnotationRangeStarts , context . currentLocalVariableAnnotationRangeEnds , context . currentLocalVariableAnnotationRangeIndices , annotationDescriptor , /* visible = */
true ) , currentOffset , /* named = */
true , charBuffer ) ; } } } // Visit the local variable type annotations of the RuntimeInvisibleTypeAnnotations attribute .
if ( invisibleTypeAnnotationOffsets != null ) { for ( int typeAnnotationOffset : invisibleTypeAnnotationOffsets ) { int targetType = readByte ( typeAnnotationOffset ) ; if ( targetType == TypeReference . LOCAL_VARIABLE || targetType == TypeReference . RESOURCE_VARIABLE ) { // Parse the target _ type , target _ info and target _ path fields .
currentOffset = readTypeAnnotationTarget ( context , typeAnnotationOffset ) ; // Parse the type _ index field .
String annotationDescriptor = readUTF8 ( currentOffset , charBuffer ) ; currentOffset += 2 ; // Parse num _ element _ value _ pairs and element _ value _ pairs and visit these values .
readElementValues ( methodVisitor . visitLocalVariableAnnotation ( context . currentTypeAnnotationTarget , context . currentTypeAnnotationTargetPath , context . currentLocalVariableAnnotationRangeStarts , context . currentLocalVariableAnnotationRangeEnds , context . currentLocalVariableAnnotationRangeIndices , annotationDescriptor , /* visible = */
false ) , currentOffset , /* named = */
true , charBuffer ) ; } } } // Visit the non standard attributes .
while ( attributes != null ) { // Copy and reset the nextAttribute field so that it can also be used in MethodWriter .
Attribute nextAttribute = attributes . nextAttribute ; attributes . nextAttribute = null ; methodVisitor . visitAttribute ( attributes ) ; attributes = nextAttribute ; } // Visit the max stack and max locals values .
methodVisitor . visitMaxs ( maxStack , maxLocals ) ;


signature:
public class ClassReader { /** * Returns the label corresponding to the given bytecode offset . The default implementation of
 * this method creates a label for the given offset if it has not been already created .
 * @ param bytecodeOffset a bytecode offset in a method .
 * @ param labels the already created labels , indexed by their offset . If a label already exists
 * for bytecodeOffset this method must not create a new one . Otherwise it must store the new
 * label in this array .
 * @ return a non null Label , which must be equal to labels [ bytecodeOffset ] . */
protected Label readLabel ( final int bytecodeOffset , final Label [ ] labels ) { } }

implementation: if ( labels [ bytecodeOffset ] == null ) { labels [ bytecodeOffset ] = new Label ( ) ; } return labels [ bytecodeOffset ] ;


signature:
public class ClassReader { /** * Creates a label without the { @ link Label # FLAG _ DEBUG _ ONLY } flag set , for the given bytecode
 * offset . The label is created with a call to { @ link # readLabel } and its { @ link
 * Label # FLAG _ DEBUG _ ONLY } flag is cleared .
 * @ param bytecodeOffset a bytecode offset in a method .
 * @ param labels the already created labels , indexed by their offset .
 * @ return a Label without the { @ link Label # FLAG _ DEBUG _ ONLY } flag set . */
private Label createLabel ( final int bytecodeOffset , final Label [ ] labels ) { } }

implementation: Label label = readLabel ( bytecodeOffset , labels ) ; label . flags &= ~ Label . FLAG_DEBUG_ONLY ; return label ;


signature:
public class ClassReader { /** * Creates a label with the { @ link Label # FLAG _ DEBUG _ ONLY } flag set , if there is no already
 * existing label for the given bytecode offset ( otherwise does nothing ) . The label is created
 * with a call to { @ link # readLabel } .
 * @ param bytecodeOffset a bytecode offset in a method .
 * @ param labels the already created labels , indexed by their offset . */
private void createDebugLabel ( final int bytecodeOffset , final Label [ ] labels ) { } }

implementation: if ( labels [ bytecodeOffset ] == null ) { readLabel ( bytecodeOffset , labels ) . flags |= Label . FLAG_DEBUG_ONLY ; }


signature:
public class ClassReader { /** * Parses a Runtime [ In ] VisibleTypeAnnotations attribute to find the offset of each type _ annotation
 * entry it contains , to find the corresponding labels , and to visit the try catch block
 * annotations .
 * @ param methodVisitor the method visitor to be used to visit the try catch block annotations .
 * @ param context information about the class being parsed .
 * @ param runtimeTypeAnnotationsOffset the start offset of a Runtime [ In ] VisibleTypeAnnotations
 * attribute , excluding the attribute _ info ' s attribute _ name _ index and attribute _ length fields .
 * @ param visible true if the attribute to parse is a RuntimeVisibleTypeAnnotations attribute ,
 * false it is a RuntimeInvisibleTypeAnnotations attribute .
 * @ return the start offset of each entry of the Runtime [ In ] VisibleTypeAnnotations _ attribute ' s
 * ' annotations ' array field . */
private int [ ] readTypeAnnotations ( final MethodVisitor methodVisitor , final Context context , final int runtimeTypeAnnotationsOffset , final boolean visible ) { } }

implementation:
char [ ] charBuffer = context . charBuffer ; int currentOffset = runtimeTypeAnnotationsOffset ; // Read the num _ annotations field and create an array to store the type _ annotation offsets .
int [ ] typeAnnotationsOffsets = new int [ readUnsignedShort ( currentOffset ) ] ; currentOffset += 2 ; // Parse the ' annotations ' array field .
for ( int i = 0 ; i < typeAnnotationsOffsets . length ; ++ i ) { typeAnnotationsOffsets [ i ] = currentOffset ; // Parse the type _ annotation ' s target _ type and the target _ info fields . The size of the
// target _ info field depends on the value of target _ type .
int targetType = readInt ( currentOffset ) ; switch ( targetType >>> 24 ) { case TypeReference . LOCAL_VARIABLE : case TypeReference . RESOURCE_VARIABLE : // A localvar _ target has a variable size , which depends on the value of their table _ length
// field . It also references bytecode offsets , for which we need labels .
int tableLength = readUnsignedShort ( currentOffset + 1 ) ; currentOffset += 3 ; while ( tableLength -- > 0 ) { int startPc = readUnsignedShort ( currentOffset ) ; int length = readUnsignedShort ( currentOffset + 2 ) ; // Skip the index field ( 2 bytes ) .
currentOffset += 6 ; createLabel ( startPc , context . currentMethodLabels ) ; createLabel ( startPc + length , context . currentMethodLabels ) ; } break ; case TypeReference . CAST : case TypeReference . CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT : case TypeReference . METHOD_INVOCATION_TYPE_ARGUMENT : case TypeReference . CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT : case TypeReference . METHOD_REFERENCE_TYPE_ARGUMENT : currentOffset += 4 ; break ; case TypeReference . CLASS_EXTENDS : case TypeReference . CLASS_TYPE_PARAMETER_BOUND : case TypeReference . METHOD_TYPE_PARAMETER_BOUND : case TypeReference . THROWS : case TypeReference . EXCEPTION_PARAMETER : case TypeReference . INSTANCEOF : case TypeReference . NEW : case TypeReference . CONSTRUCTOR_REFERENCE : case TypeReference . METHOD_REFERENCE : currentOffset += 3 ; break ; case TypeReference . CLASS_TYPE_PARAMETER : case TypeReference . METHOD_TYPE_PARAMETER : case TypeReference . METHOD_FORMAL_PARAMETER : case TypeReference . FIELD : case TypeReference . METHOD_RETURN : case TypeReference . METHOD_RECEIVER : default : // TypeReference type which can ' t be used in Code attribute , or which is unknown .
throw new IllegalArgumentException ( ) ; } // Parse the rest of the type _ annotation structure , starting with the target _ path structure
// ( whose size depends on its path _ length field ) .
int pathLength = readByte ( currentOffset ) ; if ( ( targetType >>> 24 ) == TypeReference . EXCEPTION_PARAMETER ) { // Parse the target _ path structure and create a corresponding TypePath .
TypePath path = pathLength == 0 ? null : new TypePath ( b , currentOffset ) ; currentOffset += 1 + 2 * pathLength ; // Parse the type _ index field .
String annotationDescriptor = readUTF8 ( currentOffset , charBuffer ) ; currentOffset += 2 ; // Parse num _ element _ value _ pairs and element _ value _ pairs and visit these values .
currentOffset = readElementValues ( methodVisitor . visitTryCatchAnnotation ( targetType & 0xFFFFFF00 , path , annotationDescriptor , visible ) , currentOffset , /* named = */
true , charBuffer ) ; } else { // We don ' t want to visit the other target _ type annotations , so we just skip them ( which
// requires some parsing because the element _ value _ pairs array has a variable size ) . First ,
// skip the target _ path structure :
currentOffset += 3 + 2 * pathLength ; // Then skip the num _ element _ value _ pairs and element _ value _ pairs fields ( by reading them
// with a null AnnotationVisitor ) .
currentOffset = readElementValues ( /* annotationVisitor = */
null , currentOffset , /* named = */
true , charBuffer ) ; } } return typeAnnotationsOffsets ;


signature:
public class ClassReader { /** * Returns the bytecode offset corresponding to the specified JVMS ' type _ annotation ' structure , or
 * - 1 if there is no such type _ annotation of if it does not have a bytecode offset .
 * @ param typeAnnotationOffsets the offset of each ' type _ annotation ' entry in a
 * Runtime [ In ] VisibleTypeAnnotations attribute , or null .
 * @ param typeAnnotationIndex the index a ' type _ annotation ' entry in typeAnnotationOffsets .
 * @ return bytecode offset corresponding to the specified JVMS ' type _ annotation ' structure , or - 1
 * if there is no such type _ annotation of if it does not have a bytecode offset . */
private int getTypeAnnotationBytecodeOffset ( final int [ ] typeAnnotationOffsets , final int typeAnnotationIndex ) { } }

implementation: if ( typeAnnotationOffsets == null || typeAnnotationIndex >= typeAnnotationOffsets . length || readByte ( typeAnnotationOffsets [ typeAnnotationIndex ] ) < TypeReference . INSTANCEOF ) { return - 1 ; } return readUnsignedShort ( typeAnnotationOffsets [ typeAnnotationIndex ] + 1 ) ;


signature:
public class ClassReader { /** * Parses the header of a JVMS type _ annotation structure to extract its target _ type , target _ info
 * and target _ path ( the result is stored in the given context ) , and returns the start offset of
 * the rest of the type _ annotation structure .
 * @ param context information about the class being parsed . This is where the extracted
 * target _ type and target _ path must be stored .
 * @ param typeAnnotationOffset the start offset of a type _ annotation structure .
 * @ return the start offset of the rest of the type _ annotation structure . */
private int readTypeAnnotationTarget ( final Context context , final int typeAnnotationOffset ) { } }

implementation:
int currentOffset = typeAnnotationOffset ; // Parse and store the target _ type structure .
int targetType = readInt ( typeAnnotationOffset ) ; switch ( targetType >>> 24 ) { case TypeReference . CLASS_TYPE_PARAMETER : case TypeReference . METHOD_TYPE_PARAMETER : case TypeReference . METHOD_FORMAL_PARAMETER : targetType &= 0xFFFF0000 ; currentOffset += 2 ; break ; case TypeReference . FIELD : case TypeReference . METHOD_RETURN : case TypeReference . METHOD_RECEIVER : targetType &= 0xFF000000 ; currentOffset += 1 ; break ; case TypeReference . LOCAL_VARIABLE : case TypeReference . RESOURCE_VARIABLE : targetType &= 0xFF000000 ; int tableLength = readUnsignedShort ( currentOffset + 1 ) ; currentOffset += 3 ; context . currentLocalVariableAnnotationRangeStarts = new Label [ tableLength ] ; context . currentLocalVariableAnnotationRangeEnds = new Label [ tableLength ] ; context . currentLocalVariableAnnotationRangeIndices = new int [ tableLength ] ; for ( int i = 0 ; i < tableLength ; ++ i ) { int startPc = readUnsignedShort ( currentOffset ) ; int length = readUnsignedShort ( currentOffset + 2 ) ; int index = readUnsignedShort ( currentOffset + 4 ) ; currentOffset += 6 ; context . currentLocalVariableAnnotationRangeStarts [ i ] = createLabel ( startPc , context . currentMethodLabels ) ; context . currentLocalVariableAnnotationRangeEnds [ i ] = createLabel ( startPc + length , context . currentMethodLabels ) ; context . currentLocalVariableAnnotationRangeIndices [ i ] = index ; } break ; case TypeReference . CAST : case TypeReference . CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT : case TypeReference . METHOD_INVOCATION_TYPE_ARGUMENT : case TypeReference . CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT : case TypeReference . METHOD_REFERENCE_TYPE_ARGUMENT : targetType &= 0xFF0000FF ; currentOffset += 4 ; break ; case TypeReference . CLASS_EXTENDS : case TypeReference . CLASS_TYPE_PARAMETER_BOUND : case TypeReference . METHOD_TYPE_PARAMETER_BOUND : case TypeReference . THROWS : case TypeReference . EXCEPTION_PARAMETER : targetType &= 0xFFFFFF00 ; currentOffset += 3 ; break ; case TypeReference . INSTANCEOF : case TypeReference . NEW : case TypeReference . CONSTRUCTOR_REFERENCE : case TypeReference . METHOD_REFERENCE : targetType &= 0xFF000000 ; currentOffset += 3 ; break ; default : throw new IllegalArgumentException ( ) ; } context . currentTypeAnnotationTarget = targetType ; // Parse and store the target _ path structure .
int pathLength = readByte ( currentOffset ) ; context . currentTypeAnnotationTargetPath = pathLength == 0 ? null : new TypePath ( b , currentOffset ) ; // Return the start offset of the rest of the type _ annotation structure .
return currentOffset + 1 + 2 * pathLength ;


signature:
public class ClassReader { /** * Reads a Runtime [ In ] VisibleParameterAnnotations attribute and makes the given visitor visit it .
 * @ param methodVisitor the visitor that must visit the parameter annotations .
 * @ param context information about the class being parsed .
 * @ param runtimeParameterAnnotationsOffset the start offset of a
 * Runtime [ In ] VisibleParameterAnnotations attribute , excluding the attribute _ info ' s
 * attribute _ name _ index and attribute _ length fields .
 * @ param visible true if the attribute to parse is a RuntimeVisibleParameterAnnotations
 * attribute , false it is a RuntimeInvisibleParameterAnnotations attribute . */
private void readParameterAnnotations ( final MethodVisitor methodVisitor , final Context context , final int runtimeParameterAnnotationsOffset , final boolean visible ) { } }

implementation:
int currentOffset = runtimeParameterAnnotationsOffset ; int numParameters = b [ currentOffset ++ ] & 0xFF ; methodVisitor . visitAnnotableParameterCount ( numParameters , visible ) ; char [ ] charBuffer = context . charBuffer ; for ( int i = 0 ; i < numParameters ; ++ i ) { int numAnnotations = readUnsignedShort ( currentOffset ) ; currentOffset += 2 ; while ( numAnnotations -- > 0 ) { // Parse the type _ index field .
String annotationDescriptor = readUTF8 ( currentOffset , charBuffer ) ; currentOffset += 2 ; // Parse num _ element _ value _ pairs and element _ value _ pairs and visit these values .
currentOffset = readElementValues ( methodVisitor . visitParameterAnnotation ( i , annotationDescriptor , visible ) , currentOffset , /* named = */
true , charBuffer ) ; } }


signature:
public class ClassReader { /** * Reads the element values of a JVMS ' annotation ' structure and makes the given visitor visit
 * them . This method can also be used to read the values of the JVMS ' array _ value ' field of an
 * annotation ' s ' element _ value ' .
 * @ param annotationVisitor the visitor that must visit the values .
 * @ param annotationOffset the start offset of an ' annotation ' structure ( excluding its type _ index
 * field ) or of an ' array _ value ' structure .
 * @ param named if the annotation values are named or not . This should be true to parse the values
 * of a JVMS ' annotation ' structure , and false to parse the JVMS ' array _ value ' of an
 * annotation ' s element _ value .
 * @ param charBuffer the buffer used to read strings in the constant pool .
 * @ return the end offset of the JVMS ' annotation ' or ' array _ value ' structure . */
private int readElementValues ( final AnnotationVisitor annotationVisitor , final int annotationOffset , final boolean named , final char [ ] charBuffer ) { } }

implementation:
int currentOffset = annotationOffset ; // Read the num _ element _ value _ pairs field ( or num _ values field for an array _ value ) .
int numElementValuePairs = readUnsignedShort ( currentOffset ) ; currentOffset += 2 ; if ( named ) { // Parse the element _ value _ pairs array .
while ( numElementValuePairs -- > 0 ) { String elementName = readUTF8 ( currentOffset , charBuffer ) ; currentOffset = readElementValue ( annotationVisitor , currentOffset + 2 , elementName , charBuffer ) ; } } else { // Parse the array _ value array .
while ( numElementValuePairs -- > 0 ) { currentOffset = readElementValue ( annotationVisitor , currentOffset , /* named = */
null , charBuffer ) ; } } if ( annotationVisitor != null ) { annotationVisitor . visitEnd ( ) ; } return currentOffset ;