private int readMethod(final ClassVisitor classVisitor,
            final Context context, int u) {
        // reads the method declaration
        char[] c = context.buffer;
        context.access = readUnsignedShort(u);
        context.name = readUTF8(u + 2, c);
        context.desc = readUTF8(u + 4, c);
        u += 6;

        // reads the method attributes
        int code = 0;
        int exception = 0;
        String[] exceptions = null;
        String signature = null;
        int methodParameters = 0;
        int anns = 0;
        int ianns = 0;
        int tanns = 0;
        int itanns = 0;
        int dann = 0;
        int mpanns = 0;
        int impanns = 0;
        int firstAttribute = u;
        Attribute attributes = null;

        for (int i = readUnsignedShort(u); i > 0; --i) {
            String attrName = readUTF8(u + 2, c);
            // tests are sorted in decreasing frequency order
            // (based on frequencies observed on typical classes)
            if ("Code".equals(attrName)) {
                if ((context.flags & SKIP_CODE) == 0) {
                    code = u + 8;
                }
            } else if ("Exceptions".equals(attrName)) {
                exceptions = new String[readUnsignedShort(u + 8)];
                exception = u + 10;
                for (int j = 0; j < exceptions.length; ++j) {
                    exceptions[j] = readClass(exception, c);
                    exception += 2;
                }
            } else if (SIGNATURES && "Signature".equals(attrName)) {
                signature = readUTF8(u + 8, c);
            } else if ("Deprecated".equals(attrName)) {
                context.access |= Opcodes.ACC_DEPRECATED;
            } else if (ANNOTATIONS
                    && "RuntimeVisibleAnnotations".equals(attrName)) {
                anns = u + 8;
            } else if (ANNOTATIONS
                    && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
                tanns = u + 8;
            } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
                dann = u + 8;
            } else if ("Synthetic".equals(attrName)) {
                context.access |= Opcodes.ACC_SYNTHETIC
                        | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
            } else if (ANNOTATIONS
                    && "RuntimeInvisibleAnnotations".equals(attrName)) {
                ianns = u + 8;
            } else if (ANNOTATIONS
                    && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
                itanns = u + 8;
            } else if (ANNOTATIONS
                    && "RuntimeVisibleParameterAnnotations".equals(attrName)) {
                mpanns = u + 8;
            } else if (ANNOTATIONS
                    && "RuntimeInvisibleParameterAnnotations".equals(attrName)) {
                impanns = u + 8;
            } else if ("MethodParameters".equals(attrName)) {
                methodParameters = u + 8;
            } else {
                Attribute attr = readAttribute(context.attrs, attrName, u + 8,
                        readInt(u + 4), c, -1, null);
                if (attr != null) {
                    attr.next = attributes;
                    attributes = attr;
                }
            }
            u += 6 + readInt(u + 4);
        }
        u += 2;

        // visits the method declaration
        MethodVisitor mv = classVisitor.visitMethod(context.access,
                context.name, context.desc, signature, exceptions);
        if (mv == null) {
            return u;
        }

        /*
         * if the returned MethodVisitor is in fact a MethodWriter, it means
         * there is no method adapter between the reader and the writer. If, in
         * addition, the writer's constant pool was copied from this reader
         * (mw.cw.cr == this), and the signature and exceptions of the method
         * have not been changed, then it is possible to skip all visit events
         * and just copy the original code of the method to the writer (the
         * access, name and descriptor can have been changed, this is not
         * important since they are not copied as is from the reader).
         */
        if (WRITER && mv instanceof MethodWriter) {
            MethodWriter mw = (MethodWriter) mv;
            if (mw.cw.cr == this && signature == mw.signature) {
                boolean sameExceptions = false;
                if (exceptions == null) {
                    sameExceptions = mw.exceptionCount == 0;
                } else if (exceptions.length == mw.exceptionCount) {
                    sameExceptions = true;
                    for (int j = exceptions.length - 1; j >= 0; --j) {
                        exception -= 2;
                        if (mw.exceptions[j] != readUnsignedShort(exception)) {
                            sameExceptions = false;
                            break;
                        }
                    }
                }
                if (sameExceptions) {
                    /*
                     * we do not copy directly the code into MethodWriter to
                     * save a byte array copy operation. The real copy will be
                     * done in ClassWriter.toByteArray().
                     */
                    mw.classReaderOffset = firstAttribute;
                    mw.classReaderLength = u - firstAttribute;
                    return u;
                }
            }
        }

        // visit the method parameters
        if (methodParameters != 0) {
            for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) {
                mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2));
            }
        }

        // visits the method annotations
        if (ANNOTATIONS && dann != 0) {
            AnnotationVisitor dv = mv.visitAnnotationDefault();
            readAnnotationValue(dann, c, null, dv);
            if (dv != null) {
                dv.visitEnd();
            }
        }
        if (ANNOTATIONS && anns != 0) {
            for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
                v = readAnnotationValues(v + 2, c, true,
                        mv.visitAnnotation(readUTF8(v, c), true));
            }
        }
        if (ANNOTATIONS && ianns != 0) {
            for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
                v = readAnnotationValues(v + 2, c, true,
                        mv.visitAnnotation(readUTF8(v, c), false));
            }
        }
        if (ANNOTATIONS && tanns != 0) {
            for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
                v = readAnnotationTarget(context, v);
                v = readAnnotationValues(v + 2, c, true,
                        mv.visitTypeAnnotation(context.typeRef,
                                context.typePath, readUTF8(v, c), true));
            }
        }
        if (ANNOTATIONS && itanns != 0) {
            for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
                v = readAnnotationTarget(context, v);
                v = readAnnotationValues(v + 2, c, true,
                        mv.visitTypeAnnotation(context.typeRef,
                                context.typePath, readUTF8(v, c), false));
            }
        }
        if (ANNOTATIONS && mpanns != 0) {
            readParameterAnnotations(mv, context, mpanns, true);
        }
        if (ANNOTATIONS && impanns != 0) {
            readParameterAnnotations(mv, context, impanns, false);
        }

        // visits the method attributes
        while (attributes != null) {
            Attribute attr = attributes.next;
            attributes.next = null;
            mv.visitAttribute(attributes);
            attributes = attr;
        }

        // visits the method code
        if (code != 0) {
            mv.visitCode();
            readCode(mv, context, code);
        }

        // visits the end of the method
        mv.visitEnd();

        return u;
    }
private int readMethod(final ClassVisitor classVisitor,
            final Context context, int u) {
        
        char[] c = context.buffer;
        context.access = readUnsignedShort(u);
        context.name = readUTF8(u + 2, c);
        context.desc = readUTF8(u + 4, c);
        u += 6;

        
        int code = 0;
        int exception = 0;
        String[] exceptions = null;
        String signature = null;
        int methodParameters = 0;
        int anns = 0;
        int ianns = 0;
        int tanns = 0;
        int itanns = 0;
        int dann = 0;
        int mpanns = 0;
        int impanns = 0;
        int firstAttribute = u;
        Attribute attributes = null;

        for (int i = readUnsignedShort(u); i > 0; --i) {
            String attrName = readUTF8(u + 2, c);
            
            
            if ("Code".equals(attrName)) {
                if ((context.flags & SKIP_CODE) == 0) {
                    code = u + 8;
                }
            } else if ("Exceptions".equals(attrName)) {
                exceptions = new String[readUnsignedShort(u + 8)];
                exception = u + 10;
                for (int j = 0; j < exceptions.length; ++j) {
                    exceptions[j] = readClass(exception, c);
                    exception += 2;
                }
            } else if (SIGNATURES && "Signature".equals(attrName)) {
                signature = readUTF8(u + 8, c);
            } else if ("Deprecated".equals(attrName)) {
                context.access |= Opcodes.ACC_DEPRECATED;
            } else if (ANNOTATIONS
                    && "RuntimeVisibleAnnotations".equals(attrName)) {
                anns = u + 8;
            } else if (ANNOTATIONS
                    && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
                tanns = u + 8;
            } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
                dann = u + 8;
            } else if ("Synthetic".equals(attrName)) {
                context.access |= Opcodes.ACC_SYNTHETIC
                        | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
            } else if (ANNOTATIONS
                    && "RuntimeInvisibleAnnotations".equals(attrName)) {
                ianns = u + 8;
            } else if (ANNOTATIONS
                    && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
                itanns = u + 8;
            } else if (ANNOTATIONS
                    && "RuntimeVisibleParameterAnnotations".equals(attrName)) {
                mpanns = u + 8;
            } else if (ANNOTATIONS
                    && "RuntimeInvisibleParameterAnnotations".equals(attrName)) {
                impanns = u + 8;
            } else if ("MethodParameters".equals(attrName)) {
                methodParameters = u + 8;
            } else {
                Attribute attr = readAttribute(context.attrs, attrName, u + 8,
                        readInt(u + 4), c, -1, null);
                if (attr != null) {
                    attr.next = attributes;
                    attributes = attr;
                }
            }
            u += 6 + readInt(u + 4);
        }
        u += 2;

        
        MethodVisitor mv = classVisitor.visitMethod(context.access,
                context.name, context.desc, signature, exceptions);
        if (mv == null) {
            return u;
        }

        
        if (WRITER && mv instanceof MethodWriter) {
            MethodWriter mw = (MethodWriter) mv;
            if (mw.cw.cr == this && signature == mw.signature) {
                boolean sameExceptions = false;
                if (exceptions == null) {
                    sameExceptions = mw.exceptionCount == 0;
                } else if (exceptions.length == mw.exceptionCount) {
                    sameExceptions = true;
                    for (int j = exceptions.length - 1; j >= 0; --j) {
                        exception -= 2;
                        if (mw.exceptions[j] != readUnsignedShort(exception)) {
                            sameExceptions = false;
                            break;
                        }
                    }
                }
                if (sameExceptions) {
                    
                    mw.classReaderOffset = firstAttribute;
                    mw.classReaderLength = u - firstAttribute;
                    return u;
                }
            }
        }

        
        if (methodParameters != 0) {
            for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) {
                mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2));
            }
        }

        
        if (ANNOTATIONS && dann != 0) {
            AnnotationVisitor dv = mv.visitAnnotationDefault();
            readAnnotationValue(dann, c, null, dv);
            if (dv != null) {
                dv.visitEnd();
            }
        }
        if (ANNOTATIONS && anns != 0) {
            for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
                v = readAnnotationValues(v + 2, c, true,
                        mv.visitAnnotation(readUTF8(v, c), true));
            }
        }
        if (ANNOTATIONS && ianns != 0) {
            for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
                v = readAnnotationValues(v + 2, c, true,
                        mv.visitAnnotation(readUTF8(v, c), false));
            }
        }
        if (ANNOTATIONS && tanns != 0) {
            for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
                v = readAnnotationTarget(context, v);
                v = readAnnotationValues(v + 2, c, true,
                        mv.visitTypeAnnotation(context.typeRef,
                                context.typePath, readUTF8(v, c), true));
            }
        }
        if (ANNOTATIONS && itanns != 0) {
            for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
                v = readAnnotationTarget(context, v);
                v = readAnnotationValues(v + 2, c, true,
                        mv.visitTypeAnnotation(context.typeRef,
                                context.typePath, readUTF8(v, c), false));
            }
        }
        if (ANNOTATIONS && mpanns != 0) {
            readParameterAnnotations(mv, context, mpanns, true);
        }
        if (ANNOTATIONS && impanns != 0) {
            readParameterAnnotations(mv, context, impanns, false);
        }

        
        while (attributes != null) {
            Attribute attr = attributes.next;
            attributes.next = null;
            mv.visitAttribute(attributes);
            attributes = attr;
        }

        
        if (code != 0) {
            mv.visitCode();
            readCode(mv, context, code);
        }

        
        mv.visitEnd();

        return u;
    }
private int readMethod ( final ClassVisitor classVisitor , final Context context , int u ) { // reads the method declaration char [ ] c = context . buffer ; context . access = readUnsignedShort ( u ) ; context . name = readUTF8 ( u + 2 , c ) ; context . desc = readUTF8 ( u + 4 , c ) ; u += 6 ; // reads the method attributes int code = 0 ; int exception = 0 ; String [ ] exceptions = null ; String signature = null ; int methodParameters = 0 ; int anns = 0 ; int ianns = 0 ; int tanns = 0 ; int itanns = 0 ; int dann = 0 ; int mpanns = 0 ; int impanns = 0 ; int firstAttribute = u ; Attribute attributes = null ; for ( int i = readUnsignedShort ( u ) ; i > 0 ; -- i ) { String attrName = readUTF8 ( u + 2 , c ) ; // tests are sorted in decreasing frequency order // (based on frequencies observed on typical classes) if ( "Code" . equals ( attrName ) ) { if ( ( context . flags & SKIP_CODE ) == 0 ) { code = u + 8 ; } } else if ( "Exceptions" . equals ( attrName ) ) { exceptions = new String [ readUnsignedShort ( u + 8 ) ] ; exception = u + 10 ; for ( int j = 0 ; j < exceptions . length ; ++ j ) { exceptions [ j ] = readClass ( exception , c ) ; exception += 2 ; } } else if ( SIGNATURES && "Signature" . equals ( attrName ) ) { signature = readUTF8 ( u + 8 , c ) ; } else if ( "Deprecated" . equals ( attrName ) ) { context . access |= Opcodes . ACC_DEPRECATED ; } else if ( ANNOTATIONS && "RuntimeVisibleAnnotations" . equals ( attrName ) ) { anns = u + 8 ; } else if ( ANNOTATIONS && "RuntimeVisibleTypeAnnotations" . equals ( attrName ) ) { tanns = u + 8 ; } else if ( ANNOTATIONS && "AnnotationDefault" . equals ( attrName ) ) { dann = u + 8 ; } else if ( "Synthetic" . equals ( attrName ) ) { context . access |= Opcodes . ACC_SYNTHETIC | ClassWriter . ACC_SYNTHETIC_ATTRIBUTE ; } else if ( ANNOTATIONS && "RuntimeInvisibleAnnotations" . equals ( attrName ) ) { ianns = u + 8 ; } else if ( ANNOTATIONS && "RuntimeInvisibleTypeAnnotations" . equals ( attrName ) ) { itanns = u + 8 ; } else if ( ANNOTATIONS && "RuntimeVisibleParameterAnnotations" . equals ( attrName ) ) { mpanns = u + 8 ; } else if ( ANNOTATIONS && "RuntimeInvisibleParameterAnnotations" . equals ( attrName ) ) { impanns = u + 8 ; } else if ( "MethodParameters" . equals ( attrName ) ) { methodParameters = u + 8 ; } else { Attribute attr = readAttribute ( context . attrs , attrName , u + 8 , readInt ( u + 4 ) , c , - 1 , null ) ; if ( attr != null ) { attr . next = attributes ; attributes = attr ; } } u += 6 + readInt ( u + 4 ) ; } u += 2 ; // visits the method declaration MethodVisitor mv = classVisitor . visitMethod ( context . access , context . name , context . desc , signature , exceptions ) ; if ( mv == null ) { return u ; } /*
         * if the returned MethodVisitor is in fact a MethodWriter, it means
         * there is no method adapter between the reader and the writer. If, in
         * addition, the writer's constant pool was copied from this reader
         * (mw.cw.cr == this), and the signature and exceptions of the method
         * have not been changed, then it is possible to skip all visit events
         * and just copy the original code of the method to the writer (the
         * access, name and descriptor can have been changed, this is not
         * important since they are not copied as is from the reader).
         */ if ( WRITER && mv instanceof MethodWriter ) { MethodWriter mw = ( MethodWriter ) mv ; if ( mw . cw . cr == this && signature == mw . signature ) { boolean sameExceptions = false ; if ( exceptions == null ) { sameExceptions = mw . exceptionCount == 0 ; } else if ( exceptions . length == mw . exceptionCount ) { sameExceptions = true ; for ( int j = exceptions . length - 1 ; j >= 0 ; -- j ) { exception -= 2 ; if ( mw . exceptions [ j ] != readUnsignedShort ( exception ) ) { sameExceptions = false ; break ; } } } if ( sameExceptions ) { /*
                     * we do not copy directly the code into MethodWriter to
                     * save a byte array copy operation. The real copy will be
                     * done in ClassWriter.toByteArray().
                     */ mw . classReaderOffset = firstAttribute ; mw . classReaderLength = u - firstAttribute ; return u ; } } } // visit the method parameters if ( methodParameters != 0 ) { for ( int i = b [ methodParameters ] & 0xFF , v = methodParameters + 1 ; i > 0 ; -- i , v = v + 4 ) { mv . visitParameter ( readUTF8 ( v , c ) , readUnsignedShort ( v + 2 ) ) ; } } // visits the method annotations if ( ANNOTATIONS && dann != 0 ) { AnnotationVisitor dv = mv . visitAnnotationDefault ( ) ; readAnnotationValue ( dann , c , null , dv ) ; if ( dv != null ) { dv . visitEnd ( ) ; } } if ( ANNOTATIONS && anns != 0 ) { for ( int i = readUnsignedShort ( anns ) , v = anns + 2 ; i > 0 ; -- i ) { v = readAnnotationValues ( v + 2 , c , true , mv . visitAnnotation ( readUTF8 ( v , c ) , true ) ) ; } } if ( ANNOTATIONS && ianns != 0 ) { for ( int i = readUnsignedShort ( ianns ) , v = ianns + 2 ; i > 0 ; -- i ) { v = readAnnotationValues ( v + 2 , c , true , mv . visitAnnotation ( readUTF8 ( v , c ) , false ) ) ; } } if ( ANNOTATIONS && tanns != 0 ) { for ( int i = readUnsignedShort ( tanns ) , v = tanns + 2 ; i > 0 ; -- i ) { v = readAnnotationTarget ( context , v ) ; v = readAnnotationValues ( v + 2 , c , true , mv . visitTypeAnnotation ( context . typeRef , context . typePath , readUTF8 ( v , c ) , true ) ) ; } } if ( ANNOTATIONS && itanns != 0 ) { for ( int i = readUnsignedShort ( itanns ) , v = itanns + 2 ; i > 0 ; -- i ) { v = readAnnotationTarget ( context , v ) ; v = readAnnotationValues ( v + 2 , c , true , mv . visitTypeAnnotation ( context . typeRef , context . typePath , readUTF8 ( v , c ) , false ) ) ; } } if ( ANNOTATIONS && mpanns != 0 ) { readParameterAnnotations ( mv , context , mpanns , true ) ; } if ( ANNOTATIONS && impanns != 0 ) { readParameterAnnotations ( mv , context , impanns , false ) ; } // visits the method attributes while ( attributes != null ) { Attribute attr = attributes . next ; attributes . next = null ; mv . visitAttribute ( attributes ) ; attributes = attr ; } // visits the method code if ( code != 0 ) { mv . visitCode ( ) ; readCode ( mv , context , code ) ; } // visits the end of the method mv . visitEnd ( ) ; return u ; }
Reads a method 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 u
the start offset of the method in the class file.
@return the offset of the first byte following the method in the class.
Reads a method and makes the given visitor visit it .