ClassReader.java revision 674060f01e9090cd21b3c5656cc3204912ad17a6
1/***
2 * ASM: a very small and fast Java bytecode manipulation framework
3 * Copyright (c) 2000-2007 INRIA, France Telecom
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the copyright holders nor the names of its
15 *    contributors may be used to endorse or promote products derived from
16 *    this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGE.
29 */
30package org.mockito.asm;
31
32import java.io.InputStream;
33import java.io.IOException;
34
35/**
36 * A Java class parser to make a {@link ClassVisitor} visit an existing class.
37 * This class parses a byte array conforming to the Java class file format and
38 * calls the appropriate visit methods of a given class visitor for each field,
39 * method and bytecode instruction encountered.
40 *
41 * @author Eric Bruneton
42 * @author Eugene Kuleshov
43 */
44public class ClassReader {
45
46    /**
47     * True to enable signatures support.
48     */
49    static final boolean SIGNATURES = true;
50
51    /**
52     * True to enable annotations support.
53     */
54    static final boolean ANNOTATIONS = true;
55
56    /**
57     * True to enable stack map frames support.
58     */
59    static final boolean FRAMES = true;
60
61    /**
62     * True to enable bytecode writing support.
63     */
64    static final boolean WRITER = true;
65
66    /**
67     * True to enable JSR_W and GOTO_W support.
68     */
69    static final boolean RESIZE = true;
70
71    /**
72     * Flag to skip method code. If this class is set <code>CODE</code>
73     * attribute won't be visited. This can be used, for example, to retrieve
74     * annotations for methods and method parameters.
75     */
76    public static final int SKIP_CODE = 1;
77
78    /**
79     * Flag to skip the debug information in the class. If this flag is set the
80     * debug information of the class is not visited, i.e. the
81     * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
82     * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be
83     * called.
84     */
85    public static final int SKIP_DEBUG = 2;
86
87    /**
88     * Flag to skip the stack map frames in the class. If this flag is set the
89     * stack map frames of the class is not visited, i.e. the
90     * {@link MethodVisitor#visitFrame visitFrame} method will not be called.
91     * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is
92     * used: it avoids visiting frames that will be ignored and recomputed from
93     * scratch in the class writer.
94     */
95    public static final int SKIP_FRAMES = 4;
96
97    /**
98     * Flag to expand the stack map frames. By default stack map frames are
99     * 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     * The class to be parsed. <i>The content of this array must not be
109     * modified. This field is intended for {@link Attribute} sub classes, and
110     * is normally not needed by class generators or adapters.</i>
111     */
112    public final byte[] b;
113
114    /**
115     * The start index of each constant pool item in {@link #b b}, plus one.
116     * The one byte offset skips the constant pool item tag that indicates its
117     * type.
118     */
119    private final int[] items;
120
121    /**
122     * The String objects corresponding to the CONSTANT_Utf8 items. This cache
123     * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
124     * which GREATLY improves performances (by a factor 2 to 3). This caching
125     * strategy could be extended to all constant pool items, but its benefit
126     * would not be so great for these items (because they are much less
127     * expensive to parse than CONSTANT_Utf8 items).
128     */
129    private final String[] strings;
130
131    /**
132     * Maximum length of the strings contained in the constant pool of the
133     * class.
134     */
135    private final int maxStringLength;
136
137    /**
138     * Start index of the class header information (access, name...) in
139     * {@link #b b}.
140     */
141    public final int header;
142
143    // ------------------------------------------------------------------------
144    // Constructors
145    // ------------------------------------------------------------------------
146
147    /**
148     * Constructs a new {@link ClassReader} object.
149     *
150     * @param b the bytecode of the class to be read.
151     */
152    public ClassReader(final byte[] b) {
153        this(b, 0, b.length);
154    }
155
156    /**
157     * Constructs a new {@link ClassReader} object.
158     *
159     * @param b the bytecode of the class to be read.
160     * @param off the start offset of the class data.
161     * @param len the length of the class data.
162     */
163    public ClassReader(final byte[] b, final int off, final int len) {
164        this.b = b;
165        // parses the constant pool
166        items = new int[readUnsignedShort(off + 8)];
167        int n = items.length;
168        strings = new String[n];
169        int max = 0;
170        int index = off + 10;
171        for (int i = 1; i < n; ++i) {
172            items[i] = index + 1;
173            int size;
174            switch (b[index]) {
175                case ClassWriter.FIELD:
176                case ClassWriter.METH:
177                case ClassWriter.IMETH:
178                case ClassWriter.INT:
179                case ClassWriter.FLOAT:
180                case ClassWriter.NAME_TYPE:
181                    size = 5;
182                    break;
183                case ClassWriter.LONG:
184                case ClassWriter.DOUBLE:
185                    size = 9;
186                    ++i;
187                    break;
188                case ClassWriter.UTF8:
189                    size = 3 + readUnsignedShort(index + 1);
190                    if (size > max) {
191                        max = size;
192                    }
193                    break;
194                // case ClassWriter.CLASS:
195                // case ClassWriter.STR:
196                default:
197                    size = 3;
198                    break;
199            }
200            index += size;
201        }
202        maxStringLength = max;
203        // the class header information starts just after the constant pool
204        header = index;
205    }
206
207    /**
208     * Returns the class's access flags (see {@link Opcodes}). This value may
209     * not reflect Deprecated and Synthetic flags when bytecode is before 1.5
210     * and those flags are represented by attributes.
211     *
212     * @return the class access flags
213     *
214     * @see ClassVisitor#visit(int, int, String, String, String, String[])
215     */
216    public int getAccess() {
217        return readUnsignedShort(header);
218    }
219
220    /**
221     * Returns the internal name of the class (see
222     * {@link Type#getInternalName() getInternalName}).
223     *
224     * @return the internal class name
225     *
226     * @see ClassVisitor#visit(int, int, String, String, String, String[])
227     */
228    public String getClassName() {
229        return readClass(header + 2, new char[maxStringLength]);
230    }
231
232    /**
233     * Returns the internal of name of the super class (see
234     * {@link Type#getInternalName() getInternalName}). For interfaces, the
235     * super class is {@link Object}.
236     *
237     * @return the internal name of super class, or <tt>null</tt> for
238     *         {@link Object} class.
239     *
240     * @see ClassVisitor#visit(int, int, String, String, String, String[])
241     */
242    public String getSuperName() {
243        int n = items[readUnsignedShort(header + 4)];
244        return n == 0 ? null : readUTF8(n, new char[maxStringLength]);
245    }
246
247    /**
248     * Returns the internal names of the class's interfaces (see
249     * {@link Type#getInternalName() getInternalName}).
250     *
251     * @return the array of internal names for all implemented interfaces or
252     *         <tt>null</tt>.
253     *
254     * @see ClassVisitor#visit(int, int, String, String, String, String[])
255     */
256    public String[] getInterfaces() {
257        int index = header + 6;
258        int n = readUnsignedShort(index);
259        String[] interfaces = new String[n];
260        if (n > 0) {
261            char[] buf = new char[maxStringLength];
262            for (int i = 0; i < n; ++i) {
263                index += 2;
264                interfaces[i] = readClass(index, buf);
265            }
266        }
267        return interfaces;
268    }
269
270    /**
271     * Copies the constant pool data into the given {@link ClassWriter}. Should
272     * be called before the {@link #accept(ClassVisitor,int)} method.
273     *
274     * @param classWriter the {@link ClassWriter} to copy constant pool into.
275     */
276    void copyPool(final ClassWriter classWriter) {
277        char[] buf = new char[maxStringLength];
278        int ll = items.length;
279        Item[] items2 = new Item[ll];
280        for (int i = 1; i < ll; i++) {
281            int index = items[i];
282            int tag = b[index - 1];
283            Item item = new Item(i);
284            int nameType;
285            switch (tag) {
286                case ClassWriter.FIELD:
287                case ClassWriter.METH:
288                case ClassWriter.IMETH:
289                    nameType = items[readUnsignedShort(index + 2)];
290                    item.set(tag,
291                            readClass(index, buf),
292                            readUTF8(nameType, buf),
293                            readUTF8(nameType + 2, buf));
294                    break;
295
296                case ClassWriter.INT:
297                    item.set(readInt(index));
298                    break;
299
300                case ClassWriter.FLOAT:
301                    item.set(Float.intBitsToFloat(readInt(index)));
302                    break;
303
304                case ClassWriter.NAME_TYPE:
305                    item.set(tag,
306                            readUTF8(index, buf),
307                            readUTF8(index + 2, buf),
308                            null);
309                    break;
310
311                case ClassWriter.LONG:
312                    item.set(readLong(index));
313                    ++i;
314                    break;
315
316                case ClassWriter.DOUBLE:
317                    item.set(Double.longBitsToDouble(readLong(index)));
318                    ++i;
319                    break;
320
321                case ClassWriter.UTF8: {
322                    String s = strings[i];
323                    if (s == null) {
324                        index = items[i];
325                        s = strings[i] = readUTF(index + 2,
326                                readUnsignedShort(index),
327                                buf);
328                    }
329                    item.set(tag, s, null, null);
330                }
331                    break;
332
333                // case ClassWriter.STR:
334                // case ClassWriter.CLASS:
335                default:
336                    item.set(tag, readUTF8(index, buf), null, null);
337                    break;
338            }
339
340            int index2 = item.hashCode % items2.length;
341            item.next = items2[index2];
342            items2[index2] = item;
343        }
344
345        int off = items[1] - 1;
346        classWriter.pool.putByteArray(b, off, header - off);
347        classWriter.items = items2;
348        classWriter.threshold = (int) (0.75d * ll);
349        classWriter.index = ll;
350    }
351
352    /**
353     * Constructs a new {@link ClassReader} object.
354     *
355     * @param is an input stream from which to read the class.
356     * @throws IOException if a problem occurs during reading.
357     */
358    public ClassReader(final InputStream is) throws IOException {
359        this(readClass(is));
360    }
361
362    /**
363     * Constructs a new {@link ClassReader} object.
364     *
365     * @param name the fully qualified name of the class to be read.
366     * @throws IOException if an exception occurs during reading.
367     */
368    public ClassReader(final String name) throws IOException {
369        this(ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
370                + ".class"));
371    }
372
373    /**
374     * Reads the bytecode of a class.
375     *
376     * @param is an input stream from which to read the class.
377     * @return the bytecode read from the given input stream.
378     * @throws IOException if a problem occurs during reading.
379     */
380    private static byte[] readClass(final InputStream is) throws IOException {
381        if (is == null) {
382            throw new IOException("Class not found");
383        }
384        byte[] b = new byte[is.available()];
385        int len = 0;
386        while (true) {
387            int n = is.read(b, len, b.length - len);
388            if (n == -1) {
389                if (len < b.length) {
390                    byte[] c = new byte[len];
391                    System.arraycopy(b, 0, c, 0, len);
392                    b = c;
393                }
394                return b;
395            }
396            len += n;
397            if (len == b.length) {
398                byte[] c = new byte[b.length + 1000];
399                System.arraycopy(b, 0, c, 0, len);
400                b = c;
401            }
402        }
403    }
404
405    // ------------------------------------------------------------------------
406    // Public methods
407    // ------------------------------------------------------------------------
408
409    /**
410     * Makes the given visitor visit the Java class of this {@link ClassReader}.
411     * This class is the one specified in the constructor (see
412     * {@link #ClassReader(byte[]) ClassReader}).
413     *
414     * @param classVisitor the visitor that must visit this class.
415     * @param flags option flags that can be used to modify the default behavior
416     *        of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
417     *        {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
418     */
419    public void accept(final ClassVisitor classVisitor, final int flags) {
420        accept(classVisitor, new Attribute[0], flags);
421    }
422
423    /**
424     * Makes the given visitor visit the Java class of this {@link ClassReader}.
425     * This class is the one specified in the constructor (see
426     * {@link #ClassReader(byte[]) ClassReader}).
427     *
428     * @param classVisitor the visitor that must visit this class.
429     * @param attrs prototypes of the attributes that must be parsed during the
430     *        visit of the class. Any attribute whose type is not equal to the
431     *        type of one the prototypes will not be parsed: its byte array
432     *        value will be passed unchanged to the ClassWriter. <i>This may
433     *        corrupt it if this value contains references to the constant pool,
434     *        or has syntactic or semantic links with a class element that has
435     *        been transformed by a class adapter between the reader and the
436     *        writer</i>.
437     * @param flags option flags that can be used to modify the default behavior
438     *        of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
439     *        {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
440     */
441    public void accept(
442        final ClassVisitor classVisitor,
443        final Attribute[] attrs,
444        final int flags)
445    {
446        byte[] b = this.b; // the bytecode array
447        char[] c = new char[maxStringLength]; // buffer used to read strings
448        int i, j, k; // loop variables
449        int u, v, w; // indexes in b
450        Attribute attr;
451
452        int access;
453        String name;
454        String desc;
455        String attrName;
456        String signature;
457        int anns = 0;
458        int ianns = 0;
459        Attribute cattrs = null;
460
461        // visits the header
462        u = header;
463        access = readUnsignedShort(u);
464        name = readClass(u + 2, c);
465        v = items[readUnsignedShort(u + 4)];
466        String superClassName = v == 0 ? null : readUTF8(v, c);
467        String[] implementedItfs = new String[readUnsignedShort(u + 6)];
468        w = 0;
469        u += 8;
470        for (i = 0; i < implementedItfs.length; ++i) {
471            implementedItfs[i] = readClass(u, c);
472            u += 2;
473        }
474
475        boolean skipCode = (flags & SKIP_CODE) != 0;
476        boolean skipDebug = (flags & SKIP_DEBUG) != 0;
477        boolean unzip = (flags & EXPAND_FRAMES) != 0;
478
479        // skips fields and methods
480        v = u;
481        i = readUnsignedShort(v);
482        v += 2;
483        for (; i > 0; --i) {
484            j = readUnsignedShort(v + 6);
485            v += 8;
486            for (; j > 0; --j) {
487                v += 6 + readInt(v + 2);
488            }
489        }
490        i = readUnsignedShort(v);
491        v += 2;
492        for (; i > 0; --i) {
493            j = readUnsignedShort(v + 6);
494            v += 8;
495            for (; j > 0; --j) {
496                v += 6 + readInt(v + 2);
497            }
498        }
499        // reads the class's attributes
500        signature = null;
501        String sourceFile = null;
502        String sourceDebug = null;
503        String enclosingOwner = null;
504        String enclosingName = null;
505        String enclosingDesc = null;
506
507        i = readUnsignedShort(v);
508        v += 2;
509        for (; i > 0; --i) {
510            attrName = readUTF8(v, c);
511            // tests are sorted in decreasing frequency order
512            // (based on frequencies observed on typical classes)
513            if ("SourceFile".equals(attrName)) {
514                sourceFile = readUTF8(v + 6, c);
515            } else if ("InnerClasses".equals(attrName)) {
516                w = v + 6;
517            } else if ("EnclosingMethod".equals(attrName)) {
518                enclosingOwner = readClass(v + 6, c);
519                int item = readUnsignedShort(v + 8);
520                if (item != 0) {
521                    enclosingName = readUTF8(items[item], c);
522                    enclosingDesc = readUTF8(items[item] + 2, c);
523                }
524            } else if (SIGNATURES && "Signature".equals(attrName)) {
525                signature = readUTF8(v + 6, c);
526            } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
527                anns = v + 6;
528            } else if ("Deprecated".equals(attrName)) {
529                access |= Opcodes.ACC_DEPRECATED;
530            } else if ("Synthetic".equals(attrName)) {
531                access |= Opcodes.ACC_SYNTHETIC;
532            } else if ("SourceDebugExtension".equals(attrName)) {
533                int len = readInt(v + 2);
534                sourceDebug = readUTF(v + 6, len, new char[len]);
535            } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
536                ianns = v + 6;
537            } else {
538                attr = readAttribute(attrs,
539                        attrName,
540                        v + 6,
541                        readInt(v + 2),
542                        c,
543                        -1,
544                        null);
545                if (attr != null) {
546                    attr.next = cattrs;
547                    cattrs = attr;
548                }
549            }
550            v += 6 + readInt(v + 2);
551        }
552        // calls the visit method
553        classVisitor.visit(readInt(4),
554                access,
555                name,
556                signature,
557                superClassName,
558                implementedItfs);
559
560        // calls the visitSource method
561        if (!skipDebug && (sourceFile != null || sourceDebug != null)) {
562            classVisitor.visitSource(sourceFile, sourceDebug);
563        }
564
565        // calls the visitOuterClass method
566        if (enclosingOwner != null) {
567            classVisitor.visitOuterClass(enclosingOwner,
568                    enclosingName,
569                    enclosingDesc);
570        }
571
572        // visits the class annotations
573        if (ANNOTATIONS) {
574            for (i = 1; i >= 0; --i) {
575                v = i == 0 ? ianns : anns;
576                if (v != 0) {
577                    j = readUnsignedShort(v);
578                    v += 2;
579                    for (; j > 0; --j) {
580                        v = readAnnotationValues(v + 2,
581                                c,
582                                true,
583                                classVisitor.visitAnnotation(readUTF8(v, c), i != 0));
584                    }
585                }
586            }
587        }
588
589        // visits the class attributes
590        while (cattrs != null) {
591            attr = cattrs.next;
592            cattrs.next = null;
593            classVisitor.visitAttribute(cattrs);
594            cattrs = attr;
595        }
596
597        // calls the visitInnerClass method
598        if (w != 0) {
599            i = readUnsignedShort(w);
600            w += 2;
601            for (; i > 0; --i) {
602                classVisitor.visitInnerClass(readUnsignedShort(w) == 0
603                        ? null
604                        : readClass(w, c), readUnsignedShort(w + 2) == 0
605                        ? null
606                        : readClass(w + 2, c), readUnsignedShort(w + 4) == 0
607                        ? null
608                        : readUTF8(w + 4, c), readUnsignedShort(w + 6));
609                w += 8;
610            }
611        }
612
613        // visits the fields
614        i = readUnsignedShort(u);
615        u += 2;
616        for (; i > 0; --i) {
617            access = readUnsignedShort(u);
618            name = readUTF8(u + 2, c);
619            desc = readUTF8(u + 4, c);
620            // visits the field's attributes and looks for a ConstantValue
621            // attribute
622            int fieldValueItem = 0;
623            signature = null;
624            anns = 0;
625            ianns = 0;
626            cattrs = null;
627
628            j = readUnsignedShort(u + 6);
629            u += 8;
630            for (; j > 0; --j) {
631                attrName = readUTF8(u, c);
632                // tests are sorted in decreasing frequency order
633                // (based on frequencies observed on typical classes)
634                if ("ConstantValue".equals(attrName)) {
635                    fieldValueItem = readUnsignedShort(u + 6);
636                } else if (SIGNATURES && "Signature".equals(attrName)) {
637                    signature = readUTF8(u + 6, c);
638                } else if ("Deprecated".equals(attrName)) {
639                    access |= Opcodes.ACC_DEPRECATED;
640                } else if ("Synthetic".equals(attrName)) {
641                    access |= Opcodes.ACC_SYNTHETIC;
642                } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
643                    anns = u + 6;
644                } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
645                    ianns = u + 6;
646                } else {
647                    attr = readAttribute(attrs,
648                            attrName,
649                            u + 6,
650                            readInt(u + 2),
651                            c,
652                            -1,
653                            null);
654                    if (attr != null) {
655                        attr.next = cattrs;
656                        cattrs = attr;
657                    }
658                }
659                u += 6 + readInt(u + 2);
660            }
661            // visits the field
662            FieldVisitor fv = classVisitor.visitField(access,
663                    name,
664                    desc,
665                    signature,
666                    fieldValueItem == 0 ? null : readConst(fieldValueItem, c));
667            // visits the field annotations and attributes
668            if (fv != null) {
669                if (ANNOTATIONS) {
670                    for (j = 1; j >= 0; --j) {
671                        v = j == 0 ? ianns : anns;
672                        if (v != 0) {
673                            k = readUnsignedShort(v);
674                            v += 2;
675                            for (; k > 0; --k) {
676                                v = readAnnotationValues(v + 2,
677                                        c,
678                                        true,
679                                        fv.visitAnnotation(readUTF8(v, c), j != 0));
680                            }
681                        }
682                    }
683                }
684                while (cattrs != null) {
685                    attr = cattrs.next;
686                    cattrs.next = null;
687                    fv.visitAttribute(cattrs);
688                    cattrs = attr;
689                }
690                fv.visitEnd();
691            }
692        }
693
694        // visits the methods
695        i = readUnsignedShort(u);
696        u += 2;
697        for (; i > 0; --i) {
698            int u0 = u + 6;
699            access = readUnsignedShort(u);
700            name = readUTF8(u + 2, c);
701            desc = readUTF8(u + 4, c);
702            signature = null;
703            anns = 0;
704            ianns = 0;
705            int dann = 0;
706            int mpanns = 0;
707            int impanns = 0;
708            cattrs = null;
709            v = 0;
710            w = 0;
711
712            // looks for Code and Exceptions attributes
713            j = readUnsignedShort(u + 6);
714            u += 8;
715            for (; j > 0; --j) {
716                attrName = readUTF8(u, c);
717                int attrSize = readInt(u + 2);
718                u += 6;
719                // tests are sorted in decreasing frequency order
720                // (based on frequencies observed on typical classes)
721                if ("Code".equals(attrName)) {
722                    if (!skipCode) {
723                        v = u;
724                    }
725                } else if ("Exceptions".equals(attrName)) {
726                    w = u;
727                } else if (SIGNATURES && "Signature".equals(attrName)) {
728                    signature = readUTF8(u, c);
729                } else if ("Deprecated".equals(attrName)) {
730                    access |= Opcodes.ACC_DEPRECATED;
731                } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
732                    anns = u;
733                } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
734                    dann = u;
735                } else if ("Synthetic".equals(attrName)) {
736                    access |= Opcodes.ACC_SYNTHETIC;
737                } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
738                    ianns = u;
739                } else if (ANNOTATIONS && "RuntimeVisibleParameterAnnotations".equals(attrName))
740                {
741                    mpanns = u;
742                } else if (ANNOTATIONS && "RuntimeInvisibleParameterAnnotations".equals(attrName))
743                {
744                    impanns = u;
745                } else {
746                    attr = readAttribute(attrs,
747                            attrName,
748                            u,
749                            attrSize,
750                            c,
751                            -1,
752                            null);
753                    if (attr != null) {
754                        attr.next = cattrs;
755                        cattrs = attr;
756                    }
757                }
758                u += attrSize;
759            }
760            // reads declared exceptions
761            String[] exceptions;
762            if (w == 0) {
763                exceptions = null;
764            } else {
765                exceptions = new String[readUnsignedShort(w)];
766                w += 2;
767                for (j = 0; j < exceptions.length; ++j) {
768                    exceptions[j] = readClass(w, c);
769                    w += 2;
770                }
771            }
772
773            // visits the method's code, if any
774            MethodVisitor mv = classVisitor.visitMethod(access,
775                    name,
776                    desc,
777                    signature,
778                    exceptions);
779
780            if (mv != null) {
781                /*
782                 * if the returned MethodVisitor is in fact a MethodWriter, it
783                 * means there is no method adapter between the reader and the
784                 * writer. If, in addition, the writer's constant pool was
785                 * copied from this reader (mw.cw.cr == this), and the signature
786                 * and exceptions of the method have not been changed, then it
787                 * is possible to skip all visit events and just copy the
788                 * original code of the method to the writer (the access, name
789                 * and descriptor can have been changed, this is not important
790                 * since they are not copied as is from the reader).
791                 */
792                if (WRITER && mv instanceof MethodWriter) {
793                    MethodWriter mw = (MethodWriter) mv;
794                    if (mw.cw.cr == this) {
795                        if (signature == mw.signature) {
796                            boolean sameExceptions = false;
797                            if (exceptions == null) {
798                                sameExceptions = mw.exceptionCount == 0;
799                            } else {
800                                if (exceptions.length == mw.exceptionCount) {
801                                    sameExceptions = true;
802                                    for (j = exceptions.length - 1; j >= 0; --j)
803                                    {
804                                        w -= 2;
805                                        if (mw.exceptions[j] != readUnsignedShort(w))
806                                        {
807                                            sameExceptions = false;
808                                            break;
809                                        }
810                                    }
811                                }
812                            }
813                            if (sameExceptions) {
814                                /*
815                                 * we do not copy directly the code into
816                                 * MethodWriter to save a byte array copy
817                                 * operation. The real copy will be done in
818                                 * ClassWriter.toByteArray().
819                                 */
820                                mw.classReaderOffset = u0;
821                                mw.classReaderLength = u - u0;
822                                continue;
823                            }
824                        }
825                    }
826                }
827
828                if (ANNOTATIONS && dann != 0) {
829                    AnnotationVisitor dv = mv.visitAnnotationDefault();
830                    readAnnotationValue(dann, c, null, dv);
831                    if (dv != null) {
832                        dv.visitEnd();
833                    }
834                }
835                if (ANNOTATIONS) {
836                    for (j = 1; j >= 0; --j) {
837                        w = j == 0 ? ianns : anns;
838                        if (w != 0) {
839                            k = readUnsignedShort(w);
840                            w += 2;
841                            for (; k > 0; --k) {
842                                w = readAnnotationValues(w + 2,
843                                        c,
844                                        true,
845                                        mv.visitAnnotation(readUTF8(w, c), j != 0));
846                            }
847                        }
848                    }
849                }
850                if (ANNOTATIONS && mpanns != 0) {
851                    readParameterAnnotations(mpanns, desc, c, true, mv);
852                }
853                if (ANNOTATIONS && impanns != 0) {
854                    readParameterAnnotations(impanns, desc, c, false, mv);
855                }
856                while (cattrs != null) {
857                    attr = cattrs.next;
858                    cattrs.next = null;
859                    mv.visitAttribute(cattrs);
860                    cattrs = attr;
861                }
862            }
863
864            if (mv != null && v != 0) {
865                int maxStack = readUnsignedShort(v);
866                int maxLocals = readUnsignedShort(v + 2);
867                int codeLength = readInt(v + 4);
868                v += 8;
869
870                int codeStart = v;
871                int codeEnd = v + codeLength;
872
873                mv.visitCode();
874
875                // 1st phase: finds the labels
876                int label;
877                Label[] labels = new Label[codeLength + 2];
878                readLabel(codeLength + 1, labels);
879                while (v < codeEnd) {
880                    w = v - codeStart;
881                    int opcode = b[v] & 0xFF;
882                    switch (ClassWriter.TYPE[opcode]) {
883                        case ClassWriter.NOARG_INSN:
884                        case ClassWriter.IMPLVAR_INSN:
885                            v += 1;
886                            break;
887                        case ClassWriter.LABEL_INSN:
888                            readLabel(w + readShort(v + 1), labels);
889                            v += 3;
890                            break;
891                        case ClassWriter.LABELW_INSN:
892                            readLabel(w + readInt(v + 1), labels);
893                            v += 5;
894                            break;
895                        case ClassWriter.WIDE_INSN:
896                            opcode = b[v + 1] & 0xFF;
897                            if (opcode == Opcodes.IINC) {
898                                v += 6;
899                            } else {
900                                v += 4;
901                            }
902                            break;
903                        case ClassWriter.TABL_INSN:
904                            // skips 0 to 3 padding bytes*
905                            v = v + 4 - (w & 3);
906                            // reads instruction
907                            readLabel(w + readInt(v), labels);
908                            j = readInt(v + 8) - readInt(v + 4) + 1;
909                            v += 12;
910                            for (; j > 0; --j) {
911                                readLabel(w + readInt(v), labels);
912                                v += 4;
913                            }
914                            break;
915                        case ClassWriter.LOOK_INSN:
916                            // skips 0 to 3 padding bytes*
917                            v = v + 4 - (w & 3);
918                            // reads instruction
919                            readLabel(w + readInt(v), labels);
920                            j = readInt(v + 4);
921                            v += 8;
922                            for (; j > 0; --j) {
923                                readLabel(w + readInt(v + 4), labels);
924                                v += 8;
925                            }
926                            break;
927                        case ClassWriter.VAR_INSN:
928                        case ClassWriter.SBYTE_INSN:
929                        case ClassWriter.LDC_INSN:
930                            v += 2;
931                            break;
932                        case ClassWriter.SHORT_INSN:
933                        case ClassWriter.LDCW_INSN:
934                        case ClassWriter.FIELDORMETH_INSN:
935                        case ClassWriter.TYPE_INSN:
936                        case ClassWriter.IINC_INSN:
937                            v += 3;
938                            break;
939                        case ClassWriter.ITFMETH_INSN:
940                            v += 5;
941                            break;
942                        // case MANA_INSN:
943                        default:
944                            v += 4;
945                            break;
946                    }
947                }
948                // parses the try catch entries
949                j = readUnsignedShort(v);
950                v += 2;
951                for (; j > 0; --j) {
952                    Label start = readLabel(readUnsignedShort(v), labels);
953                    Label end = readLabel(readUnsignedShort(v + 2), labels);
954                    Label handler = readLabel(readUnsignedShort(v + 4), labels);
955                    int type = readUnsignedShort(v + 6);
956                    if (type == 0) {
957                        mv.visitTryCatchBlock(start, end, handler, null);
958                    } else {
959                        mv.visitTryCatchBlock(start,
960                                end,
961                                handler,
962                                readUTF8(items[type], c));
963                    }
964                    v += 8;
965                }
966                // parses the local variable, line number tables, and code
967                // attributes
968                int varTable = 0;
969                int varTypeTable = 0;
970                int stackMap = 0;
971                int frameCount = 0;
972                int frameMode = 0;
973                int frameOffset = 0;
974                int frameLocalCount = 0;
975                int frameLocalDiff = 0;
976                int frameStackCount = 0;
977                Object[] frameLocal = null;
978                Object[] frameStack = null;
979                boolean zip = true;
980                cattrs = null;
981                j = readUnsignedShort(v);
982                v += 2;
983                for (; j > 0; --j) {
984                    attrName = readUTF8(v, c);
985                    if ("LocalVariableTable".equals(attrName)) {
986                        if (!skipDebug) {
987                            varTable = v + 6;
988                            k = readUnsignedShort(v + 6);
989                            w = v + 8;
990                            for (; k > 0; --k) {
991                                label = readUnsignedShort(w);
992                                if (labels[label] == null) {
993                                    readLabel(label, labels).status |= Label.DEBUG;
994                                }
995                                label += readUnsignedShort(w + 2);
996                                if (labels[label] == null) {
997                                    readLabel(label, labels).status |= Label.DEBUG;
998                                }
999                                w += 10;
1000                            }
1001                        }
1002                    } else if ("LocalVariableTypeTable".equals(attrName)) {
1003                        varTypeTable = v + 6;
1004                    } else if ("LineNumberTable".equals(attrName)) {
1005                        if (!skipDebug) {
1006                            k = readUnsignedShort(v + 6);
1007                            w = v + 8;
1008                            for (; k > 0; --k) {
1009                                label = readUnsignedShort(w);
1010                                if (labels[label] == null) {
1011                                    readLabel(label, labels).status |= Label.DEBUG;
1012                                }
1013                                labels[label].line = readUnsignedShort(w + 2);
1014                                w += 4;
1015                            }
1016                        }
1017                    } else if (FRAMES && "StackMapTable".equals(attrName)) {
1018                        if ((flags & SKIP_FRAMES) == 0) {
1019                            stackMap = v + 8;
1020                            frameCount = readUnsignedShort(v + 6);
1021                        }
1022                        /*
1023                         * here we do not extract the labels corresponding to
1024                         * the attribute content. This would require a full
1025                         * parsing of the attribute, which would need to be
1026                         * repeated in the second phase (see below). Instead the
1027                         * content of the attribute is read one frame at a time
1028                         * (i.e. after a frame has been visited, the next frame
1029                         * is read), and the labels it contains are also
1030                         * extracted one frame at a time. Thanks to the ordering
1031                         * of frames, having only a "one frame lookahead" is not
1032                         * a problem, i.e. it is not possible to see an offset
1033                         * smaller than the offset of the current insn and for
1034                         * which no Label exist.
1035                         */
1036                        // TODO true for frame offsets,
1037                        // but for UNINITIALIZED type offsets?
1038                    } else if (FRAMES && "StackMap".equals(attrName)) {
1039                        if ((flags & SKIP_FRAMES) == 0) {
1040                            stackMap = v + 8;
1041                            frameCount = readUnsignedShort(v + 6);
1042                            zip = false;
1043                        }
1044                        /*
1045                         * IMPORTANT! here we assume that the frames are
1046                         * ordered, as in the StackMapTable attribute, although
1047                         * this is not guaranteed by the attribute format.
1048                         */
1049                    } else {
1050                        for (k = 0; k < attrs.length; ++k) {
1051                            if (attrs[k].type.equals(attrName)) {
1052                                attr = attrs[k].read(this,
1053                                        v + 6,
1054                                        readInt(v + 2),
1055                                        c,
1056                                        codeStart - 8,
1057                                        labels);
1058                                if (attr != null) {
1059                                    attr.next = cattrs;
1060                                    cattrs = attr;
1061                                }
1062                            }
1063                        }
1064                    }
1065                    v += 6 + readInt(v + 2);
1066                }
1067
1068                // 2nd phase: visits each instruction
1069                if (FRAMES && stackMap != 0) {
1070                    // creates the very first (implicit) frame from the method
1071                    // descriptor
1072                    frameLocal = new Object[maxLocals];
1073                    frameStack = new Object[maxStack];
1074                    if (unzip) {
1075                        int local = 0;
1076                        if ((access & Opcodes.ACC_STATIC) == 0) {
1077                            if ("<init>".equals(name)) {
1078                                frameLocal[local++] = Opcodes.UNINITIALIZED_THIS;
1079                            } else {
1080                                frameLocal[local++] = readClass(header + 2, c);
1081                            }
1082                        }
1083                        j = 1;
1084                        loop: while (true) {
1085                            k = j;
1086                            switch (desc.charAt(j++)) {
1087                                case 'Z':
1088                                case 'C':
1089                                case 'B':
1090                                case 'S':
1091                                case 'I':
1092                                    frameLocal[local++] = Opcodes.INTEGER;
1093                                    break;
1094                                case 'F':
1095                                    frameLocal[local++] = Opcodes.FLOAT;
1096                                    break;
1097                                case 'J':
1098                                    frameLocal[local++] = Opcodes.LONG;
1099                                    break;
1100                                case 'D':
1101                                    frameLocal[local++] = Opcodes.DOUBLE;
1102                                    break;
1103                                case '[':
1104                                    while (desc.charAt(j) == '[') {
1105                                        ++j;
1106                                    }
1107                                    if (desc.charAt(j) == 'L') {
1108                                        ++j;
1109                                        while (desc.charAt(j) != ';') {
1110                                            ++j;
1111                                        }
1112                                    }
1113                                    frameLocal[local++] = desc.substring(k, ++j);
1114                                    break;
1115                                case 'L':
1116                                    while (desc.charAt(j) != ';') {
1117                                        ++j;
1118                                    }
1119                                    frameLocal[local++] = desc.substring(k + 1,
1120                                            j++);
1121                                    break;
1122                                default:
1123                                    break loop;
1124                            }
1125                        }
1126                        frameLocalCount = local;
1127                    }
1128                    /*
1129                     * for the first explicit frame the offset is not
1130                     * offset_delta + 1 but only offset_delta; setting the
1131                     * implicit frame offset to -1 allow the use of the
1132                     * "offset_delta + 1" rule in all cases
1133                     */
1134                    frameOffset = -1;
1135                }
1136                v = codeStart;
1137                Label l;
1138                while (v < codeEnd) {
1139                    w = v - codeStart;
1140
1141                    l = labels[w];
1142                    if (l != null) {
1143                        mv.visitLabel(l);
1144                        if (!skipDebug && l.line > 0) {
1145                            mv.visitLineNumber(l.line, l);
1146                        }
1147                    }
1148
1149                    while (FRAMES && frameLocal != null
1150                            && (frameOffset == w || frameOffset == -1))
1151                    {
1152                        // if there is a frame for this offset,
1153                        // makes the visitor visit it,
1154                        // and reads the next frame if there is one.
1155                        if (!zip || unzip) {
1156                            mv.visitFrame(Opcodes.F_NEW,
1157                                    frameLocalCount,
1158                                    frameLocal,
1159                                    frameStackCount,
1160                                    frameStack);
1161                        } else if (frameOffset != -1) {
1162                            mv.visitFrame(frameMode,
1163                                    frameLocalDiff,
1164                                    frameLocal,
1165                                    frameStackCount,
1166                                    frameStack);
1167                        }
1168
1169                        if (frameCount > 0) {
1170                            int tag, delta, n;
1171                            if (zip) {
1172                                tag = b[stackMap++] & 0xFF;
1173                            } else {
1174                                tag = MethodWriter.FULL_FRAME;
1175                                frameOffset = -1;
1176                            }
1177                            frameLocalDiff = 0;
1178                            if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME)
1179                            {
1180                                delta = tag;
1181                                frameMode = Opcodes.F_SAME;
1182                                frameStackCount = 0;
1183                            } else if (tag < MethodWriter.RESERVED) {
1184                                delta = tag
1185                                        - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME;
1186                                stackMap = readFrameType(frameStack,
1187                                        0,
1188                                        stackMap,
1189                                        c,
1190                                        labels);
1191                                frameMode = Opcodes.F_SAME1;
1192                                frameStackCount = 1;
1193                            } else {
1194                                delta = readUnsignedShort(stackMap);
1195                                stackMap += 2;
1196                                if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
1197                                {
1198                                    stackMap = readFrameType(frameStack,
1199                                            0,
1200                                            stackMap,
1201                                            c,
1202                                            labels);
1203                                    frameMode = Opcodes.F_SAME1;
1204                                    frameStackCount = 1;
1205                                } else if (tag >= MethodWriter.CHOP_FRAME
1206                                        && tag < MethodWriter.SAME_FRAME_EXTENDED)
1207                                {
1208                                    frameMode = Opcodes.F_CHOP;
1209                                    frameLocalDiff = MethodWriter.SAME_FRAME_EXTENDED
1210                                            - tag;
1211                                    frameLocalCount -= frameLocalDiff;
1212                                    frameStackCount = 0;
1213                                } else if (tag == MethodWriter.SAME_FRAME_EXTENDED)
1214                                {
1215                                    frameMode = Opcodes.F_SAME;
1216                                    frameStackCount = 0;
1217                                } else if (tag < MethodWriter.FULL_FRAME) {
1218                                    j = unzip ? frameLocalCount : 0;
1219                                    for (k = tag
1220                                            - MethodWriter.SAME_FRAME_EXTENDED; k > 0; k--)
1221                                    {
1222                                        stackMap = readFrameType(frameLocal,
1223                                                j++,
1224                                                stackMap,
1225                                                c,
1226                                                labels);
1227                                    }
1228                                    frameMode = Opcodes.F_APPEND;
1229                                    frameLocalDiff = tag
1230                                            - MethodWriter.SAME_FRAME_EXTENDED;
1231                                    frameLocalCount += frameLocalDiff;
1232                                    frameStackCount = 0;
1233                                } else { // if (tag == FULL_FRAME) {
1234                                    frameMode = Opcodes.F_FULL;
1235                                    n = frameLocalDiff = frameLocalCount = readUnsignedShort(stackMap);
1236                                    stackMap += 2;
1237                                    for (j = 0; n > 0; n--) {
1238                                        stackMap = readFrameType(frameLocal,
1239                                                j++,
1240                                                stackMap,
1241                                                c,
1242                                                labels);
1243                                    }
1244                                    n = frameStackCount = readUnsignedShort(stackMap);
1245                                    stackMap += 2;
1246                                    for (j = 0; n > 0; n--) {
1247                                        stackMap = readFrameType(frameStack,
1248                                                j++,
1249                                                stackMap,
1250                                                c,
1251                                                labels);
1252                                    }
1253                                }
1254                            }
1255                            frameOffset += delta + 1;
1256                            readLabel(frameOffset, labels);
1257
1258                            --frameCount;
1259                        } else {
1260                            frameLocal = null;
1261                        }
1262                    }
1263
1264                    int opcode = b[v] & 0xFF;
1265                    switch (ClassWriter.TYPE[opcode]) {
1266                        case ClassWriter.NOARG_INSN:
1267                            mv.visitInsn(opcode);
1268                            v += 1;
1269                            break;
1270                        case ClassWriter.IMPLVAR_INSN:
1271                            if (opcode > Opcodes.ISTORE) {
1272                                opcode -= 59; // ISTORE_0
1273                                mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),
1274                                        opcode & 0x3);
1275                            } else {
1276                                opcode -= 26; // ILOAD_0
1277                                mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2),
1278                                        opcode & 0x3);
1279                            }
1280                            v += 1;
1281                            break;
1282                        case ClassWriter.LABEL_INSN:
1283                            mv.visitJumpInsn(opcode, labels[w
1284                                    + readShort(v + 1)]);
1285                            v += 3;
1286                            break;
1287                        case ClassWriter.LABELW_INSN:
1288                            mv.visitJumpInsn(opcode - 33, labels[w
1289                                    + readInt(v + 1)]);
1290                            v += 5;
1291                            break;
1292                        case ClassWriter.WIDE_INSN:
1293                            opcode = b[v + 1] & 0xFF;
1294                            if (opcode == Opcodes.IINC) {
1295                                mv.visitIincInsn(readUnsignedShort(v + 2),
1296                                        readShort(v + 4));
1297                                v += 6;
1298                            } else {
1299                                mv.visitVarInsn(opcode,
1300                                        readUnsignedShort(v + 2));
1301                                v += 4;
1302                            }
1303                            break;
1304                        case ClassWriter.TABL_INSN:
1305                            // skips 0 to 3 padding bytes
1306                            v = v + 4 - (w & 3);
1307                            // reads instruction
1308                            label = w + readInt(v);
1309                            int min = readInt(v + 4);
1310                            int max = readInt(v + 8);
1311                            v += 12;
1312                            Label[] table = new Label[max - min + 1];
1313                            for (j = 0; j < table.length; ++j) {
1314                                table[j] = labels[w + readInt(v)];
1315                                v += 4;
1316                            }
1317                            mv.visitTableSwitchInsn(min,
1318                                    max,
1319                                    labels[label],
1320                                    table);
1321                            break;
1322                        case ClassWriter.LOOK_INSN:
1323                            // skips 0 to 3 padding bytes
1324                            v = v + 4 - (w & 3);
1325                            // reads instruction
1326                            label = w + readInt(v);
1327                            j = readInt(v + 4);
1328                            v += 8;
1329                            int[] keys = new int[j];
1330                            Label[] values = new Label[j];
1331                            for (j = 0; j < keys.length; ++j) {
1332                                keys[j] = readInt(v);
1333                                values[j] = labels[w + readInt(v + 4)];
1334                                v += 8;
1335                            }
1336                            mv.visitLookupSwitchInsn(labels[label],
1337                                    keys,
1338                                    values);
1339                            break;
1340                        case ClassWriter.VAR_INSN:
1341                            mv.visitVarInsn(opcode, b[v + 1] & 0xFF);
1342                            v += 2;
1343                            break;
1344                        case ClassWriter.SBYTE_INSN:
1345                            mv.visitIntInsn(opcode, b[v + 1]);
1346                            v += 2;
1347                            break;
1348                        case ClassWriter.SHORT_INSN:
1349                            mv.visitIntInsn(opcode, readShort(v + 1));
1350                            v += 3;
1351                            break;
1352                        case ClassWriter.LDC_INSN:
1353                            mv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c));
1354                            v += 2;
1355                            break;
1356                        case ClassWriter.LDCW_INSN:
1357                            mv.visitLdcInsn(readConst(readUnsignedShort(v + 1),
1358                                    c));
1359                            v += 3;
1360                            break;
1361                        case ClassWriter.FIELDORMETH_INSN:
1362                        case ClassWriter.ITFMETH_INSN:
1363                            int cpIndex = items[readUnsignedShort(v + 1)];
1364                            String iowner = readClass(cpIndex, c);
1365                            cpIndex = items[readUnsignedShort(cpIndex + 2)];
1366                            String iname = readUTF8(cpIndex, c);
1367                            String idesc = readUTF8(cpIndex + 2, c);
1368                            if (opcode < Opcodes.INVOKEVIRTUAL) {
1369                                mv.visitFieldInsn(opcode, iowner, iname, idesc);
1370                            } else {
1371                                mv.visitMethodInsn(opcode, iowner, iname, idesc);
1372                            }
1373                            if (opcode == Opcodes.INVOKEINTERFACE) {
1374                                v += 5;
1375                            } else {
1376                                v += 3;
1377                            }
1378                            break;
1379                        case ClassWriter.TYPE_INSN:
1380                            mv.visitTypeInsn(opcode, readClass(v + 1, c));
1381                            v += 3;
1382                            break;
1383                        case ClassWriter.IINC_INSN:
1384                            mv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]);
1385                            v += 3;
1386                            break;
1387                        // case MANA_INSN:
1388                        default:
1389                            mv.visitMultiANewArrayInsn(readClass(v + 1, c),
1390                                    b[v + 3] & 0xFF);
1391                            v += 4;
1392                            break;
1393                    }
1394                }
1395                l = labels[codeEnd - codeStart];
1396                if (l != null) {
1397                    mv.visitLabel(l);
1398                }
1399                // visits the local variable tables
1400                if (!skipDebug && varTable != 0) {
1401                    int[] typeTable = null;
1402                    if (varTypeTable != 0) {
1403                        k = readUnsignedShort(varTypeTable) * 3;
1404                        w = varTypeTable + 2;
1405                        typeTable = new int[k];
1406                        while (k > 0) {
1407                            typeTable[--k] = w + 6; // signature
1408                            typeTable[--k] = readUnsignedShort(w + 8); // index
1409                            typeTable[--k] = readUnsignedShort(w); // start
1410                            w += 10;
1411                        }
1412                    }
1413                    k = readUnsignedShort(varTable);
1414                    w = varTable + 2;
1415                    for (; k > 0; --k) {
1416                        int start = readUnsignedShort(w);
1417                        int length = readUnsignedShort(w + 2);
1418                        int index = readUnsignedShort(w + 8);
1419                        String vsignature = null;
1420                        if (typeTable != null) {
1421                            for (int a = 0; a < typeTable.length; a += 3) {
1422                                if (typeTable[a] == start
1423                                        && typeTable[a + 1] == index)
1424                                {
1425                                    vsignature = readUTF8(typeTable[a + 2], c);
1426                                    break;
1427                                }
1428                            }
1429                        }
1430                        mv.visitLocalVariable(readUTF8(w + 4, c),
1431                                readUTF8(w + 6, c),
1432                                vsignature,
1433                                labels[start],
1434                                labels[start + length],
1435                                index);
1436                        w += 10;
1437                    }
1438                }
1439                // visits the other attributes
1440                while (cattrs != null) {
1441                    attr = cattrs.next;
1442                    cattrs.next = null;
1443                    mv.visitAttribute(cattrs);
1444                    cattrs = attr;
1445                }
1446                // visits the max stack and max locals values
1447                mv.visitMaxs(maxStack, maxLocals);
1448            }
1449
1450            if (mv != null) {
1451                mv.visitEnd();
1452            }
1453        }
1454
1455        // visits the end of the class
1456        classVisitor.visitEnd();
1457    }
1458
1459    /**
1460     * Reads parameter annotations and makes the given visitor visit them.
1461     *
1462     * @param v start offset in {@link #b b} of the annotations to be read.
1463     * @param desc the method descriptor.
1464     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1465     *        {@link #readClass(int,char[]) readClass} or
1466     *        {@link #readConst readConst}.
1467     * @param visible <tt>true</tt> if the annotations to be read are visible
1468     *        at runtime.
1469     * @param mv the visitor that must visit the annotations.
1470     */
1471    private void readParameterAnnotations(
1472        int v,
1473        final String desc,
1474        final char[] buf,
1475        final boolean visible,
1476        final MethodVisitor mv)
1477    {
1478        int i;
1479        int n = b[v++] & 0xFF;
1480        // workaround for a bug in javac (javac compiler generates a parameter
1481        // annotation array whose size is equal to the number of parameters in
1482        // the Java source file, while it should generate an array whose size is
1483        // equal to the number of parameters in the method descriptor - which
1484        // includes the synthetic parameters added by the compiler). This work-
1485        // around supposes that the synthetic parameters are the first ones.
1486        int synthetics = Type.getArgumentTypes(desc).length - n;
1487        AnnotationVisitor av;
1488        for (i = 0; i < synthetics; ++i) {
1489            // virtual annotation to detect synthetic parameters in MethodWriter
1490            av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false);
1491            if (av != null) {
1492                av.visitEnd();
1493            }
1494        }
1495        for (; i < n + synthetics; ++i) {
1496            int j = readUnsignedShort(v);
1497            v += 2;
1498            for (; j > 0; --j) {
1499                av = mv.visitParameterAnnotation(i, readUTF8(v, buf), visible);
1500                v = readAnnotationValues(v + 2, buf, true, av);
1501            }
1502        }
1503    }
1504
1505    /**
1506     * Reads the values of an annotation and makes the given visitor visit them.
1507     *
1508     * @param v the start offset in {@link #b b} of the values to be read
1509     *        (including the unsigned short that gives the number of values).
1510     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1511     *        {@link #readClass(int,char[]) readClass} or
1512     *        {@link #readConst readConst}.
1513     * @param named if the annotation values are named or not.
1514     * @param av the visitor that must visit the values.
1515     * @return the end offset of the annotation values.
1516     */
1517    private int readAnnotationValues(
1518        int v,
1519        final char[] buf,
1520        final boolean named,
1521        final AnnotationVisitor av)
1522    {
1523        int i = readUnsignedShort(v);
1524        v += 2;
1525        if (named) {
1526            for (; i > 0; --i) {
1527                v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av);
1528            }
1529        } else {
1530            for (; i > 0; --i) {
1531                v = readAnnotationValue(v, buf, null, av);
1532            }
1533        }
1534        if (av != null) {
1535            av.visitEnd();
1536        }
1537        return v;
1538    }
1539
1540    /**
1541     * Reads a value of an annotation and makes the given visitor visit it.
1542     *
1543     * @param v the start offset in {@link #b b} of the value to be read (<i>not
1544     *        including the value name constant pool index</i>).
1545     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1546     *        {@link #readClass(int,char[]) readClass} or
1547     *        {@link #readConst readConst}.
1548     * @param name the name of the value to be read.
1549     * @param av the visitor that must visit the value.
1550     * @return the end offset of the annotation value.
1551     */
1552    private int readAnnotationValue(
1553        int v,
1554        final char[] buf,
1555        final String name,
1556        final AnnotationVisitor av)
1557    {
1558        int i;
1559        if (av == null) {
1560            switch (b[v] & 0xFF) {
1561                case 'e': // enum_const_value
1562                    return v + 5;
1563                case '@': // annotation_value
1564                    return readAnnotationValues(v + 3, buf, true, null);
1565                case '[': // array_value
1566                    return readAnnotationValues(v + 1, buf, false, null);
1567                default:
1568                    return v + 3;
1569            }
1570        }
1571        switch (b[v++] & 0xFF) {
1572            case 'I': // pointer to CONSTANT_Integer
1573            case 'J': // pointer to CONSTANT_Long
1574            case 'F': // pointer to CONSTANT_Float
1575            case 'D': // pointer to CONSTANT_Double
1576                av.visit(name, readConst(readUnsignedShort(v), buf));
1577                v += 2;
1578                break;
1579            case 'B': // pointer to CONSTANT_Byte
1580                av.visit(name,
1581                        new Byte((byte) readInt(items[readUnsignedShort(v)])));
1582                v += 2;
1583                break;
1584            case 'Z': // pointer to CONSTANT_Boolean
1585                av.visit(name, readInt(items[readUnsignedShort(v)]) == 0
1586                        ? Boolean.FALSE
1587                        : Boolean.TRUE);
1588                v += 2;
1589                break;
1590            case 'S': // pointer to CONSTANT_Short
1591                av.visit(name,
1592                        new Short((short) readInt(items[readUnsignedShort(v)])));
1593                v += 2;
1594                break;
1595            case 'C': // pointer to CONSTANT_Char
1596                av.visit(name,
1597                        new Character((char) readInt(items[readUnsignedShort(v)])));
1598                v += 2;
1599                break;
1600            case 's': // pointer to CONSTANT_Utf8
1601                av.visit(name, readUTF8(v, buf));
1602                v += 2;
1603                break;
1604            case 'e': // enum_const_value
1605                av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));
1606                v += 4;
1607                break;
1608            case 'c': // class_info
1609                av.visit(name, Type.getType(readUTF8(v, buf)));
1610                v += 2;
1611                break;
1612            case '@': // annotation_value
1613                v = readAnnotationValues(v + 2,
1614                        buf,
1615                        true,
1616                        av.visitAnnotation(name, readUTF8(v, buf)));
1617                break;
1618            case '[': // array_value
1619                int size = readUnsignedShort(v);
1620                v += 2;
1621                if (size == 0) {
1622                    return readAnnotationValues(v - 2,
1623                            buf,
1624                            false,
1625                            av.visitArray(name));
1626                }
1627                switch (this.b[v++] & 0xFF) {
1628                    case 'B':
1629                        byte[] bv = new byte[size];
1630                        for (i = 0; i < size; i++) {
1631                            bv[i] = (byte) readInt(items[readUnsignedShort(v)]);
1632                            v += 3;
1633                        }
1634                        av.visit(name, bv);
1635                        --v;
1636                        break;
1637                    case 'Z':
1638                        boolean[] zv = new boolean[size];
1639                        for (i = 0; i < size; i++) {
1640                            zv[i] = readInt(items[readUnsignedShort(v)]) != 0;
1641                            v += 3;
1642                        }
1643                        av.visit(name, zv);
1644                        --v;
1645                        break;
1646                    case 'S':
1647                        short[] sv = new short[size];
1648                        for (i = 0; i < size; i++) {
1649                            sv[i] = (short) readInt(items[readUnsignedShort(v)]);
1650                            v += 3;
1651                        }
1652                        av.visit(name, sv);
1653                        --v;
1654                        break;
1655                    case 'C':
1656                        char[] cv = new char[size];
1657                        for (i = 0; i < size; i++) {
1658                            cv[i] = (char) readInt(items[readUnsignedShort(v)]);
1659                            v += 3;
1660                        }
1661                        av.visit(name, cv);
1662                        --v;
1663                        break;
1664                    case 'I':
1665                        int[] iv = new int[size];
1666                        for (i = 0; i < size; i++) {
1667                            iv[i] = readInt(items[readUnsignedShort(v)]);
1668                            v += 3;
1669                        }
1670                        av.visit(name, iv);
1671                        --v;
1672                        break;
1673                    case 'J':
1674                        long[] lv = new long[size];
1675                        for (i = 0; i < size; i++) {
1676                            lv[i] = readLong(items[readUnsignedShort(v)]);
1677                            v += 3;
1678                        }
1679                        av.visit(name, lv);
1680                        --v;
1681                        break;
1682                    case 'F':
1683                        float[] fv = new float[size];
1684                        for (i = 0; i < size; i++) {
1685                            fv[i] = Float.intBitsToFloat(readInt(items[readUnsignedShort(v)]));
1686                            v += 3;
1687                        }
1688                        av.visit(name, fv);
1689                        --v;
1690                        break;
1691                    case 'D':
1692                        double[] dv = new double[size];
1693                        for (i = 0; i < size; i++) {
1694                            dv[i] = Double.longBitsToDouble(readLong(items[readUnsignedShort(v)]));
1695                            v += 3;
1696                        }
1697                        av.visit(name, dv);
1698                        --v;
1699                        break;
1700                    default:
1701                        v = readAnnotationValues(v - 3,
1702                                buf,
1703                                false,
1704                                av.visitArray(name));
1705                }
1706        }
1707        return v;
1708    }
1709
1710    private int readFrameType(
1711        final Object[] frame,
1712        final int index,
1713        int v,
1714        final char[] buf,
1715        final Label[] labels)
1716    {
1717        int type = b[v++] & 0xFF;
1718        switch (type) {
1719            case 0:
1720                frame[index] = Opcodes.TOP;
1721                break;
1722            case 1:
1723                frame[index] = Opcodes.INTEGER;
1724                break;
1725            case 2:
1726                frame[index] = Opcodes.FLOAT;
1727                break;
1728            case 3:
1729                frame[index] = Opcodes.DOUBLE;
1730                break;
1731            case 4:
1732                frame[index] = Opcodes.LONG;
1733                break;
1734            case 5:
1735                frame[index] = Opcodes.NULL;
1736                break;
1737            case 6:
1738                frame[index] = Opcodes.UNINITIALIZED_THIS;
1739                break;
1740            case 7: // Object
1741                frame[index] = readClass(v, buf);
1742                v += 2;
1743                break;
1744            default: // Uninitialized
1745                frame[index] = readLabel(readUnsignedShort(v), labels);
1746                v += 2;
1747        }
1748        return v;
1749    }
1750
1751    /**
1752     * Returns the label corresponding to the given offset. The default
1753     * implementation of this method creates a label for the given offset if it
1754     * has not been already created.
1755     *
1756     * @param offset a bytecode offset in a method.
1757     * @param labels the already created labels, indexed by their offset. If a
1758     *        label already exists for offset this method must not create a new
1759     *        one. Otherwise it must store the new label in this array.
1760     * @return a non null Label, which must be equal to labels[offset].
1761     */
1762    protected Label readLabel(int offset, Label[] labels) {
1763        if (labels[offset] == null) {
1764            labels[offset] = new Label();
1765        }
1766        return labels[offset];
1767    }
1768
1769    /**
1770     * Reads an attribute in {@link #b b}.
1771     *
1772     * @param attrs prototypes of the attributes that must be parsed during the
1773     *        visit of the class. Any attribute whose type is not equal to the
1774     *        type of one the prototypes is ignored (i.e. an empty
1775     *        {@link Attribute} instance is returned).
1776     * @param type the type of the attribute.
1777     * @param off index of the first byte of the attribute's content in
1778     *        {@link #b b}. The 6 attribute header bytes, containing the type
1779     *        and the length of the attribute, are not taken into account here
1780     *        (they have already been read).
1781     * @param len the length of the attribute's content.
1782     * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
1783     *        {@link #readClass(int,char[]) readClass} or
1784     *        {@link #readConst readConst}.
1785     * @param codeOff index of the first byte of code's attribute content in
1786     *        {@link #b b}, or -1 if the attribute to be read is not a code
1787     *        attribute. The 6 attribute header bytes, containing the type and
1788     *        the length of the attribute, are not taken into account here.
1789     * @param labels the labels of the method's code, or <tt>null</tt> if the
1790     *        attribute to be read is not a code attribute.
1791     * @return the attribute that has been read, or <tt>null</tt> to skip this
1792     *         attribute.
1793     */
1794    private Attribute readAttribute(
1795        final Attribute[] attrs,
1796        final String type,
1797        final int off,
1798        final int len,
1799        final char[] buf,
1800        final int codeOff,
1801        final Label[] labels)
1802    {
1803        for (int i = 0; i < attrs.length; ++i) {
1804            if (attrs[i].type.equals(type)) {
1805                return attrs[i].read(this, off, len, buf, codeOff, labels);
1806            }
1807        }
1808        return new Attribute(type).read(this, off, len, null, -1, null);
1809    }
1810
1811    // ------------------------------------------------------------------------
1812    // Utility methods: low level parsing
1813    // ------------------------------------------------------------------------
1814
1815    /**
1816     * Returns the start index of the constant pool item in {@link #b b}, plus
1817     * one. <i>This method is intended for {@link Attribute} sub classes, and is
1818     * normally not needed by class generators or adapters.</i>
1819     *
1820     * @param item the index a constant pool item.
1821     * @return the start index of the constant pool item in {@link #b b}, plus
1822     *         one.
1823     */
1824    public int getItem(final int item) {
1825        return items[item];
1826    }
1827
1828    /**
1829     * Reads a byte value in {@link #b b}. <i>This method is intended for
1830     * {@link Attribute} sub classes, and is normally not needed by class
1831     * generators or adapters.</i>
1832     *
1833     * @param index the start index of the value to be read in {@link #b b}.
1834     * @return the read value.
1835     */
1836    public int readByte(final int index) {
1837        return b[index] & 0xFF;
1838    }
1839
1840    /**
1841     * Reads an unsigned short value in {@link #b b}. <i>This method is
1842     * intended for {@link Attribute} sub classes, and is normally not needed by
1843     * class generators or adapters.</i>
1844     *
1845     * @param index the start index of the value to be read in {@link #b b}.
1846     * @return the read value.
1847     */
1848    public int readUnsignedShort(final int index) {
1849        byte[] b = this.b;
1850        return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
1851    }
1852
1853    /**
1854     * Reads a signed short value in {@link #b b}. <i>This method is intended
1855     * for {@link Attribute} sub classes, and is normally not needed by class
1856     * generators or adapters.</i>
1857     *
1858     * @param index the start index of the value to be read in {@link #b b}.
1859     * @return the read value.
1860     */
1861    public short readShort(final int index) {
1862        byte[] b = this.b;
1863        return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
1864    }
1865
1866    /**
1867     * Reads a signed int value in {@link #b b}. <i>This method is intended for
1868     * {@link Attribute} sub classes, and is normally not needed by class
1869     * generators or adapters.</i>
1870     *
1871     * @param index the start index of the value to be read in {@link #b b}.
1872     * @return the read value.
1873     */
1874    public int readInt(final int index) {
1875        byte[] b = this.b;
1876        return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)
1877                | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
1878    }
1879
1880    /**
1881     * Reads a signed long value in {@link #b b}. <i>This method is intended
1882     * for {@link Attribute} sub classes, and is normally not needed by class
1883     * generators or adapters.</i>
1884     *
1885     * @param index the start index of the value to be read in {@link #b b}.
1886     * @return the read value.
1887     */
1888    public long readLong(final int index) {
1889        long l1 = readInt(index);
1890        long l0 = readInt(index + 4) & 0xFFFFFFFFL;
1891        return (l1 << 32) | l0;
1892    }
1893
1894    /**
1895     * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method
1896     * is intended for {@link Attribute} sub classes, and is normally not needed
1897     * by class generators or adapters.</i>
1898     *
1899     * @param index the start index of an unsigned short value in {@link #b b},
1900     *        whose value is the index of an UTF8 constant pool item.
1901     * @param buf buffer to be used to read the item. This buffer must be
1902     *        sufficiently large. It is not automatically resized.
1903     * @return the String corresponding to the specified UTF8 item.
1904     */
1905    public String readUTF8(int index, final char[] buf) {
1906        int item = readUnsignedShort(index);
1907        String s = strings[item];
1908        if (s != null) {
1909            return s;
1910        }
1911        index = items[item];
1912        return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf);
1913    }
1914
1915    /**
1916     * Reads UTF8 string in {@link #b b}.
1917     *
1918     * @param index start offset of the UTF8 string to be read.
1919     * @param utfLen length of the UTF8 string to be read.
1920     * @param buf buffer to be used to read the string. This buffer must be
1921     *        sufficiently large. It is not automatically resized.
1922     * @return the String corresponding to the specified UTF8 string.
1923     */
1924    private String readUTF(int index, final int utfLen, final char[] buf) {
1925        int endIndex = index + utfLen;
1926        byte[] b = this.b;
1927        int strLen = 0;
1928        int c, d, e;
1929        while (index < endIndex) {
1930            c = b[index++] & 0xFF;
1931            switch (c >> 4) {
1932                case 0:
1933                case 1:
1934                case 2:
1935                case 3:
1936                case 4:
1937                case 5:
1938                case 6:
1939                case 7:
1940                    // 0xxxxxxx
1941                    buf[strLen++] = (char) c;
1942                    break;
1943                case 12:
1944                case 13:
1945                    // 110x xxxx 10xx xxxx
1946                    d = b[index++];
1947                    buf[strLen++] = (char) (((c & 0x1F) << 6) | (d & 0x3F));
1948                    break;
1949                default:
1950                    // 1110 xxxx 10xx xxxx 10xx xxxx
1951                    d = b[index++];
1952                    e = b[index++];
1953                    buf[strLen++] = (char) (((c & 0x0F) << 12)
1954                            | ((d & 0x3F) << 6) | (e & 0x3F));
1955                    break;
1956            }
1957        }
1958        return new String(buf, 0, strLen);
1959    }
1960
1961    /**
1962     * Reads a class constant pool item in {@link #b b}. <i>This method is
1963     * intended for {@link Attribute} sub classes, and is normally not needed by
1964     * class generators or adapters.</i>
1965     *
1966     * @param index the start index of an unsigned short value in {@link #b b},
1967     *        whose value is the index of a class constant pool item.
1968     * @param buf buffer to be used to read the item. This buffer must be
1969     *        sufficiently large. It is not automatically resized.
1970     * @return the String corresponding to the specified class item.
1971     */
1972    public String readClass(final int index, final char[] buf) {
1973        // computes the start index of the CONSTANT_Class item in b
1974        // and reads the CONSTANT_Utf8 item designated by
1975        // the first two bytes of this CONSTANT_Class item
1976        return readUTF8(items[readUnsignedShort(index)], buf);
1977    }
1978
1979    /**
1980     * Reads a numeric or string constant pool item in {@link #b b}. <i>This
1981     * method is intended for {@link Attribute} sub classes, and is normally not
1982     * needed by class generators or adapters.</i>
1983     *
1984     * @param item the index of a constant pool item.
1985     * @param buf buffer to be used to read the item. This buffer must be
1986     *        sufficiently large. It is not automatically resized.
1987     * @return the {@link Integer}, {@link Float}, {@link Long},
1988     *         {@link Double}, {@link String} or {@link Type} corresponding to
1989     *         the given constant pool item.
1990     */
1991    public Object readConst(final int item, final char[] buf) {
1992        int index = items[item];
1993        switch (b[index - 1]) {
1994            case ClassWriter.INT:
1995                return new Integer(readInt(index));
1996            case ClassWriter.FLOAT:
1997                return new Float(Float.intBitsToFloat(readInt(index)));
1998            case ClassWriter.LONG:
1999                return new Long(readLong(index));
2000            case ClassWriter.DOUBLE:
2001                return new Double(Double.longBitsToDouble(readLong(index)));
2002            case ClassWriter.CLASS:
2003                return Type.getObjectType(readUTF8(index, buf));
2004                // case ClassWriter.STR:
2005            default:
2006                return readUTF8(index, buf);
2007        }
2008    }
2009}
2010