view src/clojure/asm/ClassReader.java @ 10:ef7dbbd6452c

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