001/***
002 * ASM: a very small and fast Java bytecode manipulation framework
003 * Copyright (c) 2000-2011 INRIA, France Telecom
004 * All rights reserved.
005 *
006 * Redistribution and use in source and binary forms, with or without
007 * modification, are permitted provided that the following conditions
008 * are met:
009 * 1. Redistributions of source code must retain the above copyright
010 *    notice, this list of conditions and the following disclaimer.
011 * 2. Redistributions in binary form must reproduce the above copyright
012 *    notice, this list of conditions and the following disclaimer in the
013 *    documentation and/or other materials provided with the distribution.
014 * 3. Neither the name of the copyright holders nor the names of its
015 *    contributors may be used to endorse or promote products derived from
016 *    this software without specific prior written permission.
017 *
018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
022 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
028 * THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package org.springframework.asm;
031
032import java.io.IOException;
033import java.io.InputStream;
034
035/**
036 * A Java class parser to make a {@link ClassVisitor} visit an existing class.
037 * This class parses a byte array conforming to the Java class file format and
038 * calls the appropriate visit methods of a given class visitor for each field,
039 * method and bytecode instruction encountered.
040 * 
041 * @author Eric Bruneton
042 * @author Eugene Kuleshov
043 */
044public class ClassReader {
045
046    /**
047     * True to enable signatures support.
048     */
049    static final boolean SIGNATURES = true;
050
051    /**
052     * True to enable annotations support.
053     */
054    static final boolean ANNOTATIONS = true;
055
056    /**
057     * True to enable stack map frames support.
058     */
059    static final boolean FRAMES = true;
060
061    /**
062     * True to enable bytecode writing support.
063     */
064    static final boolean WRITER = true;
065
066    /**
067     * True to enable JSR_W and GOTO_W support.
068     */
069    static final boolean RESIZE = true;
070
071    /**
072     * Flag to skip method code. If this class is set <code>CODE</code>
073     * attribute won't be visited. This can be used, for example, to retrieve
074     * annotations for methods and method parameters.
075     */
076    public static final int SKIP_CODE = 1;
077
078    /**
079     * Flag to skip the debug information in the class. If this flag is set the
080     * debug information of the class is not visited, i.e. the
081     * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
082     * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be
083     * called.
084     */
085    public static final int SKIP_DEBUG = 2;
086
087    /**
088     * Flag to skip the stack map frames in the class. If this flag is set the
089     * stack map frames of the class is not visited, i.e. the
090     * {@link MethodVisitor#visitFrame visitFrame} method will not be called.
091     * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is
092     * used: it avoids visiting frames that will be ignored and recomputed from
093     * scratch in the class writer.
094     */
095    public static final int SKIP_FRAMES = 4;
096
097    /**
098     * Flag to expand the stack map frames. By default stack map frames are
099     * visited in their original format (i.e. "expanded" for classes whose
100     * version is less than V1_6, and "compressed" for the other classes). If
101     * this flag is set, stack map frames are always visited in expanded format
102     * (this option adds a decompression/recompression step in ClassReader and
103     * ClassWriter which degrades performances quite a lot).
104     */
105    public static final int EXPAND_FRAMES = 8;
106
107    /**
108     * Flag to expand the ASM pseudo instructions into an equivalent sequence of
109     * standard bytecode instructions. When resolving a forward jump it may
110     * happen that the signed 2 bytes offset reserved for it is not sufficient
111     * to store the bytecode offset. In this case the jump instruction is
112     * replaced with a temporary ASM pseudo instruction using an unsigned 2
113     * bytes offset (see Label#resolve). This internal flag is used to re-read
114     * classes containing such instructions, in order to replace them with
115     * standard instructions. In addition, when this flag is used, GOTO_W and
116     * JSR_W are <i>not</i> converted into GOTO and JSR, to make sure that
117     * infinite loops where a GOTO_W is replaced with a GOTO in ClassReader and
118     * converted back to a GOTO_W in ClassWriter cannot occur.
119     */
120    static final int EXPAND_ASM_INSNS = 256;
121
122    /**
123     * The class to be parsed. <i>The content of this array must not be
124     * modified. This field is intended for {@link Attribute} sub classes, and
125     * is normally not needed by class generators or adapters.</i>
126     */
127    public final byte[] b;
128
129    /**
130     * The start index of each constant pool item in {@link #b b}, plus one. The
131     * one byte offset skips the constant pool item tag that indicates its type.
132     */
133    private final int[] items;
134
135    /**
136     * The String objects corresponding to the CONSTANT_Utf8 items. This cache
137     * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
138     * which GREATLY improves performances (by a factor 2 to 3). This caching
139     * strategy could be extended to all constant pool items, but its benefit
140     * would not be so great for these items (because they are much less
141     * expensive to parse than CONSTANT_Utf8 items).
142     */
143    private final String[] strings;
144
145    /**
146     * Maximum length of the strings contained in the constant pool of the
147     * class.
148     */
149    private final int maxStringLength;
150
151    /**
152     * Start index of the class header information (access, name...) in
153     * {@link #b b}.
154     */
155    public final int header;
156
157    // ------------------------------------------------------------------------
158    // Constructors
159    // ------------------------------------------------------------------------
160
161    /**
162     * Constructs a new {@link ClassReader} object.
163     * 
164     * @param b
165     *            the bytecode of the class to be read.
166     */
167    public ClassReader(final byte[] b) {
168        this(b, 0, b.length);
169    }
170
171    /**
172     * Constructs a new {@link ClassReader} object.
173     * 
174     * @param b
175     *            the bytecode of the class to be read.
176     * @param off
177     *            the start offset of the class data.
178     * @param len
179     *            the length of the class data.
180     */
181    public ClassReader(final byte[] b, final int off, final int len) {
182        this.b = b;
183        // checks the class version
184                /* SPRING PATCH: REMOVED FOR FORWARD COMPATIBILITY WITH JDK 9
185        if (readShort(off + 6) > Opcodes.V1_8) {
186            throw new IllegalArgumentException();
187        }
188                */
189        // parses the constant pool
190        items = new int[readUnsignedShort(off + 8)];
191        int n = items.length;
192        strings = new String[n];
193        int max = 0;
194        int index = off + 10;
195        for (int i = 1; i < n; ++i) {
196            items[i] = index + 1;
197            int size;
198            switch (b[index]) {
199            case ClassWriter.FIELD:
200            case ClassWriter.METH:
201            case ClassWriter.IMETH:
202            case ClassWriter.INT:
203            case ClassWriter.FLOAT:
204            case ClassWriter.NAME_TYPE:
205            case ClassWriter.INDY:
206                size = 5;
207                break;
208            case ClassWriter.LONG:
209            case ClassWriter.DOUBLE:
210                size = 9;
211                ++i;
212                break;
213            case ClassWriter.UTF8:
214                size = 3 + readUnsignedShort(index + 1);
215                if (size > max) {
216                    max = size;
217                }
218                break;
219            case ClassWriter.HANDLE:
220                size = 4;
221                break;
222            // case ClassWriter.CLASS:
223            // case ClassWriter.STR:
224            // case ClassWriter.MTYPE
225            // case ClassWriter.PACKAGE:
226            // case ClassWriter.MODULE:
227            default:
228                size = 3;
229                break;
230            }
231            index += size;
232        }
233        maxStringLength = max;
234        // the class header information starts just after the constant pool
235        header = index;
236    }
237
238    /**
239     * Returns the class's access flags (see {@link Opcodes}). This value may
240     * not reflect Deprecated and Synthetic flags when bytecode is before 1.5
241     * and those flags are represented by attributes.
242     * 
243     * @return the class access flags
244     * 
245     * @see ClassVisitor#visit(int, int, String, String, String, String[])
246     */
247    public int getAccess() {
248        return readUnsignedShort(header);
249    }
250
251    /**
252     * Returns the internal name of the class (see
253     * {@link Type#getInternalName() getInternalName}).
254     * 
255     * @return the internal class name
256     * 
257     * @see ClassVisitor#visit(int, int, String, String, String, String[])
258     */
259    public String getClassName() {
260        return readClass(header + 2, new char[maxStringLength]);
261    }
262
263    /**
264     * Returns the internal of name of the super class (see
265     * {@link Type#getInternalName() getInternalName}). For interfaces, the
266     * super class is {@link Object}.
267     * 
268     * @return the internal name of super class, or <tt>null</tt> for
269     *         {@link Object} class.
270     * 
271     * @see ClassVisitor#visit(int, int, String, String, String, String[])
272     */
273    public String getSuperName() {
274        return readClass(header + 4, new char[maxStringLength]);
275    }
276
277    /**
278     * Returns the internal names of the class's interfaces (see
279     * {@link Type#getInternalName() getInternalName}).
280     * 
281     * @return the array of internal names for all implemented interfaces or
282     *         <tt>null</tt>.
283     * 
284     * @see ClassVisitor#visit(int, int, String, String, String, String[])
285     */
286    public String[] getInterfaces() {
287        int index = header + 6;
288        int n = readUnsignedShort(index);
289        String[] interfaces = new String[n];
290        if (n > 0) {
291            char[] buf = new char[maxStringLength];
292            for (int i = 0; i < n; ++i) {
293                index += 2;
294                interfaces[i] = readClass(index, buf);
295            }
296        }
297        return interfaces;
298    }
299
300    /**
301     * Copies the constant pool data into the given {@link ClassWriter}. Should
302     * be called before the {@link #accept(ClassVisitor,int)} method.
303     * 
304     * @param classWriter
305     *            the {@link ClassWriter} to copy constant pool into.
306     */
307    void copyPool(final ClassWriter classWriter) {
308        char[] buf = new char[maxStringLength];
309        int ll = items.length;
310        Item[] items2 = new Item[ll];
311        for (int i = 1; i < ll; i++) {
312            int index = items[i];
313            int tag = b[index - 1];
314            Item item = new Item(i);
315            int nameType;
316            switch (tag) {
317            case ClassWriter.FIELD:
318            case ClassWriter.METH:
319            case ClassWriter.IMETH:
320                nameType = items[readUnsignedShort(index + 2)];
321                item.set(tag, readClass(index, buf), readUTF8(nameType, buf),
322                        readUTF8(nameType + 2, buf));
323                break;
324            case ClassWriter.INT:
325                item.set(readInt(index));
326                break;
327            case ClassWriter.FLOAT:
328                item.set(Float.intBitsToFloat(readInt(index)));
329                break;
330            case ClassWriter.NAME_TYPE:
331                item.set(tag, readUTF8(index, buf), readUTF8(index + 2, buf),
332                        null);
333                break;
334            case ClassWriter.LONG:
335                item.set(readLong(index));
336                ++i;
337                break;
338            case ClassWriter.DOUBLE:
339                item.set(Double.longBitsToDouble(readLong(index)));
340                ++i;
341                break;
342            case ClassWriter.UTF8: {
343                String s = strings[i];
344                if (s == null) {
345                    index = items[i];
346                    s = strings[i] = readUTF(index + 2,
347                            readUnsignedShort(index), buf);
348                }
349                item.set(tag, s, null, null);
350                break;
351            }
352            case ClassWriter.HANDLE: {
353                int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
354                nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
355                item.set(ClassWriter.HANDLE_BASE + readByte(index),
356                        readClass(fieldOrMethodRef, buf),
357                        readUTF8(nameType, buf), readUTF8(nameType + 2, buf));
358                break;
359            }
360            case ClassWriter.INDY:
361                if (classWriter.bootstrapMethods == null) {
362                    copyBootstrapMethods(classWriter, items2, buf);
363                }
364                nameType = items[readUnsignedShort(index + 2)];
365                item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf),
366                        readUnsignedShort(index));
367                break;
368            // case ClassWriter.STR:
369            // case ClassWriter.CLASS:
370            // case ClassWriter.MTYPE:
371            // case ClassWriter.MODULE:
372            // case ClassWriter.PACKAGE:
373            default:
374                item.set(tag, readUTF8(index, buf), null, null);
375                break;
376            }
377
378            int index2 = item.hashCode % items2.length;
379            item.next = items2[index2];
380            items2[index2] = item;
381        }
382
383        int off = items[1] - 1;
384        classWriter.pool.putByteArray(b, off, header - off);
385        classWriter.items = items2;
386        classWriter.threshold = (int) (0.75d * ll);
387        classWriter.index = ll;
388    }
389
390    /**
391     * Copies the bootstrap method data into the given {@link ClassWriter}.
392     * Should be called before the {@link #accept(ClassVisitor,int)} method.
393     * 
394     * @param classWriter
395     *            the {@link ClassWriter} to copy bootstrap methods into.
396     */
397    private void copyBootstrapMethods(final ClassWriter classWriter,
398            final Item[] items, final char[] c) {
399        // finds the "BootstrapMethods" attribute
400        int u = getAttributes();
401        boolean found = false;
402        for (int i = readUnsignedShort(u); i > 0; --i) {
403            String attrName = readUTF8(u + 2, c);
404            if ("BootstrapMethods".equals(attrName)) {
405                found = true;
406                break;
407            }
408            u += 6 + readInt(u + 4);
409        }
410        if (!found) {
411            return;
412        }
413        // copies the bootstrap methods in the class writer
414        int boostrapMethodCount = readUnsignedShort(u + 8);
415        for (int j = 0, v = u + 10; j < boostrapMethodCount; j++) {
416            int position = v - u - 10;
417            int hashCode = readConst(readUnsignedShort(v), c).hashCode();
418            for (int k = readUnsignedShort(v + 2); k > 0; --k) {
419                hashCode ^= readConst(readUnsignedShort(v + 4), c).hashCode();
420                v += 2;
421            }
422            v += 4;
423            Item item = new Item(j);
424            item.set(position, hashCode & 0x7FFFFFFF);
425            int index = item.hashCode % items.length;
426            item.next = items[index];
427            items[index] = item;
428        }
429        int attrSize = readInt(u + 4);
430        ByteVector bootstrapMethods = new ByteVector(attrSize + 62);
431        bootstrapMethods.putByteArray(b, u + 10, attrSize - 2);
432        classWriter.bootstrapMethodsCount = boostrapMethodCount;
433        classWriter.bootstrapMethods = bootstrapMethods;
434    }
435
436    /**
437     * Constructs a new {@link ClassReader} object.
438     * 
439     * @param is
440     *            an input stream from which to read the class.
441     * @throws IOException
442     *             if a problem occurs during reading.
443     */
444    public ClassReader(final InputStream is) throws IOException {
445        this(readClass(is, false));
446    }
447
448    /**
449     * Constructs a new {@link ClassReader} object.
450     * 
451     * @param name
452     *            the binary qualified name of the class to be read.
453     * @throws IOException
454     *             if an exception occurs during reading.
455     */
456    public ClassReader(final String name) throws IOException {
457        this(readClass(
458                ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
459                        + ".class"), true));
460    }
461
462    /**
463     * Reads the bytecode of a class.
464     * 
465     * @param is
466     *            an input stream from which to read the class.
467     * @param close
468     *            true to close the input stream after reading.
469     * @return the bytecode read from the given input stream.
470     * @throws IOException
471     *             if a problem occurs during reading.
472     */
473    private static byte[] readClass(final InputStream is, boolean close)
474            throws IOException {
475        if (is == null) {
476            throw new IOException("Class not found");
477        }
478        try {
479            byte[] b = new byte[is.available()];
480            int len = 0;
481            while (true) {
482                int n = is.read(b, len, b.length - len);
483                if (n == -1) {
484                    if (len < b.length) {
485                        byte[] c = new byte[len];
486                        System.arraycopy(b, 0, c, 0, len);
487                        b = c;
488                    }
489                    return b;
490                }
491                len += n;
492                if (len == b.length) {
493                    int last = is.read();
494                    if (last < 0) {
495                        return b;
496                    }
497                    byte[] c = new byte[b.length + 1000];
498                    System.arraycopy(b, 0, c, 0, len);
499                    c[len++] = (byte) last;
500                    b = c;
501                }
502            }
503        } finally {
504            if (close) {
505                is.close();
506            }
507        }
508    }
509
510    // ------------------------------------------------------------------------
511    // Public methods
512    // ------------------------------------------------------------------------
513
514    /**
515     * Makes the given visitor visit the Java class of this {@link ClassReader}
516     * . This class is the one specified in the constructor (see
517     * {@link #ClassReader(byte[]) ClassReader}).
518     * 
519     * @param classVisitor
520     *            the visitor that must visit this class.
521     * @param flags
522     *            option flags that can be used to modify the default behavior
523     *            of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}
524     *            , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
525     */
526    public void accept(final ClassVisitor classVisitor, final int flags) {
527        accept(classVisitor, new Attribute[0], flags);
528    }
529
530    /**
531     * Makes the given visitor visit the Java class of this {@link ClassReader}.
532     * This class is the one specified in the constructor (see
533     * {@link #ClassReader(byte[]) ClassReader}).
534     * 
535     * @param classVisitor
536     *            the visitor that must visit this class.
537     * @param attrs
538     *            prototypes of the attributes that must be parsed during the
539     *            visit of the class. Any attribute whose type is not equal to
540     *            the type of one the prototypes will not be parsed: its byte
541     *            array value will be passed unchanged to the ClassWriter.
542     *            <i>This may corrupt it if this value contains references to
543     *            the constant pool, or has syntactic or semantic links with a
544     *            class element that has been transformed by a class adapter
545     *            between the reader and the writer</i>.
546     * @param flags
547     *            option flags that can be used to modify the default behavior
548     *            of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}
549     *            , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
550     */
551    public void accept(final ClassVisitor classVisitor,
552            final Attribute[] attrs, final int flags) {
553        int u = header; // current offset in the class file
554        char[] c = new char[maxStringLength]; // buffer used to read strings
555
556        Context context = new Context();
557        context.attrs = attrs;
558        context.flags = flags;
559        context.buffer = c;
560
561        // reads the class declaration
562        int access = readUnsignedShort(u);
563        String name = readClass(u + 2, c);
564        String superClass = readClass(u + 4, c);
565        String[] interfaces = new String[readUnsignedShort(u + 6)];
566        u += 8;
567        for (int i = 0; i < interfaces.length; ++i) {
568            interfaces[i] = readClass(u, c);
569            u += 2;
570        }
571
572        // reads the class attributes
573        String signature = null;
574        String sourceFile = null;
575        String sourceDebug = null;
576        String enclosingOwner = null;
577        String enclosingName = null;
578        String enclosingDesc = null;
579        String moduleMainClass = null;
580        int anns = 0;
581        int ianns = 0;
582        int tanns = 0;
583        int itanns = 0;
584        int innerClasses = 0;
585        int module = 0;
586        int packages = 0;
587        Attribute attributes = null;
588
589        u = getAttributes();
590        for (int i = readUnsignedShort(u); i > 0; --i) {
591            String attrName = readUTF8(u + 2, c);
592            // tests are sorted in decreasing frequency order
593            // (based on frequencies observed on typical classes)
594            if ("SourceFile".equals(attrName)) {
595                sourceFile = readUTF8(u + 8, c);
596            } else if ("InnerClasses".equals(attrName)) {
597                innerClasses = u + 8;
598            } else if ("EnclosingMethod".equals(attrName)) {
599                enclosingOwner = readClass(u + 8, c);
600                int item = readUnsignedShort(u + 10);
601                if (item != 0) {
602                    enclosingName = readUTF8(items[item], c);
603                    enclosingDesc = readUTF8(items[item] + 2, c);
604                }
605            } else if (SIGNATURES && "Signature".equals(attrName)) {
606                signature = readUTF8(u + 8, c);
607            } else if (ANNOTATIONS
608                    && "RuntimeVisibleAnnotations".equals(attrName)) {
609                anns = u + 8;
610            } else if (ANNOTATIONS
611                    && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
612                tanns = u + 8;
613            } else if ("Deprecated".equals(attrName)) {
614                access |= Opcodes.ACC_DEPRECATED;
615            } else if ("Synthetic".equals(attrName)) {
616                access |= Opcodes.ACC_SYNTHETIC
617                        | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
618            } else if ("SourceDebugExtension".equals(attrName)) {
619                int len = readInt(u + 4);
620                sourceDebug = readUTF(u + 8, len, new char[len]);
621            } else if (ANNOTATIONS
622                    && "RuntimeInvisibleAnnotations".equals(attrName)) {
623                ianns = u + 8;
624            } else if (ANNOTATIONS
625                    && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
626                itanns = u + 8;
627            } else if ("Module".equals(attrName)) {
628                module = u + 8;
629            } else if ("ModuleMainClass".equals(attrName)) {
630                moduleMainClass = readClass(u + 8, c);
631            } else if ("ModulePackages".equals(attrName)) {
632                packages = u + 10;
633            } else if ("BootstrapMethods".equals(attrName)) {
634                int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
635                for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
636                    bootstrapMethods[j] = v;
637                    v += 2 + readUnsignedShort(v + 2) << 1;
638                }
639                context.bootstrapMethods = bootstrapMethods;
640            } else {
641                Attribute attr = readAttribute(attrs, attrName, u + 8,
642                        readInt(u + 4), c, -1, null);
643                if (attr != null) {
644                    attr.next = attributes;
645                    attributes = attr;
646                }
647            }
648            u += 6 + readInt(u + 4);
649        }
650
651        // visits the class declaration
652        classVisitor.visit(readInt(items[1] - 7), access, name, signature,
653                superClass, interfaces);
654
655        // visits the source and debug info
656        if ((flags & SKIP_DEBUG) == 0
657                && (sourceFile != null || sourceDebug != null)) {
658            classVisitor.visitSource(sourceFile, sourceDebug);
659        }
660
661        // visits the module info and associated attributes
662        if (module != 0) {
663            readModule(classVisitor, context, module,
664                    moduleMainClass, packages);
665        }
666
667        // visits the outer class
668        if (enclosingOwner != null) {
669            classVisitor.visitOuterClass(enclosingOwner, enclosingName,
670                    enclosingDesc);
671        }
672
673        // visits the class annotations and type annotations
674        if (ANNOTATIONS && anns != 0) {
675            for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
676                v = readAnnotationValues(v + 2, c, true,
677                        classVisitor.visitAnnotation(readUTF8(v, c), true));
678            }
679        }
680        if (ANNOTATIONS && ianns != 0) {
681            for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
682                v = readAnnotationValues(v + 2, c, true,
683                        classVisitor.visitAnnotation(readUTF8(v, c), false));
684            }
685        }
686        if (ANNOTATIONS && tanns != 0) {
687            for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
688                v = readAnnotationTarget(context, v);
689                v = readAnnotationValues(v + 2, c, true,
690                        classVisitor.visitTypeAnnotation(context.typeRef,
691                                context.typePath, readUTF8(v, c), true));
692            }
693        }
694        if (ANNOTATIONS && itanns != 0) {
695            for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
696                v = readAnnotationTarget(context, v);
697                v = readAnnotationValues(v + 2, c, true,
698                        classVisitor.visitTypeAnnotation(context.typeRef,
699                                context.typePath, readUTF8(v, c), false));
700            }
701        }
702
703        // visits the attributes
704        while (attributes != null) {
705            Attribute attr = attributes.next;
706            attributes.next = null;
707            classVisitor.visitAttribute(attributes);
708            attributes = attr;
709        }
710
711        // visits the inner classes
712        if (innerClasses != 0) {
713            int v = innerClasses + 2;
714            for (int i = readUnsignedShort(innerClasses); i > 0; --i) {
715                classVisitor.visitInnerClass(readClass(v, c),
716                        readClass(v + 2, c), readUTF8(v + 4, c),
717                        readUnsignedShort(v + 6));
718                v += 8;
719            }
720        }
721
722        // visits the fields and methods
723        u = header + 10 + 2 * interfaces.length;
724        for (int i = readUnsignedShort(u - 2); i > 0; --i) {
725            u = readField(classVisitor, context, u);
726        }
727        u += 2;
728        for (int i = readUnsignedShort(u - 2); i > 0; --i) {
729            u = readMethod(classVisitor, context, u);
730        }
731
732        // visits the end of the class
733        classVisitor.visitEnd();
734    }
735
736    /**
737     * Reads the module attribute and visit it.
738     *
739     * @param classVisitor
740     *           the current class visitor
741     * @param context
742     *           information about the class being parsed.
743     * @param u
744     *           start offset of the module attribute in the class file.
745     * @param mainClass
746     *           name of the main class of a module or null.
747     * @param packages
748     *           start offset of the concealed package attribute.
749     */
750    private void readModule(final ClassVisitor classVisitor,
751            final Context context, int u,
752            final String mainClass, int packages) {
753
754        char[] buffer = context.buffer;
755
756        // reads module name, flags and version
757        String name = readModule(u, buffer);
758        int flags = readUnsignedShort(u + 2);
759        String version = readUTF8(u + 4, buffer);
760        u += 6;
761
762        ModuleVisitor mv = classVisitor.visitModule(name, flags, version);
763        if (mv == null) {
764            return;
765        }
766
767        // module attributes (main class, packages)
768        if (mainClass != null) {
769            mv.visitMainClass(mainClass);
770        }
771
772        if (packages != 0) {
773            for (int i = readUnsignedShort(packages - 2); i > 0; --i) {
774                String packaze = readPackage(packages, buffer);
775                mv.visitPackage(packaze);
776                packages += 2;
777            }
778        }
779
780        // reads requires
781        u += 2;
782        for (int i = readUnsignedShort(u - 2); i > 0; --i) {
783            String module = readModule(u, buffer);
784            int access = readUnsignedShort(u + 2);
785            String requireVersion = readUTF8(u + 4, buffer);
786            mv.visitRequire(module, access, requireVersion);
787            u += 6;
788        }
789
790        // reads exports
791        u += 2;
792        for (int i = readUnsignedShort(u - 2); i > 0; --i) {
793            String export = readPackage(u, buffer);
794            int access = readUnsignedShort(u + 2);
795            int exportToCount = readUnsignedShort(u + 4);
796            u += 6;
797            String[] tos = null;
798            if (exportToCount != 0) {
799                tos = new String[exportToCount];
800                for (int j = 0; j < tos.length; ++j) {
801                    tos[j] = readModule(u, buffer);
802                    u += 2;
803                }
804            }
805            mv.visitExport(export, access, tos);
806        }
807
808        // reads opens
809        u += 2;
810        for (int i = readUnsignedShort(u - 2); i > 0; --i) {
811            String open = readPackage(u, buffer);
812            int access = readUnsignedShort(u + 2);
813            int openToCount = readUnsignedShort(u + 4);
814            u += 6;
815            String[] tos = null;
816            if (openToCount != 0) {
817                tos = new String[openToCount];
818                for (int j = 0; j < tos.length; ++j) {
819                    tos[j] = readModule(u, buffer);
820                    u += 2;
821                }
822            }
823            mv.visitOpen(open, access, tos);
824        }
825
826        // read uses
827        u += 2;
828        for (int i = readUnsignedShort(u - 2); i > 0; --i) {
829            mv.visitUse(readClass(u, buffer));
830            u += 2;
831        }
832
833        // read provides
834        u += 2;
835        for (int i = readUnsignedShort(u - 2); i > 0; --i) {
836            String service = readClass(u, buffer);
837            int provideWithCount = readUnsignedShort(u + 2);
838            u += 4;
839            String[] withs = new String[provideWithCount];
840            for (int j = 0; j < withs.length; ++j) {
841                withs[j] = readClass(u, buffer);
842                u += 2;
843            }
844            mv.visitProvide(service, withs);
845        }
846
847        mv.visitEnd();
848    }
849
850    /**
851     * Reads a field and makes the given visitor visit it.
852     * 
853     * @param classVisitor
854     *            the visitor that must visit the field.
855     * @param context
856     *            information about the class being parsed.
857     * @param u
858     *            the start offset of the field in the class file.
859     * @return the offset of the first byte following the field in the class.
860     */
861    private int readField(final ClassVisitor classVisitor,
862            final Context context, int u) {
863        // reads the field declaration
864        char[] c = context.buffer;
865        int access = readUnsignedShort(u);
866        String name = readUTF8(u + 2, c);
867        String desc = readUTF8(u + 4, c);
868        u += 6;
869
870        // reads the field attributes
871        String signature = null;
872        int anns = 0;
873        int ianns = 0;
874        int tanns = 0;
875        int itanns = 0;
876        Object value = null;
877        Attribute attributes = null;
878
879        for (int i = readUnsignedShort(u); i > 0; --i) {
880            String attrName = readUTF8(u + 2, c);
881            // tests are sorted in decreasing frequency order
882            // (based on frequencies observed on typical classes)
883            if ("ConstantValue".equals(attrName)) {
884                int item = readUnsignedShort(u + 8);
885                value = item == 0 ? null : readConst(item, c);
886            } else if (SIGNATURES && "Signature".equals(attrName)) {
887                signature = readUTF8(u + 8, c);
888            } else if ("Deprecated".equals(attrName)) {
889                access |= Opcodes.ACC_DEPRECATED;
890            } else if ("Synthetic".equals(attrName)) {
891                access |= Opcodes.ACC_SYNTHETIC
892                        | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
893            } else if (ANNOTATIONS
894                    && "RuntimeVisibleAnnotations".equals(attrName)) {
895                anns = u + 8;
896            } else if (ANNOTATIONS
897                    && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
898                tanns = u + 8;
899            } else if (ANNOTATIONS
900                    && "RuntimeInvisibleAnnotations".equals(attrName)) {
901                ianns = u + 8;
902            } else if (ANNOTATIONS
903                    && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
904                itanns = u + 8;
905            } else {
906                Attribute attr = readAttribute(context.attrs, attrName, u + 8,
907                        readInt(u + 4), c, -1, null);
908                if (attr != null) {
909                    attr.next = attributes;
910                    attributes = attr;
911                }
912            }
913            u += 6 + readInt(u + 4);
914        }
915        u += 2;
916
917        // visits the field declaration
918        FieldVisitor fv = classVisitor.visitField(access, name, desc,
919                signature, value);
920        if (fv == null) {
921            return u;
922        }
923
924        // visits the field annotations and type annotations
925        if (ANNOTATIONS && anns != 0) {
926            for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
927                v = readAnnotationValues(v + 2, c, true,
928                        fv.visitAnnotation(readUTF8(v, c), true));
929            }
930        }
931        if (ANNOTATIONS && ianns != 0) {
932            for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
933                v = readAnnotationValues(v + 2, c, true,
934                        fv.visitAnnotation(readUTF8(v, c), false));
935            }
936        }
937        if (ANNOTATIONS && tanns != 0) {
938            for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
939                v = readAnnotationTarget(context, v);
940                v = readAnnotationValues(v + 2, c, true,
941                        fv.visitTypeAnnotation(context.typeRef,
942                                context.typePath, readUTF8(v, c), true));
943            }
944        }
945        if (ANNOTATIONS && itanns != 0) {
946            for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
947                v = readAnnotationTarget(context, v);
948                v = readAnnotationValues(v + 2, c, true,
949                        fv.visitTypeAnnotation(context.typeRef,
950                                context.typePath, readUTF8(v, c), false));
951            }
952        }
953
954        // visits the field attributes
955        while (attributes != null) {
956            Attribute attr = attributes.next;
957            attributes.next = null;
958            fv.visitAttribute(attributes);
959            attributes = attr;
960        }
961
962        // visits the end of the field
963        fv.visitEnd();
964
965        return u;
966    }
967
968    /**
969     * Reads a method and makes the given visitor visit it.
970     * 
971     * @param classVisitor
972     *            the visitor that must visit the method.
973     * @param context
974     *            information about the class being parsed.
975     * @param u
976     *            the start offset of the method in the class file.
977     * @return the offset of the first byte following the method in the class.
978     */
979    private int readMethod(final ClassVisitor classVisitor,
980            final Context context, int u) {
981        // reads the method declaration
982        char[] c = context.buffer;
983        context.access = readUnsignedShort(u);
984        context.name = readUTF8(u + 2, c);
985        context.desc = readUTF8(u + 4, c);
986        u += 6;
987
988        // reads the method attributes
989        int code = 0;
990        int exception = 0;
991        String[] exceptions = null;
992        String signature = null;
993        int methodParameters = 0;
994        int anns = 0;
995        int ianns = 0;
996        int tanns = 0;
997        int itanns = 0;
998        int dann = 0;
999        int mpanns = 0;
1000        int impanns = 0;
1001        int firstAttribute = u;
1002        Attribute attributes = null;
1003
1004        for (int i = readUnsignedShort(u); i > 0; --i) {
1005            String attrName = readUTF8(u + 2, c);
1006            // tests are sorted in decreasing frequency order
1007            // (based on frequencies observed on typical classes)
1008            if ("Code".equals(attrName)) {
1009                if ((context.flags & SKIP_CODE) == 0) {
1010                    code = u + 8;
1011                }
1012            } else if ("Exceptions".equals(attrName)) {
1013                exceptions = new String[readUnsignedShort(u + 8)];
1014                exception = u + 10;
1015                for (int j = 0; j < exceptions.length; ++j) {
1016                    exceptions[j] = readClass(exception, c);
1017                    exception += 2;
1018                }
1019            } else if (SIGNATURES && "Signature".equals(attrName)) {
1020                signature = readUTF8(u + 8, c);
1021            } else if ("Deprecated".equals(attrName)) {
1022                context.access |= Opcodes.ACC_DEPRECATED;
1023            } else if (ANNOTATIONS
1024                    && "RuntimeVisibleAnnotations".equals(attrName)) {
1025                anns = u + 8;
1026            } else if (ANNOTATIONS
1027                    && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
1028                tanns = u + 8;
1029            } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
1030                dann = u + 8;
1031            } else if ("Synthetic".equals(attrName)) {
1032                context.access |= Opcodes.ACC_SYNTHETIC
1033                        | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
1034            } else if (ANNOTATIONS
1035                    && "RuntimeInvisibleAnnotations".equals(attrName)) {
1036                ianns = u + 8;
1037            } else if (ANNOTATIONS
1038                    && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
1039                itanns = u + 8;
1040            } else if (ANNOTATIONS
1041                    && "RuntimeVisibleParameterAnnotations".equals(attrName)) {
1042                mpanns = u + 8;
1043            } else if (ANNOTATIONS
1044                    && "RuntimeInvisibleParameterAnnotations".equals(attrName)) {
1045                impanns = u + 8;
1046            } else if ("MethodParameters".equals(attrName)) {
1047                methodParameters = u + 8;
1048            } else {
1049                Attribute attr = readAttribute(context.attrs, attrName, u + 8,
1050                        readInt(u + 4), c, -1, null);
1051                if (attr != null) {
1052                    attr.next = attributes;
1053                    attributes = attr;
1054                }
1055            }
1056            u += 6 + readInt(u + 4);
1057        }
1058        u += 2;
1059
1060        // visits the method declaration
1061        MethodVisitor mv = classVisitor.visitMethod(context.access,
1062                context.name, context.desc, signature, exceptions);
1063        if (mv == null) {
1064            return u;
1065        }
1066
1067        /*
1068         * if the returned MethodVisitor is in fact a MethodWriter, it means
1069         * there is no method adapter between the reader and the writer. If, in
1070         * addition, the writer's constant pool was copied from this reader
1071         * (mw.cw.cr == this), and the signature and exceptions of the method
1072         * have not been changed, then it is possible to skip all visit events
1073         * and just copy the original code of the method to the writer (the
1074         * access, name and descriptor can have been changed, this is not
1075         * important since they are not copied as is from the reader).
1076         */
1077        if (WRITER && mv instanceof MethodWriter) {
1078            MethodWriter mw = (MethodWriter) mv;
1079            if (mw.cw.cr == this &&
1080                                        (signature != null ? signature.equals(mw.signature) : mw.signature == null)) {
1081                boolean sameExceptions = false;
1082                if (exceptions == null) {
1083                    sameExceptions = mw.exceptionCount == 0;
1084                } else if (exceptions.length == mw.exceptionCount) {
1085                    sameExceptions = true;
1086                    for (int j = exceptions.length - 1; j >= 0; --j) {
1087                        exception -= 2;
1088                        if (mw.exceptions[j] != readUnsignedShort(exception)) {
1089                            sameExceptions = false;
1090                            break;
1091                        }
1092                    }
1093                }
1094                if (sameExceptions) {
1095                    /*
1096                     * we do not copy directly the code into MethodWriter to
1097                     * save a byte array copy operation. The real copy will be
1098                     * done in ClassWriter.toByteArray().
1099                     */
1100                    mw.classReaderOffset = firstAttribute;
1101                    mw.classReaderLength = u - firstAttribute;
1102                    return u;
1103                }
1104            }
1105        }
1106
1107        // visit the method parameters
1108        if (methodParameters != 0) {
1109            for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) {
1110                mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2));
1111            }
1112        }
1113
1114        // visits the method annotations
1115        if (ANNOTATIONS && dann != 0) {
1116            AnnotationVisitor dv = mv.visitAnnotationDefault();
1117            readAnnotationValue(dann, c, null, dv);
1118            if (dv != null) {
1119                dv.visitEnd();
1120            }
1121        }
1122        if (ANNOTATIONS && anns != 0) {
1123            for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
1124                v = readAnnotationValues(v + 2, c, true,
1125                        mv.visitAnnotation(readUTF8(v, c), true));
1126            }
1127        }
1128        if (ANNOTATIONS && ianns != 0) {
1129            for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
1130                v = readAnnotationValues(v + 2, c, true,
1131                        mv.visitAnnotation(readUTF8(v, c), false));
1132            }
1133        }
1134        if (ANNOTATIONS && tanns != 0) {
1135            for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
1136                v = readAnnotationTarget(context, v);
1137                v = readAnnotationValues(v + 2, c, true,
1138                        mv.visitTypeAnnotation(context.typeRef,
1139                                context.typePath, readUTF8(v, c), true));
1140            }
1141        }
1142        if (ANNOTATIONS && itanns != 0) {
1143            for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
1144                v = readAnnotationTarget(context, v);
1145                v = readAnnotationValues(v + 2, c, true,
1146                        mv.visitTypeAnnotation(context.typeRef,
1147                                context.typePath, readUTF8(v, c), false));
1148            }
1149        }
1150        if (ANNOTATIONS && mpanns != 0) {
1151            readParameterAnnotations(mv, context, mpanns, true);
1152        }
1153        if (ANNOTATIONS && impanns != 0) {
1154            readParameterAnnotations(mv, context, impanns, false);
1155        }
1156
1157        // visits the method attributes
1158        while (attributes != null) {
1159            Attribute attr = attributes.next;
1160            attributes.next = null;
1161            mv.visitAttribute(attributes);
1162            attributes = attr;
1163        }
1164
1165        // visits the method code
1166        if (code != 0) {
1167            mv.visitCode();
1168            readCode(mv, context, code);
1169        }
1170
1171        // visits the end of the method
1172        mv.visitEnd();
1173
1174        return u;
1175    }
1176
1177    /**
1178     * Reads the bytecode of a method and makes the given visitor visit it.
1179     * 
1180     * @param mv
1181     *            the visitor that must visit the method's code.
1182     * @param context
1183     *            information about the class being parsed.
1184     * @param u
1185     *            the start offset of the code attribute in the class file.
1186     */
1187    private void readCode(final MethodVisitor mv, final Context context, int u) {
1188        // reads the header
1189        byte[] b = this.b;
1190        char[] c = context.buffer;
1191        int maxStack = readUnsignedShort(u);
1192        int maxLocals = readUnsignedShort(u + 2);
1193        int codeLength = readInt(u + 4);
1194        u += 8;
1195
1196        // reads the bytecode to find the labels
1197        int codeStart = u;
1198        int codeEnd = u + codeLength;
1199        Label[] labels = context.labels = new Label[codeLength + 2];
1200        readLabel(codeLength + 1, labels);
1201        while (u < codeEnd) {
1202            int offset = u - codeStart;
1203            int opcode = b[u] & 0xFF;
1204            switch (ClassWriter.TYPE[opcode]) {
1205            case ClassWriter.NOARG_INSN:
1206            case ClassWriter.IMPLVAR_INSN:
1207                u += 1;
1208                break;
1209            case ClassWriter.LABEL_INSN:
1210                readLabel(offset + readShort(u + 1), labels);
1211                u += 3;
1212                break;
1213            case ClassWriter.ASM_LABEL_INSN:
1214                readLabel(offset + readUnsignedShort(u + 1), labels);
1215                u += 3;
1216                break;
1217            case ClassWriter.LABELW_INSN:
1218            case ClassWriter.ASM_LABELW_INSN:
1219                readLabel(offset + readInt(u + 1), labels);
1220                u += 5;
1221                break;
1222            case ClassWriter.WIDE_INSN:
1223                opcode = b[u + 1] & 0xFF;
1224                if (opcode == Opcodes.IINC) {
1225                    u += 6;
1226                } else {
1227                    u += 4;
1228                }
1229                break;
1230            case ClassWriter.TABL_INSN:
1231                // skips 0 to 3 padding bytes
1232                u = u + 4 - (offset & 3);
1233                // reads instruction
1234                readLabel(offset + readInt(u), labels);
1235                for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) {
1236                    readLabel(offset + readInt(u + 12), labels);
1237                    u += 4;
1238                }
1239                u += 12;
1240                break;
1241            case ClassWriter.LOOK_INSN:
1242                // skips 0 to 3 padding bytes
1243                u = u + 4 - (offset & 3);
1244                // reads instruction
1245                readLabel(offset + readInt(u), labels);
1246                for (int i = readInt(u + 4); i > 0; --i) {
1247                    readLabel(offset + readInt(u + 12), labels);
1248                    u += 8;
1249                }
1250                u += 8;
1251                break;
1252            case ClassWriter.VAR_INSN:
1253            case ClassWriter.SBYTE_INSN:
1254            case ClassWriter.LDC_INSN:
1255                u += 2;
1256                break;
1257            case ClassWriter.SHORT_INSN:
1258            case ClassWriter.LDCW_INSN:
1259            case ClassWriter.FIELDORMETH_INSN:
1260            case ClassWriter.TYPE_INSN:
1261            case ClassWriter.IINC_INSN:
1262                u += 3;
1263                break;
1264            case ClassWriter.ITFMETH_INSN:
1265            case ClassWriter.INDYMETH_INSN:
1266                u += 5;
1267                break;
1268            // case MANA_INSN:
1269            default:
1270                u += 4;
1271                break;
1272            }
1273        }
1274
1275        // reads the try catch entries to find the labels, and also visits them
1276        for (int i = readUnsignedShort(u); i > 0; --i) {
1277            Label start = readLabel(readUnsignedShort(u + 2), labels);
1278            Label end = readLabel(readUnsignedShort(u + 4), labels);
1279            Label handler = readLabel(readUnsignedShort(u + 6), labels);
1280            String type = readUTF8(items[readUnsignedShort(u + 8)], c);
1281            mv.visitTryCatchBlock(start, end, handler, type);
1282            u += 8;
1283        }
1284        u += 2;
1285
1286        // reads the code attributes
1287        int[] tanns = null; // start index of each visible type annotation
1288        int[] itanns = null; // start index of each invisible type annotation
1289        int tann = 0; // current index in tanns array
1290        int itann = 0; // current index in itanns array
1291        int ntoff = -1; // next visible type annotation code offset
1292        int nitoff = -1; // next invisible type annotation code offset
1293        int varTable = 0;
1294        int varTypeTable = 0;
1295        boolean zip = true;
1296        boolean unzip = (context.flags & EXPAND_FRAMES) != 0;
1297        int stackMap = 0;
1298        int stackMapSize = 0;
1299        int frameCount = 0;
1300        Context frame = null;
1301        Attribute attributes = null;
1302
1303        for (int i = readUnsignedShort(u); i > 0; --i) {
1304            String attrName = readUTF8(u + 2, c);
1305            if ("LocalVariableTable".equals(attrName)) {
1306                if ((context.flags & SKIP_DEBUG) == 0) {
1307                    varTable = u + 8;
1308                    for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
1309                        int label = readUnsignedShort(v + 10);
1310                        if (labels[label] == null) {
1311                            readLabel(label, labels).status |= Label.DEBUG;
1312                        }
1313                        label += readUnsignedShort(v + 12);
1314                        if (labels[label] == null) {
1315                            readLabel(label, labels).status |= Label.DEBUG;
1316                        }
1317                        v += 10;
1318                    }
1319                }
1320            } else if ("LocalVariableTypeTable".equals(attrName)) {
1321                varTypeTable = u + 8;
1322            } else if ("LineNumberTable".equals(attrName)) {
1323                if ((context.flags & SKIP_DEBUG) == 0) {
1324                    for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
1325                        int label = readUnsignedShort(v + 10);
1326                        if (labels[label] == null) {
1327                            readLabel(label, labels).status |= Label.DEBUG;
1328                        }
1329                        Label l = labels[label];
1330                        while (l.line > 0) {
1331                            if (l.next == null) {
1332                                l.next = new Label();
1333                            }
1334                            l = l.next;
1335                        }
1336                        l.line = readUnsignedShort(v + 12);
1337                        v += 4;
1338                    }
1339                }
1340            } else if (ANNOTATIONS
1341                    && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
1342                tanns = readTypeAnnotations(mv, context, u + 8, true);
1343                ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1
1344                        : readUnsignedShort(tanns[0] + 1);
1345            } else if (ANNOTATIONS
1346                    && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
1347                itanns = readTypeAnnotations(mv, context, u + 8, false);
1348                nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1
1349                        : readUnsignedShort(itanns[0] + 1);
1350            } else if (FRAMES && "StackMapTable".equals(attrName)) {
1351                if ((context.flags & SKIP_FRAMES) == 0) {
1352                    stackMap = u + 10;
1353                    stackMapSize = readInt(u + 4);
1354                    frameCount = readUnsignedShort(u + 8);
1355                }
1356                /*
1357                 * here we do not extract the labels corresponding to the
1358                 * attribute content. This would require a full parsing of the
1359                 * attribute, which would need to be repeated in the second
1360                 * phase (see below). Instead the content of the attribute is
1361                 * read one frame at a time (i.e. after a frame has been
1362                 * visited, the next frame is read), and the labels it contains
1363                 * are also extracted one frame at a time. Thanks to the
1364                 * ordering of frames, having only a "one frame lookahead" is
1365                 * not a problem, i.e. it is not possible to see an offset
1366                 * smaller than the offset of the current insn and for which no
1367                 * Label exist.
1368                 */
1369                /*
1370                 * This is not true for UNINITIALIZED type offsets. We solve
1371                 * this by parsing the stack map table without a full decoding
1372                 * (see below).
1373                 */
1374            } else if (FRAMES && "StackMap".equals(attrName)) {
1375                if ((context.flags & SKIP_FRAMES) == 0) {
1376                    zip = false;
1377                    stackMap = u + 10;
1378                    stackMapSize = readInt(u + 4);
1379                    frameCount = readUnsignedShort(u + 8);
1380                }
1381                /*
1382                 * IMPORTANT! here we assume that the frames are ordered, as in
1383                 * the StackMapTable attribute, although this is not guaranteed
1384                 * by the attribute format.
1385                 */
1386            } else {
1387                for (int j = 0; j < context.attrs.length; ++j) {
1388                    if (context.attrs[j].type.equals(attrName)) {
1389                        Attribute attr = context.attrs[j].read(this, u + 8,
1390                                readInt(u + 4), c, codeStart - 8, labels);
1391                        if (attr != null) {
1392                            attr.next = attributes;
1393                            attributes = attr;
1394                        }
1395                    }
1396                }
1397            }
1398            u += 6 + readInt(u + 4);
1399        }
1400        u += 2;
1401
1402        // generates the first (implicit) stack map frame
1403        if (FRAMES && stackMap != 0) {
1404            /*
1405             * for the first explicit frame the offset is not offset_delta + 1
1406             * but only offset_delta; setting the implicit frame offset to -1
1407             * allow the use of the "offset_delta + 1" rule in all cases
1408             */
1409            frame = context;
1410            frame.offset = -1;
1411            frame.mode = 0;
1412            frame.localCount = 0;
1413            frame.localDiff = 0;
1414            frame.stackCount = 0;
1415            frame.local = new Object[maxLocals];
1416            frame.stack = new Object[maxStack];
1417            if (unzip) {
1418                getImplicitFrame(context);
1419            }
1420            /*
1421             * Finds labels for UNINITIALIZED frame types. Instead of decoding
1422             * each element of the stack map table, we look for 3 consecutive
1423             * bytes that "look like" an UNINITIALIZED type (tag 8, offset
1424             * within code bounds, NEW instruction at this offset). We may find
1425             * false positives (i.e. not real UNINITIALIZED types), but this
1426             * should be rare, and the only consequence will be the creation of
1427             * an unneeded label. This is better than creating a label for each
1428             * NEW instruction, and faster than fully decoding the whole stack
1429             * map table.
1430             */
1431            for (int i = stackMap; i < stackMap + stackMapSize - 2; ++i) {
1432                if (b[i] == 8) { // UNINITIALIZED FRAME TYPE
1433                    int v = readUnsignedShort(i + 1);
1434                    if (v >= 0 && v < codeLength) {
1435                        if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) {
1436                            readLabel(v, labels);
1437                        }
1438                    }
1439                }
1440            }
1441        }
1442        if ((context.flags & EXPAND_ASM_INSNS) != 0
1443            && (context.flags & EXPAND_FRAMES) != 0) {
1444            // Expanding the ASM pseudo instructions can introduce F_INSERT
1445            // frames, even if the method does not currently have any frame.
1446            // Also these inserted frames must be computed by simulating the
1447            // effect of the bytecode instructions one by one, starting from the
1448            // first one and the last existing frame (or the implicit first
1449            // one). Finally, due to the way MethodWriter computes this (with
1450            // the compute = INSERTED_FRAMES option), MethodWriter needs to know
1451            // maxLocals before the first instruction is visited. For all these
1452            // reasons we always visit the implicit first frame in this case
1453            // (passing only maxLocals - the rest can be and is computed in
1454            // MethodWriter).
1455            mv.visitFrame(Opcodes.F_NEW, maxLocals, null, 0, null);
1456        }
1457
1458        // visits the instructions
1459        int opcodeDelta = (context.flags & EXPAND_ASM_INSNS) == 0 ? -33 : 0;
1460        boolean insertFrame = false;
1461        u = codeStart;
1462        while (u < codeEnd) {
1463            int offset = u - codeStart;
1464
1465            // visits the label and line number for this offset, if any
1466            Label l = labels[offset];
1467            if (l != null) {
1468                Label next = l.next;
1469                l.next = null;
1470                mv.visitLabel(l);
1471                if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) {
1472                    mv.visitLineNumber(l.line, l);
1473                    while (next != null) {
1474                        mv.visitLineNumber(next.line, l);
1475                        next = next.next;
1476                    }
1477                }
1478            }
1479
1480            // visits the frame for this offset, if any
1481            while (FRAMES && frame != null
1482                    && (frame.offset == offset || frame.offset == -1)) {
1483                // if there is a frame for this offset, makes the visitor visit
1484                // it, and reads the next frame if there is one.
1485                if (frame.offset != -1) {
1486                    if (!zip || unzip) {
1487                        mv.visitFrame(Opcodes.F_NEW, frame.localCount,
1488                                frame.local, frame.stackCount, frame.stack);
1489                    } else {
1490                        mv.visitFrame(frame.mode, frame.localDiff, frame.local,
1491                                frame.stackCount, frame.stack);
1492                    }
1493                    // if there is already a frame for this offset, there is no
1494                    // need to insert a new one.
1495                    insertFrame = false;
1496                }
1497                if (frameCount > 0) {
1498                    stackMap = readFrame(stackMap, zip, unzip, frame);
1499                    --frameCount;
1500                } else {
1501                    frame = null;
1502                }
1503            }
1504            // inserts a frame for this offset, if requested by setting
1505            // insertFrame to true during the previous iteration. The actual
1506            // frame content will be computed in MethodWriter.
1507            if (FRAMES && insertFrame) {
1508                mv.visitFrame(ClassWriter.F_INSERT, 0, null, 0, null);
1509                insertFrame = false;
1510            }
1511
1512            // visits the instruction at this offset
1513            int opcode = b[u] & 0xFF;
1514            switch (ClassWriter.TYPE[opcode]) {
1515            case ClassWriter.NOARG_INSN:
1516                mv.visitInsn(opcode);
1517                u += 1;
1518                break;
1519            case ClassWriter.IMPLVAR_INSN:
1520                if (opcode > Opcodes.ISTORE) {
1521                    opcode -= 59; // ISTORE_0
1522                    mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),
1523                            opcode & 0x3);
1524                } else {
1525                    opcode -= 26; // ILOAD_0
1526                    mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), opcode & 0x3);
1527                }
1528                u += 1;
1529                break;
1530            case ClassWriter.LABEL_INSN:
1531                mv.visitJumpInsn(opcode, labels[offset + readShort(u + 1)]);
1532                u += 3;
1533                break;
1534            case ClassWriter.LABELW_INSN:
1535                mv.visitJumpInsn(opcode + opcodeDelta, labels[offset
1536                        + readInt(u + 1)]);
1537                u += 5;
1538                break;
1539            case ClassWriter.ASM_LABEL_INSN: {
1540                // changes temporary opcodes 202 to 217 (inclusive), 218
1541                // and 219 to IFEQ ... JSR (inclusive), IFNULL and
1542                // IFNONNULL
1543                opcode = opcode < 218 ? opcode - 49 : opcode - 20;
1544                Label target = labels[offset + readUnsignedShort(u + 1)];
1545                // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
1546                // <l> with IFNOTxxx <L> GOTO_W <l> L:..., where IFNOTxxx is
1547                // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
1548                // and where <L> designates the instruction just after
1549                // the GOTO_W.
1550                if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
1551                    mv.visitJumpInsn(opcode + 33, target);
1552                } else {
1553                    opcode = opcode <= 166 ? ((opcode + 1) ^ 1) - 1
1554                            : opcode ^ 1;
1555                    Label endif = readLabel(offset + 3, labels);
1556                    mv.visitJumpInsn(opcode, endif);
1557                    mv.visitJumpInsn(200, target); // GOTO_W
1558                    // endif designates the instruction just after GOTO_W,
1559                    // and is visited as part of the next instruction. Since
1560                    // it is a jump target, we need to insert a frame here.
1561                    insertFrame = true;
1562                }
1563                u += 3;
1564                break;
1565            }
1566            case ClassWriter.ASM_LABELW_INSN: {
1567                // replaces the pseudo GOTO_W instruction with a real one.
1568                mv.visitJumpInsn(200, labels[offset + readInt(u + 1)]);
1569                // The instruction just after is a jump target (because pseudo
1570                // GOTO_W are used in patterns IFNOTxxx <L> GOTO_W <l> L:...,
1571                // see MethodWriter), so we need to insert a frame here.
1572                insertFrame = true;
1573                u += 5;
1574                break;
1575            }
1576            case ClassWriter.WIDE_INSN:
1577                opcode = b[u + 1] & 0xFF;
1578                if (opcode == Opcodes.IINC) {
1579                    mv.visitIincInsn(readUnsignedShort(u + 2), readShort(u + 4));
1580                    u += 6;
1581                } else {
1582                    mv.visitVarInsn(opcode, readUnsignedShort(u + 2));
1583                    u += 4;
1584                }
1585                break;
1586            case ClassWriter.TABL_INSN: {
1587                // skips 0 to 3 padding bytes
1588                u = u + 4 - (offset & 3);
1589                // reads instruction
1590                int label = offset + readInt(u);
1591                int min = readInt(u + 4);
1592                int max = readInt(u + 8);
1593                Label[] table = new Label[max - min + 1];
1594                u += 12;
1595                for (int i = 0; i < table.length; ++i) {
1596                    table[i] = labels[offset + readInt(u)];
1597                    u += 4;
1598                }
1599                mv.visitTableSwitchInsn(min, max, labels[label], table);
1600                break;
1601            }
1602            case ClassWriter.LOOK_INSN: {
1603                // skips 0 to 3 padding bytes
1604                u = u + 4 - (offset & 3);
1605                // reads instruction
1606                int label = offset + readInt(u);
1607                int len = readInt(u + 4);
1608                int[] keys = new int[len];
1609                Label[] values = new Label[len];
1610                u += 8;
1611                for (int i = 0; i < len; ++i) {
1612                    keys[i] = readInt(u);
1613                    values[i] = labels[offset + readInt(u + 4)];
1614                    u += 8;
1615                }
1616                mv.visitLookupSwitchInsn(labels[label], keys, values);
1617                break;
1618            }
1619            case ClassWriter.VAR_INSN:
1620                mv.visitVarInsn(opcode, b[u + 1] & 0xFF);
1621                u += 2;
1622                break;
1623            case ClassWriter.SBYTE_INSN:
1624                mv.visitIntInsn(opcode, b[u + 1]);
1625                u += 2;
1626                break;
1627            case ClassWriter.SHORT_INSN:
1628                mv.visitIntInsn(opcode, readShort(u + 1));
1629                u += 3;
1630                break;
1631            case ClassWriter.LDC_INSN:
1632                mv.visitLdcInsn(readConst(b[u + 1] & 0xFF, c));
1633                u += 2;
1634                break;
1635            case ClassWriter.LDCW_INSN:
1636                mv.visitLdcInsn(readConst(readUnsignedShort(u + 1), c));
1637                u += 3;
1638                break;
1639            case ClassWriter.FIELDORMETH_INSN:
1640            case ClassWriter.ITFMETH_INSN: {
1641                int cpIndex = items[readUnsignedShort(u + 1)];
1642                boolean itf = b[cpIndex - 1] == ClassWriter.IMETH;
1643                String iowner = readClass(cpIndex, c);
1644                cpIndex = items[readUnsignedShort(cpIndex + 2)];
1645                String iname = readUTF8(cpIndex, c);
1646                String idesc = readUTF8(cpIndex + 2, c);
1647                if (opcode < Opcodes.INVOKEVIRTUAL) {
1648                    mv.visitFieldInsn(opcode, iowner, iname, idesc);
1649                } else {
1650                    mv.visitMethodInsn(opcode, iowner, iname, idesc, itf);
1651                }
1652                if (opcode == Opcodes.INVOKEINTERFACE) {
1653                    u += 5;
1654                } else {
1655                    u += 3;
1656                }
1657                break;
1658            }
1659            case ClassWriter.INDYMETH_INSN: {
1660                int cpIndex = items[readUnsignedShort(u + 1)];
1661                int bsmIndex = context.bootstrapMethods[readUnsignedShort(cpIndex)];
1662                Handle bsm = (Handle) readConst(readUnsignedShort(bsmIndex), c);
1663                int bsmArgCount = readUnsignedShort(bsmIndex + 2);
1664                Object[] bsmArgs = new Object[bsmArgCount];
1665                bsmIndex += 4;
1666                for (int i = 0; i < bsmArgCount; i++) {
1667                    bsmArgs[i] = readConst(readUnsignedShort(bsmIndex), c);
1668                    bsmIndex += 2;
1669                }
1670                cpIndex = items[readUnsignedShort(cpIndex + 2)];
1671                String iname = readUTF8(cpIndex, c);
1672                String idesc = readUTF8(cpIndex + 2, c);
1673                mv.visitInvokeDynamicInsn(iname, idesc, bsm, bsmArgs);
1674                u += 5;
1675                break;
1676            }
1677            case ClassWriter.TYPE_INSN:
1678                mv.visitTypeInsn(opcode, readClass(u + 1, c));
1679                u += 3;
1680                break;
1681            case ClassWriter.IINC_INSN:
1682                mv.visitIincInsn(b[u + 1] & 0xFF, b[u + 2]);
1683                u += 3;
1684                break;
1685            // case MANA_INSN:
1686            default:
1687                mv.visitMultiANewArrayInsn(readClass(u + 1, c), b[u + 3] & 0xFF);
1688                u += 4;
1689                break;
1690            }
1691
1692            // visit the instruction annotations, if any
1693            while (tanns != null && tann < tanns.length && ntoff <= offset) {
1694                if (ntoff == offset) {
1695                    int v = readAnnotationTarget(context, tanns[tann]);
1696                    readAnnotationValues(v + 2, c, true,
1697                            mv.visitInsnAnnotation(context.typeRef,
1698                                    context.typePath, readUTF8(v, c), true));
1699                }
1700                ntoff = ++tann >= tanns.length || readByte(tanns[tann]) < 0x43 ? -1
1701                        : readUnsignedShort(tanns[tann] + 1);
1702            }
1703            while (itanns != null && itann < itanns.length && nitoff <= offset) {
1704                if (nitoff == offset) {
1705                    int v = readAnnotationTarget(context, itanns[itann]);
1706                    readAnnotationValues(v + 2, c, true,
1707                            mv.visitInsnAnnotation(context.typeRef,
1708                                    context.typePath, readUTF8(v, c), false));
1709                }
1710                nitoff = ++itann >= itanns.length
1711                        || readByte(itanns[itann]) < 0x43 ? -1
1712                        : readUnsignedShort(itanns[itann] + 1);
1713            }
1714        }
1715        if (labels[codeLength] != null) {
1716            mv.visitLabel(labels[codeLength]);
1717        }
1718
1719        // visits the local variable tables
1720        if ((context.flags & SKIP_DEBUG) == 0 && varTable != 0) {
1721            int[] typeTable = null;
1722            if (varTypeTable != 0) {
1723                u = varTypeTable + 2;
1724                typeTable = new int[readUnsignedShort(varTypeTable) * 3];
1725                for (int i = typeTable.length; i > 0;) {
1726                    typeTable[--i] = u + 6; // signature
1727                    typeTable[--i] = readUnsignedShort(u + 8); // index
1728                    typeTable[--i] = readUnsignedShort(u); // start
1729                    u += 10;
1730                }
1731            }
1732            u = varTable + 2;
1733            for (int i = readUnsignedShort(varTable); i > 0; --i) {
1734                int start = readUnsignedShort(u);
1735                int length = readUnsignedShort(u + 2);
1736                int index = readUnsignedShort(u + 8);
1737                String vsignature = null;
1738                if (typeTable != null) {
1739                    for (int j = 0; j < typeTable.length; j += 3) {
1740                        if (typeTable[j] == start && typeTable[j + 1] == index) {
1741                            vsignature = readUTF8(typeTable[j + 2], c);
1742                            break;
1743                        }
1744                    }
1745                }
1746                mv.visitLocalVariable(readUTF8(u + 4, c), readUTF8(u + 6, c),
1747                        vsignature, labels[start], labels[start + length],
1748                        index);
1749                u += 10;
1750            }
1751        }
1752
1753        // visits the local variables type annotations
1754        if (tanns != null) {
1755            for (int i = 0; i < tanns.length; ++i) {
1756                if ((readByte(tanns[i]) >> 1) == (0x40 >> 1)) {
1757                    int v = readAnnotationTarget(context, tanns[i]);
1758                    v = readAnnotationValues(v + 2, c, true,
1759                            mv.visitLocalVariableAnnotation(context.typeRef,
1760                                    context.typePath, context.start,
1761                                    context.end, context.index, readUTF8(v, c),
1762                                    true));
1763                }
1764            }
1765        }
1766        if (itanns != null) {
1767            for (int i = 0; i < itanns.length; ++i) {
1768                if ((readByte(itanns[i]) >> 1) == (0x40 >> 1)) {
1769                    int v = readAnnotationTarget(context, itanns[i]);
1770                    v = readAnnotationValues(v + 2, c, true,
1771                            mv.visitLocalVariableAnnotation(context.typeRef,
1772                                    context.typePath, context.start,
1773                                    context.end, context.index, readUTF8(v, c),
1774                                    false));
1775                }
1776            }
1777        }
1778
1779        // visits the code attributes
1780        while (attributes != null) {
1781            Attribute attr = attributes.next;
1782            attributes.next = null;
1783            mv.visitAttribute(attributes);
1784            attributes = attr;
1785        }
1786
1787        // visits the max stack and max locals values
1788        mv.visitMaxs(maxStack, maxLocals);
1789    }
1790
1791    /**
1792     * Parses a type annotation table to find the labels, and to visit the try
1793     * catch block annotations.
1794     * 
1795     * @param u
1796     *            the start offset of a type annotation table.
1797     * @param mv
1798     *            the method visitor to be used to visit the try catch block
1799     *            annotations.
1800     * @param context
1801     *            information about the class being parsed.
1802     * @param visible
1803     *            if the type annotation table to parse contains runtime visible
1804     *            annotations.
1805     * @return the start offset of each type annotation in the parsed table.
1806     */
1807    private int[] readTypeAnnotations(final MethodVisitor mv,
1808            final Context context, int u, boolean visible) {
1809        char[] c = context.buffer;
1810        int[] offsets = new int[readUnsignedShort(u)];
1811        u += 2;
1812        for (int i = 0; i < offsets.length; ++i) {
1813            offsets[i] = u;
1814            int target = readInt(u);
1815            switch (target >>> 24) {
1816            case 0x00: // CLASS_TYPE_PARAMETER
1817            case 0x01: // METHOD_TYPE_PARAMETER
1818            case 0x16: // METHOD_FORMAL_PARAMETER
1819                u += 2;
1820                break;
1821            case 0x13: // FIELD
1822            case 0x14: // METHOD_RETURN
1823            case 0x15: // METHOD_RECEIVER
1824                u += 1;
1825                break;
1826            case 0x40: // LOCAL_VARIABLE
1827            case 0x41: // RESOURCE_VARIABLE
1828                for (int j = readUnsignedShort(u + 1); j > 0; --j) {
1829                    int start = readUnsignedShort(u + 3);
1830                    int length = readUnsignedShort(u + 5);
1831                    readLabel(start, context.labels);
1832                    readLabel(start + length, context.labels);
1833                    u += 6;
1834                }
1835                u += 3;
1836                break;
1837            case 0x47: // CAST
1838            case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
1839            case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
1840            case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
1841            case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
1842                u += 4;
1843                break;
1844            // case 0x10: // CLASS_EXTENDS
1845            // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
1846            // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
1847            // case 0x17: // THROWS
1848            // case 0x42: // EXCEPTION_PARAMETER
1849            // case 0x43: // INSTANCEOF
1850            // case 0x44: // NEW
1851            // case 0x45: // CONSTRUCTOR_REFERENCE
1852            // case 0x46: // METHOD_REFERENCE
1853            default:
1854                u += 3;
1855                break;
1856            }
1857            int pathLength = readByte(u);
1858            if ((target >>> 24) == 0x42) {
1859                TypePath path = pathLength == 0 ? null : new TypePath(b, u);
1860                u += 1 + 2 * pathLength;
1861                u = readAnnotationValues(u + 2, c, true,
1862                        mv.visitTryCatchAnnotation(target, path,
1863                                readUTF8(u, c), visible));
1864            } else {
1865                u = readAnnotationValues(u + 3 + 2 * pathLength, c, true, null);
1866            }
1867        }
1868        return offsets;
1869    }
1870
1871    /**
1872     * Parses the header of a type annotation to extract its target_type and
1873     * target_path (the result is stored in the given context), and returns the
1874     * start offset of the rest of the type_annotation structure (i.e. the
1875     * offset to the type_index field, which is followed by
1876     * num_element_value_pairs and then the name,value pairs).
1877     * 
1878     * @param context
1879     *            information about the class being parsed. This is where the
1880     *            extracted target_type and target_path must be stored.
1881     * @param u
1882     *            the start offset of a type_annotation structure.
1883     * @return the start offset of the rest of the type_annotation structure.
1884     */
1885    private int readAnnotationTarget(final Context context, int u) {
1886        int target = readInt(u);
1887        switch (target >>> 24) {
1888        case 0x00: // CLASS_TYPE_PARAMETER
1889        case 0x01: // METHOD_TYPE_PARAMETER
1890        case 0x16: // METHOD_FORMAL_PARAMETER
1891            target &= 0xFFFF0000;
1892            u += 2;
1893            break;
1894        case 0x13: // FIELD
1895        case 0x14: // METHOD_RETURN
1896        case 0x15: // METHOD_RECEIVER
1897            target &= 0xFF000000;
1898            u += 1;
1899            break;
1900        case 0x40: // LOCAL_VARIABLE
1901        case 0x41: { // RESOURCE_VARIABLE
1902            target &= 0xFF000000;
1903            int n = readUnsignedShort(u + 1);
1904            context.start = new Label[n];
1905            context.end = new Label[n];
1906            context.index = new int[n];
1907            u += 3;
1908            for (int i = 0; i < n; ++i) {
1909                int start = readUnsignedShort(u);
1910                int length = readUnsignedShort(u + 2);
1911                context.start[i] = readLabel(start, context.labels);
1912                context.end[i] = readLabel(start + length, context.labels);
1913                context.index[i] = readUnsignedShort(u + 4);
1914                u += 6;
1915            }
1916            break;
1917        }
1918        case 0x47: // CAST
1919        case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
1920        case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
1921        case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
1922        case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
1923            target &= 0xFF0000FF;
1924            u += 4;
1925            break;
1926        // case 0x10: // CLASS_EXTENDS
1927        // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
1928        // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
1929        // case 0x17: // THROWS
1930        // case 0x42: // EXCEPTION_PARAMETER
1931        // case 0x43: // INSTANCEOF
1932        // case 0x44: // NEW
1933        // case 0x45: // CONSTRUCTOR_REFERENCE
1934        // case 0x46: // METHOD_REFERENCE
1935        default:
1936            target &= (target >>> 24) < 0x43 ? 0xFFFFFF00 : 0xFF000000;
1937            u += 3;
1938            break;
1939        }
1940        int pathLength = readByte(u);
1941        context.typeRef = target;
1942        context.typePath = pathLength == 0 ? null : new TypePath(b, u);
1943        return u + 1 + 2 * pathLength;
1944    }
1945
1946    /**
1947     * Reads parameter annotations and makes the given visitor visit them.
1948     * 
1949     * @param mv
1950     *            the visitor that must visit the annotations.
1951     * @param context
1952     *            information about the class being parsed.
1953     * @param v
1954     *            start offset in {@link #b b} of the annotations to be read.
1955     * @param visible
1956     *            <tt>true</tt> if the annotations to be read are visible at
1957     *            runtime.
1958     */
1959    private void readParameterAnnotations(final MethodVisitor mv,
1960            final Context context, int v, final boolean visible) {
1961        int i;
1962        int n = b[v++] & 0xFF;
1963        // workaround for a bug in javac (javac compiler generates a parameter
1964        // annotation array whose size is equal to the number of parameters in
1965        // the Java source file, while it should generate an array whose size is
1966        // equal to the number of parameters in the method descriptor - which
1967        // includes the synthetic parameters added by the compiler). This work-
1968        // around supposes that the synthetic parameters are the first ones.
1969        int synthetics = Type.getArgumentTypes(context.desc).length - n;
1970        AnnotationVisitor av;
1971        for (i = 0; i < synthetics; ++i) {
1972            // virtual annotation to detect synthetic parameters in MethodWriter
1973            av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false);
1974            if (av != null) {
1975                av.visitEnd();
1976            }
1977        }
1978        char[] c = context.buffer;
1979        for (; i < n + synthetics; ++i) {
1980            int j = readUnsignedShort(v);
1981            v += 2;
1982            for (; j > 0; --j) {
1983                av = mv.visitParameterAnnotation(i, readUTF8(v, c), visible);
1984                v = readAnnotationValues(v + 2, c, true, av);
1985            }
1986        }
1987    }
1988
1989    /**
1990     * Reads the values of an annotation and makes the given visitor visit them.
1991     * 
1992     * @param v
1993     *            the start offset in {@link #b b} of the values to be read
1994     *            (including the unsigned short that gives the number of
1995     *            values).
1996     * @param buf
1997     *            buffer to be used to call {@link #readUTF8 readUTF8},
1998     *            {@link #readClass(int,char[]) readClass} or {@link #readConst
1999     *            readConst}.
2000     * @param named
2001     *            if the annotation values are named or not.
2002     * @param av
2003     *            the visitor that must visit the values.
2004     * @return the end offset of the annotation values.
2005     */
2006    private int readAnnotationValues(int v, final char[] buf,
2007            final boolean named, final AnnotationVisitor av) {
2008        int i = readUnsignedShort(v);
2009        v += 2;
2010        if (named) {
2011            for (; i > 0; --i) {
2012                v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av);
2013            }
2014        } else {
2015            for (; i > 0; --i) {
2016                v = readAnnotationValue(v, buf, null, av);
2017            }
2018        }
2019        if (av != null) {
2020            av.visitEnd();
2021        }
2022        return v;
2023    }
2024
2025    /**
2026     * Reads a value of an annotation and makes the given visitor visit it.
2027     * 
2028     * @param v
2029     *            the start offset in {@link #b b} of the value to be read
2030     *            (<i>not including the value name constant pool index</i>).
2031     * @param buf
2032     *            buffer to be used to call {@link #readUTF8 readUTF8},
2033     *            {@link #readClass(int,char[]) readClass} or {@link #readConst
2034     *            readConst}.
2035     * @param name
2036     *            the name of the value to be read.
2037     * @param av
2038     *            the visitor that must visit the value.
2039     * @return the end offset of the annotation value.
2040     */
2041    private int readAnnotationValue(int v, final char[] buf, final String name,
2042            final AnnotationVisitor av) {
2043        int i;
2044        if (av == null) {
2045            switch (b[v] & 0xFF) {
2046            case 'e': // enum_const_value
2047                return v + 5;
2048            case '@': // annotation_value
2049                return readAnnotationValues(v + 3, buf, true, null);
2050            case '[': // array_value
2051                return readAnnotationValues(v + 1, buf, false, null);
2052            default:
2053                return v + 3;
2054            }
2055        }
2056        switch (b[v++] & 0xFF) {
2057        case 'I': // pointer to CONSTANT_Integer
2058        case 'J': // pointer to CONSTANT_Long
2059        case 'F': // pointer to CONSTANT_Float
2060        case 'D': // pointer to CONSTANT_Double
2061            av.visit(name, readConst(readUnsignedShort(v), buf));
2062            v += 2;
2063            break;
2064        case 'B': // pointer to CONSTANT_Byte
2065            av.visit(name, (byte) readInt(items[readUnsignedShort(v)]));
2066            v += 2;
2067            break;
2068        case 'Z': // pointer to CONSTANT_Boolean
2069            av.visit(name,
2070                    readInt(items[readUnsignedShort(v)]) == 0 ? Boolean.FALSE
2071                            : Boolean.TRUE);
2072            v += 2;
2073            break;
2074        case 'S': // pointer to CONSTANT_Short
2075            av.visit(name, (short) readInt(items[readUnsignedShort(v)]));
2076            v += 2;
2077            break;
2078        case 'C': // pointer to CONSTANT_Char
2079            av.visit(name, (char) readInt(items[readUnsignedShort(v)]));
2080            v += 2;
2081            break;
2082        case 's': // pointer to CONSTANT_Utf8
2083            av.visit(name, readUTF8(v, buf));
2084            v += 2;
2085            break;
2086        case 'e': // enum_const_value
2087            av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));
2088            v += 4;
2089            break;
2090        case 'c': // class_info
2091            av.visit(name, Type.getType(readUTF8(v, buf)));
2092            v += 2;
2093            break;
2094        case '@': // annotation_value
2095            v = readAnnotationValues(v + 2, buf, true,
2096                    av.visitAnnotation(name, readUTF8(v, buf)));
2097            break;
2098        case '[': // array_value
2099            int size = readUnsignedShort(v);
2100            v += 2;
2101            if (size == 0) {
2102                return readAnnotationValues(v - 2, buf, false,
2103                        av.visitArray(name));
2104            }
2105            switch (this.b[v++] & 0xFF) {
2106            case 'B':
2107                byte[] bv = new byte[size];
2108                for (i = 0; i < size; i++) {
2109                    bv[i] = (byte) readInt(items[readUnsignedShort(v)]);
2110                    v += 3;
2111                }
2112                av.visit(name, bv);
2113                --v;
2114                break;
2115            case 'Z':
2116                boolean[] zv = new boolean[size];
2117                for (i = 0; i < size; i++) {
2118                    zv[i] = readInt(items[readUnsignedShort(v)]) != 0;
2119                    v += 3;
2120                }
2121                av.visit(name, zv);
2122                --v;
2123                break;
2124            case 'S':
2125                short[] sv = new short[size];
2126                for (i = 0; i < size; i++) {
2127                    sv[i] = (short) readInt(items[readUnsignedShort(v)]);
2128                    v += 3;
2129                }
2130                av.visit(name, sv);
2131                --v;
2132                break;
2133            case 'C':
2134                char[] cv = new char[size];
2135                for (i = 0; i < size; i++) {
2136                    cv[i] = (char) readInt(items[readUnsignedShort(v)]);
2137                    v += 3;
2138                }
2139                av.visit(name, cv);
2140                --v;
2141                break;
2142            case 'I':
2143                int[] iv = new int[size];
2144                for (i = 0; i < size; i++) {
2145                    iv[i] = readInt(items[readUnsignedShort(v)]);
2146                    v += 3;
2147                }
2148                av.visit(name, iv);
2149                --v;
2150                break;
2151            case 'J':
2152                long[] lv = new long[size];
2153                for (i = 0; i < size; i++) {
2154                    lv[i] = readLong(items[readUnsignedShort(v)]);
2155                    v += 3;
2156                }
2157                av.visit(name, lv);
2158                --v;
2159                break;
2160            case 'F':
2161                float[] fv = new float[size];
2162                for (i = 0; i < size; i++) {
2163                    fv[i] = Float
2164                            .intBitsToFloat(readInt(items[readUnsignedShort(v)]));
2165                    v += 3;
2166                }
2167                av.visit(name, fv);
2168                --v;
2169                break;
2170            case 'D':
2171                double[] dv = new double[size];
2172                for (i = 0; i < size; i++) {
2173                    dv[i] = Double
2174                            .longBitsToDouble(readLong(items[readUnsignedShort(v)]));
2175                    v += 3;
2176                }
2177                av.visit(name, dv);
2178                --v;
2179                break;
2180            default:
2181                v = readAnnotationValues(v - 3, buf, false, av.visitArray(name));
2182            }
2183        }
2184        return v;
2185    }
2186
2187    /**
2188     * Computes the implicit frame of the method currently being parsed (as
2189     * defined in the given {@link Context}) and stores it in the given context.
2190     * 
2191     * @param frame
2192     *            information about the class being parsed.
2193     */
2194    private void getImplicitFrame(final Context frame) {
2195        String desc = frame.desc;
2196        Object[] locals = frame.local;
2197        int local = 0;
2198        if ((frame.access & Opcodes.ACC_STATIC) == 0) {
2199            if ("<init>".equals(frame.name)) {
2200                locals[local++] = Opcodes.UNINITIALIZED_THIS;
2201            } else {
2202                locals[local++] = readClass(header + 2, frame.buffer);
2203            }
2204        }
2205        int i = 1;
2206        loop: while (true) {
2207            int j = i;
2208            switch (desc.charAt(i++)) {
2209            case 'Z':
2210            case 'C':
2211            case 'B':
2212            case 'S':
2213            case 'I':
2214                locals[local++] = Opcodes.INTEGER;
2215                break;
2216            case 'F':
2217                locals[local++] = Opcodes.FLOAT;
2218                break;
2219            case 'J':
2220                locals[local++] = Opcodes.LONG;
2221                break;
2222            case 'D':
2223                locals[local++] = Opcodes.DOUBLE;
2224                break;
2225            case '[':
2226                while (desc.charAt(i) == '[') {
2227                    ++i;
2228                }
2229                if (desc.charAt(i) == 'L') {
2230                    ++i;
2231                    while (desc.charAt(i) != ';') {
2232                        ++i;
2233                    }
2234                }
2235                locals[local++] = desc.substring(j, ++i);
2236                break;
2237            case 'L':
2238                while (desc.charAt(i) != ';') {
2239                    ++i;
2240                }
2241                locals[local++] = desc.substring(j + 1, i++);
2242                break;
2243            default:
2244                break loop;
2245            }
2246        }
2247        frame.localCount = local;
2248    }
2249
2250    /**
2251     * Reads a stack map frame and stores the result in the given
2252     * {@link Context} object.
2253     * 
2254     * @param stackMap
2255     *            the start offset of a stack map frame in the class file.
2256     * @param zip
2257     *            if the stack map frame at stackMap is compressed or not.
2258     * @param unzip
2259     *            if the stack map frame must be uncompressed.
2260     * @param frame
2261     *            where the parsed stack map frame must be stored.
2262     * @return the offset of the first byte following the parsed frame.
2263     */
2264    private int readFrame(int stackMap, boolean zip, boolean unzip,
2265            Context frame) {
2266        char[] c = frame.buffer;
2267        Label[] labels = frame.labels;
2268        int tag;
2269        int delta;
2270        if (zip) {
2271            tag = b[stackMap++] & 0xFF;
2272        } else {
2273            tag = MethodWriter.FULL_FRAME;
2274            frame.offset = -1;
2275        }
2276        frame.localDiff = 0;
2277        if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME) {
2278            delta = tag;
2279            frame.mode = Opcodes.F_SAME;
2280            frame.stackCount = 0;
2281        } else if (tag < MethodWriter.RESERVED) {
2282            delta = tag - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME;
2283            stackMap = readFrameType(frame.stack, 0, stackMap, c, labels);
2284            frame.mode = Opcodes.F_SAME1;
2285            frame.stackCount = 1;
2286        } else {
2287            delta = readUnsignedShort(stackMap);
2288            stackMap += 2;
2289            if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
2290                stackMap = readFrameType(frame.stack, 0, stackMap, c, labels);
2291                frame.mode = Opcodes.F_SAME1;
2292                frame.stackCount = 1;
2293            } else if (tag >= MethodWriter.CHOP_FRAME
2294                    && tag < MethodWriter.SAME_FRAME_EXTENDED) {
2295                frame.mode = Opcodes.F_CHOP;
2296                frame.localDiff = MethodWriter.SAME_FRAME_EXTENDED - tag;
2297                frame.localCount -= frame.localDiff;
2298                frame.stackCount = 0;
2299            } else if (tag == MethodWriter.SAME_FRAME_EXTENDED) {
2300                frame.mode = Opcodes.F_SAME;
2301                frame.stackCount = 0;
2302            } else if (tag < MethodWriter.FULL_FRAME) {
2303                int local = unzip ? frame.localCount : 0;
2304                for (int i = tag - MethodWriter.SAME_FRAME_EXTENDED; i > 0; i--) {
2305                    stackMap = readFrameType(frame.local, local++, stackMap, c,
2306                            labels);
2307                }
2308                frame.mode = Opcodes.F_APPEND;
2309                frame.localDiff = tag - MethodWriter.SAME_FRAME_EXTENDED;
2310                frame.localCount += frame.localDiff;
2311                frame.stackCount = 0;
2312            } else { // if (tag == FULL_FRAME) {
2313                frame.mode = Opcodes.F_FULL;
2314                int n = readUnsignedShort(stackMap);
2315                stackMap += 2;
2316                frame.localDiff = n;
2317                frame.localCount = n;
2318                for (int local = 0; n > 0; n--) {
2319                    stackMap = readFrameType(frame.local, local++, stackMap, c,
2320                            labels);
2321                }
2322                n = readUnsignedShort(stackMap);
2323                stackMap += 2;
2324                frame.stackCount = n;
2325                for (int stack = 0; n > 0; n--) {
2326                    stackMap = readFrameType(frame.stack, stack++, stackMap, c,
2327                            labels);
2328                }
2329            }
2330        }
2331        frame.offset += delta + 1;
2332        readLabel(frame.offset, labels);
2333        return stackMap;
2334    }
2335
2336    /**
2337     * Reads a stack map frame type and stores it at the given index in the
2338     * given array.
2339     * 
2340     * @param frame
2341     *            the array where the parsed type must be stored.
2342     * @param index
2343     *            the index in 'frame' where the parsed type must be stored.
2344     * @param v
2345     *            the start offset of the stack map frame type to read.
2346     * @param buf
2347     *            a buffer to read strings.
2348     * @param labels
2349     *            the labels of the method currently being parsed, indexed by
2350     *            their offset. If the parsed type is an Uninitialized type, a
2351     *            new label for the corresponding NEW instruction is stored in
2352     *            this array if it does not already exist.
2353     * @return the offset of the first byte after the parsed type.
2354     */
2355    private int readFrameType(final Object[] frame, final int index, int v,
2356            final char[] buf, final Label[] labels) {
2357        int type = b[v++] & 0xFF;
2358        switch (type) {
2359        case 0:
2360            frame[index] = Opcodes.TOP;
2361            break;
2362        case 1:
2363            frame[index] = Opcodes.INTEGER;
2364            break;
2365        case 2:
2366            frame[index] = Opcodes.FLOAT;
2367            break;
2368        case 3:
2369            frame[index] = Opcodes.DOUBLE;
2370            break;
2371        case 4:
2372            frame[index] = Opcodes.LONG;
2373            break;
2374        case 5:
2375            frame[index] = Opcodes.NULL;
2376            break;
2377        case 6:
2378            frame[index] = Opcodes.UNINITIALIZED_THIS;
2379            break;
2380        case 7: // Object
2381            frame[index] = readClass(v, buf);
2382            v += 2;
2383            break;
2384        default: // Uninitialized
2385            frame[index] = readLabel(readUnsignedShort(v), labels);
2386            v += 2;
2387        }
2388        return v;
2389    }
2390
2391    /**
2392     * Returns the label corresponding to the given offset. The default
2393     * implementation of this method creates a label for the given offset if it
2394     * has not been already created.
2395     * 
2396     * @param offset
2397     *            a bytecode offset in a method.
2398     * @param labels
2399     *            the already created labels, indexed by their offset. If a
2400     *            label already exists for offset this method must not create a
2401     *            new one. Otherwise it must store the new label in this array.
2402     * @return a non null Label, which must be equal to labels[offset].
2403     */
2404    protected Label readLabel(int offset, Label[] labels) {
2405        // SPRING PATCH: leniently handle offset mismatch
2406        if (offset >= labels.length) {
2407            return new Label();
2408        }
2409        // END OF PATCH
2410        if (labels[offset] == null) {
2411            labels[offset] = new Label();
2412        }
2413        return labels[offset];
2414    }
2415
2416    /**
2417     * Returns the start index of the attribute_info structure of this class.
2418     * 
2419     * @return the start index of the attribute_info structure of this class.
2420     */
2421    private int getAttributes() {
2422        // skips the header
2423        int u = header + 8 + readUnsignedShort(header + 6) * 2;
2424        // skips fields and methods
2425        for (int i = readUnsignedShort(u); i > 0; --i) {
2426            for (int j = readUnsignedShort(u + 8); j > 0; --j) {
2427                u += 6 + readInt(u + 12);
2428            }
2429            u += 8;
2430        }
2431        u += 2;
2432        for (int i = readUnsignedShort(u); i > 0; --i) {
2433            for (int j = readUnsignedShort(u + 8); j > 0; --j) {
2434                u += 6 + readInt(u + 12);
2435            }
2436            u += 8;
2437        }
2438        // the attribute_info structure starts just after the methods
2439        return u + 2;
2440    }
2441
2442    /**
2443     * Reads an attribute in {@link #b b}.
2444     * 
2445     * @param attrs
2446     *            prototypes of the attributes that must be parsed during the
2447     *            visit of the class. Any attribute whose type is not equal to
2448     *            the type of one the prototypes is ignored (i.e. an empty
2449     *            {@link Attribute} instance is returned).
2450     * @param type
2451     *            the type of the attribute.
2452     * @param off
2453     *            index of the first byte of the attribute's content in
2454     *            {@link #b b}. The 6 attribute header bytes, containing the
2455     *            type and the length of the attribute, are not taken into
2456     *            account here (they have already been read).
2457     * @param len
2458     *            the length of the attribute's content.
2459     * @param buf
2460     *            buffer to be used to call {@link #readUTF8 readUTF8},
2461     *            {@link #readClass(int,char[]) readClass} or {@link #readConst
2462     *            readConst}.
2463     * @param codeOff
2464     *            index of the first byte of code's attribute content in
2465     *            {@link #b b}, or -1 if the attribute to be read is not a code
2466     *            attribute. The 6 attribute header bytes, containing the type
2467     *            and the length of the attribute, are not taken into account
2468     *            here.
2469     * @param labels
2470     *            the labels of the method's code, or <tt>null</tt> if the
2471     *            attribute to be read is not a code attribute.
2472     * @return the attribute that has been read, or <tt>null</tt> to skip this
2473     *         attribute.
2474     */
2475    private Attribute readAttribute(final Attribute[] attrs, final String type,
2476            final int off, final int len, final char[] buf, final int codeOff,
2477            final Label[] labels) {
2478        for (int i = 0; i < attrs.length; ++i) {
2479            if (attrs[i].type.equals(type)) {
2480                return attrs[i].read(this, off, len, buf, codeOff, labels);
2481            }
2482        }
2483        return new Attribute(type).read(this, off, len, null, -1, null);
2484    }
2485
2486    // ------------------------------------------------------------------------
2487    // Utility methods: low level parsing
2488    // ------------------------------------------------------------------------
2489
2490    /**
2491     * Returns the number of constant pool items in {@link #b b}.
2492     * 
2493     * @return the number of constant pool items in {@link #b b}.
2494     */
2495    public int getItemCount() {
2496        return items.length;
2497    }
2498
2499    /**
2500     * Returns the start index of the constant pool item in {@link #b b}, plus
2501     * one. <i>This method is intended for {@link Attribute} sub classes, and is
2502     * normally not needed by class generators or adapters.</i>
2503     * 
2504     * @param item
2505     *            the index a constant pool item.
2506     * @return the start index of the constant pool item in {@link #b b}, plus
2507     *         one.
2508     */
2509    public int getItem(final int item) {
2510        return items[item];
2511    }
2512
2513    /**
2514     * Returns the maximum length of the strings contained in the constant pool
2515     * of the class.
2516     * 
2517     * @return the maximum length of the strings contained in the constant pool
2518     *         of the class.
2519     */
2520    public int getMaxStringLength() {
2521        return maxStringLength;
2522    }
2523
2524    /**
2525     * Reads a byte value in {@link #b b}. <i>This method is intended for
2526     * {@link Attribute} sub classes, and is normally not needed by class
2527     * generators or adapters.</i>
2528     * 
2529     * @param index
2530     *            the start index of the value to be read in {@link #b b}.
2531     * @return the read value.
2532     */
2533    public int readByte(final int index) {
2534        return b[index] & 0xFF;
2535    }
2536
2537    /**
2538     * Reads an unsigned short value in {@link #b b}. <i>This method is intended
2539     * for {@link Attribute} sub classes, and is normally not needed by class
2540     * generators or adapters.</i>
2541     * 
2542     * @param index
2543     *            the start index of the value to be read in {@link #b b}.
2544     * @return the read value.
2545     */
2546    public int readUnsignedShort(final int index) {
2547        byte[] b = this.b;
2548        return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
2549    }
2550
2551    /**
2552     * Reads a signed short value in {@link #b b}. <i>This method is intended
2553     * for {@link Attribute} sub classes, and is normally not needed by class
2554     * generators or adapters.</i>
2555     * 
2556     * @param index
2557     *            the start index of the value to be read in {@link #b b}.
2558     * @return the read value.
2559     */
2560    public short readShort(final int index) {
2561        byte[] b = this.b;
2562        return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
2563    }
2564
2565    /**
2566     * Reads a signed int value in {@link #b b}. <i>This method is intended for
2567     * {@link Attribute} sub classes, and is normally not needed by class
2568     * generators or adapters.</i>
2569     * 
2570     * @param index
2571     *            the start index of the value to be read in {@link #b b}.
2572     * @return the read value.
2573     */
2574    public int readInt(final int index) {
2575        byte[] b = this.b;
2576        return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)
2577                | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
2578    }
2579
2580    /**
2581     * Reads a signed long value in {@link #b b}. <i>This method is intended for
2582     * {@link Attribute} sub classes, and is normally not needed by class
2583     * generators or adapters.</i>
2584     * 
2585     * @param index
2586     *            the start index of the value to be read in {@link #b b}.
2587     * @return the read value.
2588     */
2589    public long readLong(final int index) {
2590        long l1 = readInt(index);
2591        long l0 = readInt(index + 4) & 0xFFFFFFFFL;
2592        return (l1 << 32) | l0;
2593    }
2594
2595    /**
2596     * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method
2597     * is intended for {@link Attribute} sub classes, and is normally not needed
2598     * by class generators or adapters.</i>
2599     * 
2600     * @param index
2601     *            the start index of an unsigned short value in {@link #b b},
2602     *            whose value is the index of an UTF8 constant pool item.
2603     * @param buf
2604     *            buffer to be used to read the item. This buffer must be
2605     *            sufficiently large. It is not automatically resized.
2606     * @return the String corresponding to the specified UTF8 item.
2607     */
2608    public String readUTF8(int index, final char[] buf) {
2609        int item = readUnsignedShort(index);
2610        if (index == 0 || item == 0) {
2611            return null;
2612        }
2613        String s = strings[item];
2614        if (s != null) {
2615            return s;
2616        }
2617        index = items[item];
2618        return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf);
2619    }
2620
2621    /**
2622     * Reads UTF8 string in {@link #b b}.
2623     * 
2624     * @param index
2625     *            start offset of the UTF8 string to be read.
2626     * @param utfLen
2627     *            length of the UTF8 string to be read.
2628     * @param buf
2629     *            buffer to be used to read the string. This buffer must be
2630     *            sufficiently large. It is not automatically resized.
2631     * @return the String corresponding to the specified UTF8 string.
2632     */
2633    private String readUTF(int index, final int utfLen, final char[] buf) {
2634        int endIndex = index + utfLen;
2635        byte[] b = this.b;
2636        int strLen = 0;
2637        int c;
2638        int st = 0;
2639        char cc = 0;
2640        while (index < endIndex) {
2641            c = b[index++];
2642            switch (st) {
2643            case 0:
2644                c = c & 0xFF;
2645                if (c < 0x80) { // 0xxxxxxx
2646                    buf[strLen++] = (char) c;
2647                } else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx
2648                    cc = (char) (c & 0x1F);
2649                    st = 1;
2650                } else { // 1110 xxxx 10xx xxxx 10xx xxxx
2651                    cc = (char) (c & 0x0F);
2652                    st = 2;
2653                }
2654                break;
2655
2656            case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char
2657                buf[strLen++] = (char) ((cc << 6) | (c & 0x3F));
2658                st = 0;
2659                break;
2660
2661            case 2: // byte 2 of 3-byte char
2662                cc = (char) ((cc << 6) | (c & 0x3F));
2663                st = 1;
2664                break;
2665            }
2666        }
2667        return new String(buf, 0, strLen);
2668    }
2669
2670    /**
2671     * Read a stringish constant item (CONSTANT_Class, CONSTANT_String,
2672     * CONSTANT_MethodType, CONSTANT_Module or CONSTANT_Package
2673     * @param index
2674     * @param buf
2675     * @return
2676     */
2677    private String readStringish(final int index, final char[] buf) {
2678        // computes the start index of the item in b
2679        // and reads the CONSTANT_Utf8 item designated by
2680        // the first two bytes of this item
2681        return readUTF8(items[readUnsignedShort(index)], buf);
2682    }
2683
2684    /**
2685     * Reads a class constant pool item in {@link #b b}. <i>This method is
2686     * intended for {@link Attribute} sub classes, and is normally not needed by
2687     * class generators or adapters.</i>
2688     * 
2689     * @param index
2690     *            the start index of an unsigned short value in {@link #b b},
2691     *            whose value is the index of a class constant pool item.
2692     * @param buf
2693     *            buffer to be used to read the item. This buffer must be
2694     *            sufficiently large. It is not automatically resized.
2695     * @return the String corresponding to the specified class item.
2696     */
2697    public String readClass(final int index, final char[] buf) {
2698        return readStringish(index, buf);
2699    }
2700
2701    /**
2702     * Reads a module constant pool item in {@link #b b}. <i>This method is
2703     * intended for {@link Attribute} sub classes, and is normally not needed by
2704     * class generators or adapters.</i>
2705     *
2706     * @param index
2707     *            the start index of an unsigned short value in {@link #b b},
2708     *            whose value is the index of a module constant pool item.
2709     * @param buf
2710     *            buffer to be used to read the item. This buffer must be
2711     *            sufficiently large. It is not automatically resized.
2712     * @return the String corresponding to the specified module item.
2713     */
2714    public String readModule(final int index, final char[] buf) {
2715        return readStringish(index, buf);
2716    }
2717
2718    /**
2719     * Reads a module constant pool item in {@link #b b}. <i>This method is
2720     * intended for {@link Attribute} sub classes, and is normally not needed by
2721     * class generators or adapters.</i>
2722     *
2723     * @param index
2724     *            the start index of an unsigned short value in {@link #b b},
2725     *            whose value is the index of a module constant pool item.
2726     * @param buf
2727     *            buffer to be used to read the item. This buffer must be
2728     *            sufficiently large. It is not automatically resized.
2729     * @return the String corresponding to the specified module item.
2730     */
2731    public String readPackage(final int index, final char[] buf) {
2732        return readStringish(index, buf);
2733    }
2734
2735    /**
2736     * Reads a numeric or string constant pool item in {@link #b b}. <i>This
2737     * method is intended for {@link Attribute} sub classes, and is normally not
2738     * needed by class generators or adapters.</i>
2739     * 
2740     * @param item
2741     *            the index of a constant pool item.
2742     * @param buf
2743     *            buffer to be used to read the item. This buffer must be
2744     *            sufficiently large. It is not automatically resized.
2745     * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double},
2746     *         {@link String}, {@link Type} or {@link Handle} corresponding to
2747     *         the given constant pool item.
2748     */
2749    public Object readConst(final int item, final char[] buf) {
2750        int index = items[item];
2751        switch (b[index - 1]) {
2752        case ClassWriter.INT:
2753            return readInt(index);
2754        case ClassWriter.FLOAT:
2755            return Float.intBitsToFloat(readInt(index));
2756        case ClassWriter.LONG:
2757            return readLong(index);
2758        case ClassWriter.DOUBLE:
2759            return Double.longBitsToDouble(readLong(index));
2760        case ClassWriter.CLASS:
2761            return Type.getObjectType(readUTF8(index, buf));
2762        case ClassWriter.STR:
2763            return readUTF8(index, buf);
2764        case ClassWriter.MTYPE:
2765            return Type.getMethodType(readUTF8(index, buf));
2766        default: // case ClassWriter.HANDLE_BASE + [1..9]:
2767            int tag = readByte(index);
2768            int[] items = this.items;
2769            int cpIndex = items[readUnsignedShort(index + 1)];
2770            boolean itf = b[cpIndex - 1] == ClassWriter.IMETH;
2771            String owner = readClass(cpIndex, buf);
2772            cpIndex = items[readUnsignedShort(cpIndex + 2)];
2773            String name = readUTF8(cpIndex, buf);
2774            String desc = readUTF8(cpIndex + 2, buf);
2775            return new Handle(tag, owner, name, desc, itf);
2776        }
2777    }
2778}