Home | History | Annotate | Download | only in asm
      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  */
     30 package org.mockito.asm;
     31 
     32 import java.io.InputStream;
     33 import 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  */
     44 public 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