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