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