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