56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
57 * THE POSSIBILITY OF SUCH DAMAGE.
58 */
59 package jdk.internal.org.objectweb.asm;
60
61 import java.io.IOException;
62 import java.io.InputStream;
63
64 /**
65 * A Java class parser to make a {@link ClassVisitor} visit an existing class.
66 * This class parses a byte array conforming to the Java class file format and
67 * calls the appropriate visit methods of a given class visitor for each field,
68 * method and bytecode instruction encountered.
69 *
70 * @author Eric Bruneton
71 * @author Eugene Kuleshov
72 */
73 public class ClassReader {
74
75 /**
76 * True to enable signatures support.
77 */
78 static final boolean SIGNATURES = true;
79
80 /**
81 * True to enable annotations support.
82 */
83 static final boolean ANNOTATIONS = true;
84
85 /**
86 * True to enable stack map frames support.
87 */
88 static final boolean FRAMES = true;
89
90 /**
91 * True to enable bytecode writing support.
92 */
93 static final boolean WRITER = true;
94
95 /**
96 * True to enable JSR_W and GOTO_W support.
97 */
98 static final boolean RESIZE = true;
99
100 /**
101 * Flag to skip method code. If this class is set <code>CODE</code>
102 * attribute won't be visited. This can be used, for example, to retrieve
103 * annotations for methods and method parameters.
104 */
105 public static final int SKIP_CODE = 1;
106
107 /**
108 * Flag to skip the debug information in the class. If this flag is set the
109 * debug information of the class is not visited, i.e. the
110 * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
111 * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be
112 * called.
113 */
114 public static final int SKIP_DEBUG = 2;
115
116 /**
117 * Flag to skip the stack map frames in the class. If this flag is set the
118 * stack map frames of the class is not visited, i.e. the
119 * {@link MethodVisitor#visitFrame visitFrame} method will not be called.
120 * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is
121 * used: it avoids visiting frames that will be ignored and recomputed from
122 * scratch in the class writer.
123 */
124 public static final int SKIP_FRAMES = 4;
125
126 /**
127 * Flag to expand the stack map frames. By default stack map frames are
128 * visited in their original format (i.e. "expanded" for classes whose
129 * version is less than V1_6, and "compressed" for the other classes). If
130 * this flag is set, stack map frames are always visited in expanded format
131 * (this option adds a decompression/recompression step in ClassReader and
132 * ClassWriter which degrades performances quite a lot).
133 */
134 public static final int EXPAND_FRAMES = 8;
135
136 /**
137 * The class to be parsed. <i>The content of this array must not be
138 * modified. This field is intended for {@link Attribute} sub classes, and
139 * is normally not needed by class generators or adapters.</i>
140 */
141 public final byte[] b;
142
143 /**
144 * The start index of each constant pool item in {@link #b b}, plus one. The
145 * one byte offset skips the constant pool item tag that indicates its type.
146 */
147 private final int[] items;
148
149 /**
150 * The String objects corresponding to the CONSTANT_Utf8 items. This cache
151 * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
152 * which GREATLY improves performances (by a factor 2 to 3). This caching
153 * strategy could be extended to all constant pool items, but its benefit
154 * would not be so great for these items (because they are much less
155 * expensive to parse than CONSTANT_Utf8 items).
156 */
178 * @param b
179 * the bytecode of the class to be read.
180 */
181 public ClassReader(final byte[] b) {
182 this(b, 0, b.length);
183 }
184
185 /**
186 * Constructs a new {@link ClassReader} object.
187 *
188 * @param b
189 * the bytecode of the class to be read.
190 * @param off
191 * the start offset of the class data.
192 * @param len
193 * the length of the class data.
194 */
195 public ClassReader(final byte[] b, final int off, final int len) {
196 this.b = b;
197 // checks the class version
198 if (readShort(off + 6) > Opcodes.V1_9) {
199 throw new IllegalArgumentException();
200 }
201 // parses the constant pool
202 items = new int[readUnsignedShort(off + 8)];
203 int n = items.length;
204 strings = new String[n];
205 int max = 0;
206 int index = off + 10;
207 for (int i = 1; i < n; ++i) {
208 items[i] = index + 1;
209 int size;
210 switch (b[index]) {
211 case ClassWriter.FIELD:
212 case ClassWriter.METH:
213 case ClassWriter.IMETH:
214 case ClassWriter.INT:
215 case ClassWriter.FLOAT:
216 case ClassWriter.NAME_TYPE:
217 case ClassWriter.INDY:
218 size = 5;
219 break;
220 case ClassWriter.LONG:
221 case ClassWriter.DOUBLE:
222 size = 9;
223 ++i;
224 break;
225 case ClassWriter.UTF8:
226 size = 3 + readUnsignedShort(index + 1);
227 if (size > max) {
228 max = size;
229 }
230 break;
231 case ClassWriter.HANDLE:
232 size = 4;
233 break;
234 // case ClassWriter.CLASS:
235 // case ClassWriter.STR:
236 // case ClassWriter.MTYPE
237 default:
238 size = 3;
239 break;
240 }
241 index += size;
242 }
243 maxStringLength = max;
244 // the class header information starts just after the constant pool
245 header = index;
246 }
247
248 /**
249 * Returns the class's access flags (see {@link Opcodes}). This value may
250 * not reflect Deprecated and Synthetic flags when bytecode is before 1.5
251 * and those flags are represented by attributes.
252 *
253 * @return the class access flags
254 *
255 * @see ClassVisitor#visit(int, int, String, String, String, String[])
256 */
360 break;
361 }
362 case ClassWriter.HANDLE: {
363 int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
364 nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
365 item.set(ClassWriter.HANDLE_BASE + readByte(index),
366 readClass(fieldOrMethodRef, buf),
367 readUTF8(nameType, buf), readUTF8(nameType + 2, buf));
368 break;
369 }
370 case ClassWriter.INDY:
371 if (classWriter.bootstrapMethods == null) {
372 copyBootstrapMethods(classWriter, items2, buf);
373 }
374 nameType = items[readUnsignedShort(index + 2)];
375 item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf),
376 readUnsignedShort(index));
377 break;
378 // case ClassWriter.STR:
379 // case ClassWriter.CLASS:
380 // case ClassWriter.MTYPE
381 default:
382 item.set(tag, readUTF8(index, buf), null, null);
383 break;
384 }
385
386 int index2 = item.hashCode % items2.length;
387 item.next = items2[index2];
388 items2[index2] = item;
389 }
390
391 int off = items[1] - 1;
392 classWriter.pool.putByteArray(b, off, header - off);
393 classWriter.items = items2;
394 classWriter.threshold = (int) (0.75d * ll);
395 classWriter.index = ll;
396 }
397
398 /**
399 * Copies the bootstrap method data into the given {@link ClassWriter}.
400 * Should be called before the {@link #accept(ClassVisitor,int)} method.
567 context.buffer = c;
568
569 // reads the class declaration
570 int access = readUnsignedShort(u);
571 String name = readClass(u + 2, c);
572 String superClass = readClass(u + 4, c);
573 String[] interfaces = new String[readUnsignedShort(u + 6)];
574 u += 8;
575 for (int i = 0; i < interfaces.length; ++i) {
576 interfaces[i] = readClass(u, c);
577 u += 2;
578 }
579
580 // reads the class attributes
581 String signature = null;
582 String sourceFile = null;
583 String sourceDebug = null;
584 String enclosingOwner = null;
585 String enclosingName = null;
586 String enclosingDesc = null;
587 int anns = 0;
588 int ianns = 0;
589 int tanns = 0;
590 int itanns = 0;
591 int innerClasses = 0;
592 Attribute attributes = null;
593
594 u = getAttributes();
595 for (int i = readUnsignedShort(u); i > 0; --i) {
596 String attrName = readUTF8(u + 2, c);
597 // tests are sorted in decreasing frequency order
598 // (based on frequencies observed on typical classes)
599 if ("SourceFile".equals(attrName)) {
600 sourceFile = readUTF8(u + 8, c);
601 } else if ("InnerClasses".equals(attrName)) {
602 innerClasses = u + 8;
603 } else if ("EnclosingMethod".equals(attrName)) {
604 enclosingOwner = readClass(u + 8, c);
605 int item = readUnsignedShort(u + 10);
606 if (item != 0) {
607 enclosingName = readUTF8(items[item], c);
608 enclosingDesc = readUTF8(items[item] + 2, c);
609 }
610 } else if (SIGNATURES && "Signature".equals(attrName)) {
611 signature = readUTF8(u + 8, c);
612 } else if (ANNOTATIONS
613 && "RuntimeVisibleAnnotations".equals(attrName)) {
614 anns = u + 8;
615 } else if (ANNOTATIONS
616 && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
617 tanns = u + 8;
618 } else if ("Deprecated".equals(attrName)) {
619 access |= Opcodes.ACC_DEPRECATED;
620 } else if ("Synthetic".equals(attrName)) {
621 access |= Opcodes.ACC_SYNTHETIC
622 | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
623 } else if ("SourceDebugExtension".equals(attrName)) {
624 int len = readInt(u + 4);
625 sourceDebug = readUTF(u + 8, len, new char[len]);
626 } else if (ANNOTATIONS
627 && "RuntimeInvisibleAnnotations".equals(attrName)) {
628 ianns = u + 8;
629 } else if (ANNOTATIONS
630 && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
631 itanns = u + 8;
632 } else if ("BootstrapMethods".equals(attrName)) {
633 int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
634 for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
635 bootstrapMethods[j] = v;
636 v += 2 + readUnsignedShort(v + 2) << 1;
637 }
638 context.bootstrapMethods = bootstrapMethods;
639 } else {
640 Attribute attr = readAttribute(attrs, attrName, u + 8,
641 readInt(u + 4), c, -1, null);
642 if (attr != null) {
643 attr.next = attributes;
644 attributes = attr;
645 }
646 }
647 u += 6 + readInt(u + 4);
648 }
649
650 // visits the class declaration
651 classVisitor.visit(readInt(items[1] - 7), access, name, signature,
652 superClass, interfaces);
653
654 // visits the source and debug info
655 if ((flags & SKIP_DEBUG) == 0
656 && (sourceFile != null || sourceDebug != null)) {
657 classVisitor.visitSource(sourceFile, sourceDebug);
658 }
659
660 // visits the outer class
661 if (enclosingOwner != null) {
662 classVisitor.visitOuterClass(enclosingOwner, enclosingName,
663 enclosingDesc);
664 }
665
666 // visits the class annotations and type annotations
667 if (ANNOTATIONS && anns != 0) {
668 for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
669 v = readAnnotationValues(v + 2, c, true,
670 classVisitor.visitAnnotation(readUTF8(v, c), true));
671 }
672 }
673 if (ANNOTATIONS && ianns != 0) {
674 for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
675 v = readAnnotationValues(v + 2, c, true,
676 classVisitor.visitAnnotation(readUTF8(v, c), false));
677 }
678 }
679 if (ANNOTATIONS && tanns != 0) {
680 for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
681 v = readAnnotationTarget(context, v);
682 v = readAnnotationValues(v + 2, c, true,
683 classVisitor.visitTypeAnnotation(context.typeRef,
684 context.typePath, readUTF8(v, c), true));
685 }
686 }
687 if (ANNOTATIONS && itanns != 0) {
688 for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
689 v = readAnnotationTarget(context, v);
690 v = readAnnotationValues(v + 2, c, true,
691 classVisitor.visitTypeAnnotation(context.typeRef,
692 context.typePath, readUTF8(v, c), false));
693 }
694 }
695
696 // visits the attributes
697 while (attributes != null) {
698 Attribute attr = attributes.next;
699 attributes.next = null;
700 classVisitor.visitAttribute(attributes);
701 attributes = attr;
702 }
703
704 // visits the inner classes
705 if (innerClasses != 0) {
706 int v = innerClasses + 2;
707 for (int i = readUnsignedShort(innerClasses); i > 0; --i) {
710 readUnsignedShort(v + 6));
711 v += 8;
712 }
713 }
714
715 // visits the fields and methods
716 u = header + 10 + 2 * interfaces.length;
717 for (int i = readUnsignedShort(u - 2); i > 0; --i) {
718 u = readField(classVisitor, context, u);
719 }
720 u += 2;
721 for (int i = readUnsignedShort(u - 2); i > 0; --i) {
722 u = readMethod(classVisitor, context, u);
723 }
724
725 // visits the end of the class
726 classVisitor.visitEnd();
727 }
728
729 /**
730 * Reads a field and makes the given visitor visit it.
731 *
732 * @param classVisitor
733 * the visitor that must visit the field.
734 * @param context
735 * information about the class being parsed.
736 * @param u
737 * the start offset of the field in the class file.
738 * @return the offset of the first byte following the field in the class.
739 */
740 private int readField(final ClassVisitor classVisitor,
741 final Context context, int u) {
742 // reads the field declaration
743 char[] c = context.buffer;
744 int access = readUnsignedShort(u);
745 String name = readUTF8(u + 2, c);
746 String desc = readUTF8(u + 4, c);
747 u += 6;
748
749 // reads the field attributes
750 String signature = null;
751 int anns = 0;
752 int ianns = 0;
753 int tanns = 0;
754 int itanns = 0;
755 Object value = null;
756 Attribute attributes = null;
757
758 for (int i = readUnsignedShort(u); i > 0; --i) {
759 String attrName = readUTF8(u + 2, c);
760 // tests are sorted in decreasing frequency order
761 // (based on frequencies observed on typical classes)
762 if ("ConstantValue".equals(attrName)) {
763 int item = readUnsignedShort(u + 8);
764 value = item == 0 ? null : readConst(item, c);
765 } else if (SIGNATURES && "Signature".equals(attrName)) {
766 signature = readUTF8(u + 8, c);
767 } else if ("Deprecated".equals(attrName)) {
768 access |= Opcodes.ACC_DEPRECATED;
769 } else if ("Synthetic".equals(attrName)) {
770 access |= Opcodes.ACC_SYNTHETIC
771 | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
772 } else if (ANNOTATIONS
773 && "RuntimeVisibleAnnotations".equals(attrName)) {
774 anns = u + 8;
775 } else if (ANNOTATIONS
776 && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
777 tanns = u + 8;
778 } else if (ANNOTATIONS
779 && "RuntimeInvisibleAnnotations".equals(attrName)) {
780 ianns = u + 8;
781 } else if (ANNOTATIONS
782 && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
783 itanns = u + 8;
784 } else {
785 Attribute attr = readAttribute(context.attrs, attrName, u + 8,
786 readInt(u + 4), c, -1, null);
787 if (attr != null) {
788 attr.next = attributes;
789 attributes = attr;
790 }
791 }
792 u += 6 + readInt(u + 4);
793 }
794 u += 2;
795
796 // visits the field declaration
797 FieldVisitor fv = classVisitor.visitField(access, name, desc,
798 signature, value);
799 if (fv == null) {
800 return u;
801 }
802
803 // visits the field annotations and type annotations
804 if (ANNOTATIONS && anns != 0) {
805 for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
806 v = readAnnotationValues(v + 2, c, true,
807 fv.visitAnnotation(readUTF8(v, c), true));
808 }
809 }
810 if (ANNOTATIONS && ianns != 0) {
811 for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
812 v = readAnnotationValues(v + 2, c, true,
813 fv.visitAnnotation(readUTF8(v, c), false));
814 }
815 }
816 if (ANNOTATIONS && tanns != 0) {
817 for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
818 v = readAnnotationTarget(context, v);
819 v = readAnnotationValues(v + 2, c, true,
820 fv.visitTypeAnnotation(context.typeRef,
821 context.typePath, readUTF8(v, c), true));
822 }
823 }
824 if (ANNOTATIONS && itanns != 0) {
825 for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
826 v = readAnnotationTarget(context, v);
827 v = readAnnotationValues(v + 2, c, true,
828 fv.visitTypeAnnotation(context.typeRef,
829 context.typePath, readUTF8(v, c), false));
830 }
831 }
832
833 // visits the field attributes
834 while (attributes != null) {
835 Attribute attr = attributes.next;
836 attributes.next = null;
837 fv.visitAttribute(attributes);
838 attributes = attr;
839 }
840
841 // visits the end of the field
842 fv.visitEnd();
843
844 return u;
878 int mpanns = 0;
879 int impanns = 0;
880 int firstAttribute = u;
881 Attribute attributes = null;
882
883 for (int i = readUnsignedShort(u); i > 0; --i) {
884 String attrName = readUTF8(u + 2, c);
885 // tests are sorted in decreasing frequency order
886 // (based on frequencies observed on typical classes)
887 if ("Code".equals(attrName)) {
888 if ((context.flags & SKIP_CODE) == 0) {
889 code = u + 8;
890 }
891 } else if ("Exceptions".equals(attrName)) {
892 exceptions = new String[readUnsignedShort(u + 8)];
893 exception = u + 10;
894 for (int j = 0; j < exceptions.length; ++j) {
895 exceptions[j] = readClass(exception, c);
896 exception += 2;
897 }
898 } else if (SIGNATURES && "Signature".equals(attrName)) {
899 signature = readUTF8(u + 8, c);
900 } else if ("Deprecated".equals(attrName)) {
901 context.access |= Opcodes.ACC_DEPRECATED;
902 } else if (ANNOTATIONS
903 && "RuntimeVisibleAnnotations".equals(attrName)) {
904 anns = u + 8;
905 } else if (ANNOTATIONS
906 && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
907 tanns = u + 8;
908 } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
909 dann = u + 8;
910 } else if ("Synthetic".equals(attrName)) {
911 context.access |= Opcodes.ACC_SYNTHETIC
912 | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
913 } else if (ANNOTATIONS
914 && "RuntimeInvisibleAnnotations".equals(attrName)) {
915 ianns = u + 8;
916 } else if (ANNOTATIONS
917 && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
918 itanns = u + 8;
919 } else if (ANNOTATIONS
920 && "RuntimeVisibleParameterAnnotations".equals(attrName)) {
921 mpanns = u + 8;
922 } else if (ANNOTATIONS
923 && "RuntimeInvisibleParameterAnnotations".equals(attrName)) {
924 impanns = u + 8;
925 } else if ("MethodParameters".equals(attrName)) {
926 methodParameters = u + 8;
927 } else {
928 Attribute attr = readAttribute(context.attrs, attrName, u + 8,
929 readInt(u + 4), c, -1, null);
930 if (attr != null) {
931 attr.next = attributes;
932 attributes = attr;
933 }
934 }
935 u += 6 + readInt(u + 4);
936 }
937 u += 2;
938
939 // visits the method declaration
940 MethodVisitor mv = classVisitor.visitMethod(context.access,
941 context.name, context.desc, signature, exceptions);
942 if (mv == null) {
943 return u;
944 }
945
946 /*
947 * if the returned MethodVisitor is in fact a MethodWriter, it means
948 * there is no method adapter between the reader and the writer. If, in
949 * addition, the writer's constant pool was copied from this reader
950 * (mw.cw.cr == this), and the signature and exceptions of the method
951 * have not been changed, then it is possible to skip all visit events
952 * and just copy the original code of the method to the writer (the
953 * access, name and descriptor can have been changed, this is not
954 * important since they are not copied as is from the reader).
955 */
956 if (WRITER && mv instanceof MethodWriter) {
957 MethodWriter mw = (MethodWriter) mv;
958 if (mw.cw.cr == this && signature == mw.signature) {
959 boolean sameExceptions = false;
960 if (exceptions == null) {
961 sameExceptions = mw.exceptionCount == 0;
962 } else if (exceptions.length == mw.exceptionCount) {
963 sameExceptions = true;
964 for (int j = exceptions.length - 1; j >= 0; --j) {
965 exception -= 2;
966 if (mw.exceptions[j] != readUnsignedShort(exception)) {
967 sameExceptions = false;
968 break;
969 }
970 }
971 }
972 if (sameExceptions) {
973 /*
974 * we do not copy directly the code into MethodWriter to
975 * save a byte array copy operation. The real copy will be
976 * done in ClassWriter.toByteArray().
977 */
978 mw.classReaderOffset = firstAttribute;
979 mw.classReaderLength = u - firstAttribute;
980 return u;
981 }
982 }
983 }
984
985 // visit the method parameters
986 if (methodParameters != 0) {
987 for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) {
988 mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2));
989 }
990 }
991
992 // visits the method annotations
993 if (ANNOTATIONS && dann != 0) {
994 AnnotationVisitor dv = mv.visitAnnotationDefault();
995 readAnnotationValue(dann, c, null, dv);
996 if (dv != null) {
997 dv.visitEnd();
998 }
999 }
1000 if (ANNOTATIONS && anns != 0) {
1001 for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
1002 v = readAnnotationValues(v + 2, c, true,
1003 mv.visitAnnotation(readUTF8(v, c), true));
1004 }
1005 }
1006 if (ANNOTATIONS && ianns != 0) {
1007 for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
1008 v = readAnnotationValues(v + 2, c, true,
1009 mv.visitAnnotation(readUTF8(v, c), false));
1010 }
1011 }
1012 if (ANNOTATIONS && tanns != 0) {
1013 for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
1014 v = readAnnotationTarget(context, v);
1015 v = readAnnotationValues(v + 2, c, true,
1016 mv.visitTypeAnnotation(context.typeRef,
1017 context.typePath, readUTF8(v, c), true));
1018 }
1019 }
1020 if (ANNOTATIONS && itanns != 0) {
1021 for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
1022 v = readAnnotationTarget(context, v);
1023 v = readAnnotationValues(v + 2, c, true,
1024 mv.visitTypeAnnotation(context.typeRef,
1025 context.typePath, readUTF8(v, c), false));
1026 }
1027 }
1028 if (ANNOTATIONS && mpanns != 0) {
1029 readParameterAnnotations(mv, context, mpanns, true);
1030 }
1031 if (ANNOTATIONS && impanns != 0) {
1032 readParameterAnnotations(mv, context, impanns, false);
1033 }
1034
1035 // visits the method attributes
1036 while (attributes != null) {
1037 Attribute attr = attributes.next;
1038 attributes.next = null;
1039 mv.visitAttribute(attributes);
1040 attributes = attr;
1041 }
1042
1043 // visits the method code
1044 if (code != 0) {
1045 mv.visitCode();
1046 readCode(mv, context, code);
1047 }
1048
1049 // visits the end of the method
1050 mv.visitEnd();
1051
1058 * @param mv
1059 * the visitor that must visit the method's code.
1060 * @param context
1061 * information about the class being parsed.
1062 * @param u
1063 * the start offset of the code attribute in the class file.
1064 */
1065 private void readCode(final MethodVisitor mv, final Context context, int u) {
1066 // reads the header
1067 byte[] b = this.b;
1068 char[] c = context.buffer;
1069 int maxStack = readUnsignedShort(u);
1070 int maxLocals = readUnsignedShort(u + 2);
1071 int codeLength = readInt(u + 4);
1072 u += 8;
1073
1074 // reads the bytecode to find the labels
1075 int codeStart = u;
1076 int codeEnd = u + codeLength;
1077 Label[] labels = context.labels = new Label[codeLength + 2];
1078 readLabel(codeLength + 1, labels);
1079 while (u < codeEnd) {
1080 int offset = u - codeStart;
1081 int opcode = b[u] & 0xFF;
1082 switch (ClassWriter.TYPE[opcode]) {
1083 case ClassWriter.NOARG_INSN:
1084 case ClassWriter.IMPLVAR_INSN:
1085 u += 1;
1086 break;
1087 case ClassWriter.LABEL_INSN:
1088 readLabel(offset + readShort(u + 1), labels);
1089 u += 3;
1090 break;
1091 case ClassWriter.LABELW_INSN:
1092 readLabel(offset + readInt(u + 1), labels);
1093 u += 5;
1094 break;
1095 case ClassWriter.WIDE_INSN:
1096 opcode = b[u + 1] & 0xFF;
1097 if (opcode == Opcodes.IINC) {
1098 u += 6;
1099 } else {
1100 u += 4;
1101 }
1102 break;
1103 case ClassWriter.TABL_INSN:
1104 // skips 0 to 3 padding bytes
1105 u = u + 4 - (offset & 3);
1106 // reads instruction
1107 readLabel(offset + readInt(u), labels);
1108 for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) {
1109 readLabel(offset + readInt(u + 12), labels);
1110 u += 4;
1111 }
1112 u += 12;
1113 break;
1114 case ClassWriter.LOOK_INSN:
1115 // skips 0 to 3 padding bytes
1116 u = u + 4 - (offset & 3);
1117 // reads instruction
1118 readLabel(offset + readInt(u), labels);
1119 for (int i = readInt(u + 4); i > 0; --i) {
1120 readLabel(offset + readInt(u + 12), labels);
1121 u += 8;
1122 }
1123 u += 8;
1124 break;
1125 case ClassWriter.VAR_INSN:
1126 case ClassWriter.SBYTE_INSN:
1127 case ClassWriter.LDC_INSN:
1128 u += 2;
1129 break;
1130 case ClassWriter.SHORT_INSN:
1131 case ClassWriter.LDCW_INSN:
1132 case ClassWriter.FIELDORMETH_INSN:
1133 case ClassWriter.TYPE_INSN:
1134 case ClassWriter.IINC_INSN:
1135 u += 3;
1136 break;
1137 case ClassWriter.ITFMETH_INSN:
1138 case ClassWriter.INDYMETH_INSN:
1139 u += 5;
1140 break;
1141 // case MANA_INSN:
1142 default:
1143 u += 4;
1144 break;
1145 }
1146 }
1147
1148 // reads the try catch entries to find the labels, and also visits them
1149 for (int i = readUnsignedShort(u); i > 0; --i) {
1150 Label start = readLabel(readUnsignedShort(u + 2), labels);
1151 Label end = readLabel(readUnsignedShort(u + 4), labels);
1152 Label handler = readLabel(readUnsignedShort(u + 6), labels);
1153 String type = readUTF8(items[readUnsignedShort(u + 8)], c);
1154 mv.visitTryCatchBlock(start, end, handler, type);
1155 u += 8;
1156 }
1157 u += 2;
1158
1159 // reads the code attributes
1160 int[] tanns = null; // start index of each visible type annotation
1161 int[] itanns = null; // start index of each invisible type annotation
1162 int tann = 0; // current index in tanns array
1163 int itann = 0; // current index in itanns array
1164 int ntoff = -1; // next visible type annotation code offset
1165 int nitoff = -1; // next invisible type annotation code offset
1166 int varTable = 0;
1167 int varTypeTable = 0;
1168 boolean zip = true;
1169 boolean unzip = (context.flags & EXPAND_FRAMES) != 0;
1170 int stackMap = 0;
1171 int stackMapSize = 0;
1172 int frameCount = 0;
1173 Context frame = null;
1174 Attribute attributes = null;
1175
1176 for (int i = readUnsignedShort(u); i > 0; --i) {
1177 String attrName = readUTF8(u + 2, c);
1178 if ("LocalVariableTable".equals(attrName)) {
1179 if ((context.flags & SKIP_DEBUG) == 0) {
1180 varTable = u + 8;
1181 for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
1182 int label = readUnsignedShort(v + 10);
1183 if (labels[label] == null) {
1184 readLabel(label, labels).status |= Label.DEBUG;
1185 }
1186 label += readUnsignedShort(v + 12);
1187 if (labels[label] == null) {
1188 readLabel(label, labels).status |= Label.DEBUG;
1189 }
1190 v += 10;
1191 }
1192 }
1193 } else if ("LocalVariableTypeTable".equals(attrName)) {
1194 varTypeTable = u + 8;
1195 } else if ("LineNumberTable".equals(attrName)) {
1196 if ((context.flags & SKIP_DEBUG) == 0) {
1197 for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
1198 int label = readUnsignedShort(v + 10);
1199 if (labels[label] == null) {
1200 readLabel(label, labels).status |= Label.DEBUG;
1201 }
1202 Label l = labels[label];
1203 while (l.line > 0) {
1204 if (l.next == null) {
1205 l.next = new Label();
1206 }
1207 l = l.next;
1208 }
1209 l.line = readUnsignedShort(v + 12);
1210 v += 4;
1211 }
1212 }
1213 } else if (ANNOTATIONS
1214 && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
1215 tanns = readTypeAnnotations(mv, context, u + 8, true);
1216 ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1
1217 : readUnsignedShort(tanns[0] + 1);
1218 } else if (ANNOTATIONS
1219 && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
1220 itanns = readTypeAnnotations(mv, context, u + 8, false);
1221 nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1
1222 : readUnsignedShort(itanns[0] + 1);
1223 } else if (FRAMES && "StackMapTable".equals(attrName)) {
1224 if ((context.flags & SKIP_FRAMES) == 0) {
1225 stackMap = u + 10;
1226 stackMapSize = readInt(u + 4);
1227 frameCount = readUnsignedShort(u + 8);
1228 }
1229 /*
1230 * here we do not extract the labels corresponding to the
1231 * attribute content. This would require a full parsing of the
1232 * attribute, which would need to be repeated in the second
1233 * phase (see below). Instead the content of the attribute is
1234 * read one frame at a time (i.e. after a frame has been
1235 * visited, the next frame is read), and the labels it contains
1236 * are also extracted one frame at a time. Thanks to the
1237 * ordering of frames, having only a "one frame lookahead" is
1238 * not a problem, i.e. it is not possible to see an offset
1239 * smaller than the offset of the current insn and for which no
1240 * Label exist.
1241 */
1242 /*
1243 * This is not true for UNINITIALIZED type offsets. We solve
1244 * this by parsing the stack map table without a full decoding
1245 * (see below).
1246 */
1247 } else if (FRAMES && "StackMap".equals(attrName)) {
1248 if ((context.flags & SKIP_FRAMES) == 0) {
1249 zip = false;
1250 stackMap = u + 10;
1251 stackMapSize = readInt(u + 4);
1252 frameCount = readUnsignedShort(u + 8);
1253 }
1254 /*
1255 * IMPORTANT! here we assume that the frames are ordered, as in
1256 * the StackMapTable attribute, although this is not guaranteed
1257 * by the attribute format.
1258 */
1259 } else {
1260 for (int j = 0; j < context.attrs.length; ++j) {
1261 if (context.attrs[j].type.equals(attrName)) {
1262 Attribute attr = context.attrs[j].read(this, u + 8,
1263 readInt(u + 4), c, codeStart - 8, labels);
1264 if (attr != null) {
1265 attr.next = attributes;
1266 attributes = attr;
1267 }
1268 }
1269 }
1270 }
1271 u += 6 + readInt(u + 4);
1272 }
1273 u += 2;
1274
1275 // generates the first (implicit) stack map frame
1276 if (FRAMES && stackMap != 0) {
1277 /*
1278 * for the first explicit frame the offset is not offset_delta + 1
1279 * but only offset_delta; setting the implicit frame offset to -1
1280 * allow the use of the "offset_delta + 1" rule in all cases
1281 */
1282 frame = context;
1283 frame.offset = -1;
1284 frame.mode = 0;
1285 frame.localCount = 0;
1286 frame.localDiff = 0;
1287 frame.stackCount = 0;
1288 frame.local = new Object[maxLocals];
1289 frame.stack = new Object[maxStack];
1290 if (unzip) {
1291 getImplicitFrame(context);
1292 }
1293 /*
1294 * Finds labels for UNINITIALIZED frame types. Instead of decoding
1295 * each element of the stack map table, we look for 3 consecutive
1296 * bytes that "look like" an UNINITIALIZED type (tag 8, offset
1297 * within code bounds, NEW instruction at this offset). We may find
1298 * false positives (i.e. not real UNINITIALIZED types), but this
1299 * should be rare, and the only consequence will be the creation of
1300 * an unneeded label. This is better than creating a label for each
1301 * NEW instruction, and faster than fully decoding the whole stack
1302 * map table.
1303 */
1304 for (int i = stackMap; i < stackMap + stackMapSize - 2; ++i) {
1305 if (b[i] == 8) { // UNINITIALIZED FRAME TYPE
1306 int v = readUnsignedShort(i + 1);
1307 if (v >= 0 && v < codeLength) {
1308 if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) {
1309 readLabel(v, labels);
1310 }
1311 }
1312 }
1313 }
1314 }
1315
1316 // visits the instructions
1317 u = codeStart;
1318 while (u < codeEnd) {
1319 int offset = u - codeStart;
1320
1321 // visits the label and line number for this offset, if any
1322 Label l = labels[offset];
1323 if (l != null) {
1324 Label next = l.next;
1325 l.next = null;
1326 mv.visitLabel(l);
1327 if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) {
1328 mv.visitLineNumber(l.line, l);
1329 while (next != null) {
1330 mv.visitLineNumber(next.line, l);
1331 next = next.next;
1332 }
1333 }
1334 }
1335
1336 // visits the frame for this offset, if any
1337 while (FRAMES && frame != null
1338 && (frame.offset == offset || frame.offset == -1)) {
1339 // if there is a frame for this offset, makes the visitor visit
1340 // it, and reads the next frame if there is one.
1341 if (frame.offset != -1) {
1342 if (!zip || unzip) {
1343 mv.visitFrame(Opcodes.F_NEW, frame.localCount,
1344 frame.local, frame.stackCount, frame.stack);
1345 } else {
1346 mv.visitFrame(frame.mode, frame.localDiff, frame.local,
1347 frame.stackCount, frame.stack);
1348 }
1349 }
1350 if (frameCount > 0) {
1351 stackMap = readFrame(stackMap, zip, unzip, frame);
1352 --frameCount;
1353 } else {
1354 frame = null;
1355 }
1356 }
1357
1358 // visits the instruction at this offset
1359 int opcode = b[u] & 0xFF;
1360 switch (ClassWriter.TYPE[opcode]) {
1361 case ClassWriter.NOARG_INSN:
1362 mv.visitInsn(opcode);
1363 u += 1;
1364 break;
1365 case ClassWriter.IMPLVAR_INSN:
1366 if (opcode > Opcodes.ISTORE) {
1367 opcode -= 59; // ISTORE_0
1368 mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),
1369 opcode & 0x3);
1370 } else {
1371 opcode -= 26; // ILOAD_0
1372 mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), opcode & 0x3);
1373 }
1374 u += 1;
1375 break;
1376 case ClassWriter.LABEL_INSN:
1377 mv.visitJumpInsn(opcode, labels[offset + readShort(u + 1)]);
1378 u += 3;
1379 break;
1380 case ClassWriter.LABELW_INSN:
1381 mv.visitJumpInsn(opcode - 33, labels[offset + readInt(u + 1)]);
1382 u += 5;
1383 break;
1384 case ClassWriter.WIDE_INSN:
1385 opcode = b[u + 1] & 0xFF;
1386 if (opcode == Opcodes.IINC) {
1387 mv.visitIincInsn(readUnsignedShort(u + 2), readShort(u + 4));
1388 u += 6;
1389 } else {
1390 mv.visitVarInsn(opcode, readUnsignedShort(u + 2));
1391 u += 4;
1392 }
1393 break;
1394 case ClassWriter.TABL_INSN: {
1395 // skips 0 to 3 padding bytes
1396 u = u + 4 - (offset & 3);
1397 // reads instruction
1398 int label = offset + readInt(u);
1399 int min = readInt(u + 4);
1400 int max = readInt(u + 8);
1401 Label[] table = new Label[max - min + 1];
1402 u += 12;
1403 for (int i = 0; i < table.length; ++i) {
1619 u += 2;
1620 for (int i = 0; i < offsets.length; ++i) {
1621 offsets[i] = u;
1622 int target = readInt(u);
1623 switch (target >>> 24) {
1624 case 0x00: // CLASS_TYPE_PARAMETER
1625 case 0x01: // METHOD_TYPE_PARAMETER
1626 case 0x16: // METHOD_FORMAL_PARAMETER
1627 u += 2;
1628 break;
1629 case 0x13: // FIELD
1630 case 0x14: // METHOD_RETURN
1631 case 0x15: // METHOD_RECEIVER
1632 u += 1;
1633 break;
1634 case 0x40: // LOCAL_VARIABLE
1635 case 0x41: // RESOURCE_VARIABLE
1636 for (int j = readUnsignedShort(u + 1); j > 0; --j) {
1637 int start = readUnsignedShort(u + 3);
1638 int length = readUnsignedShort(u + 5);
1639 readLabel(start, context.labels);
1640 readLabel(start + length, context.labels);
1641 u += 6;
1642 }
1643 u += 3;
1644 break;
1645 case 0x47: // CAST
1646 case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
1647 case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
1648 case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
1649 case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
1650 u += 4;
1651 break;
1652 // case 0x10: // CLASS_EXTENDS
1653 // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
1654 // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
1655 // case 0x17: // THROWS
1656 // case 0x42: // EXCEPTION_PARAMETER
1657 // case 0x43: // INSTANCEOF
1658 // case 0x44: // NEW
1659 // case 0x45: // CONSTRUCTOR_REFERENCE
1660 // case 0x46: // METHOD_REFERENCE
1699 target &= 0xFFFF0000;
1700 u += 2;
1701 break;
1702 case 0x13: // FIELD
1703 case 0x14: // METHOD_RETURN
1704 case 0x15: // METHOD_RECEIVER
1705 target &= 0xFF000000;
1706 u += 1;
1707 break;
1708 case 0x40: // LOCAL_VARIABLE
1709 case 0x41: { // RESOURCE_VARIABLE
1710 target &= 0xFF000000;
1711 int n = readUnsignedShort(u + 1);
1712 context.start = new Label[n];
1713 context.end = new Label[n];
1714 context.index = new int[n];
1715 u += 3;
1716 for (int i = 0; i < n; ++i) {
1717 int start = readUnsignedShort(u);
1718 int length = readUnsignedShort(u + 2);
1719 context.start[i] = readLabel(start, context.labels);
1720 context.end[i] = readLabel(start + length, context.labels);
1721 context.index[i] = readUnsignedShort(u + 4);
1722 u += 6;
1723 }
1724 break;
1725 }
1726 case 0x47: // CAST
1727 case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
1728 case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
1729 case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
1730 case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
1731 target &= 0xFF0000FF;
1732 u += 4;
1733 break;
1734 // case 0x10: // CLASS_EXTENDS
1735 // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
1736 // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
1737 // case 0x17: // THROWS
1738 // case 0x42: // EXCEPTION_PARAMETER
1739 // case 0x43: // INSTANCEOF
1740 // case 0x44: // NEW
2120 } else { // if (tag == FULL_FRAME) {
2121 frame.mode = Opcodes.F_FULL;
2122 int n = readUnsignedShort(stackMap);
2123 stackMap += 2;
2124 frame.localDiff = n;
2125 frame.localCount = n;
2126 for (int local = 0; n > 0; n--) {
2127 stackMap = readFrameType(frame.local, local++, stackMap, c,
2128 labels);
2129 }
2130 n = readUnsignedShort(stackMap);
2131 stackMap += 2;
2132 frame.stackCount = n;
2133 for (int stack = 0; n > 0; n--) {
2134 stackMap = readFrameType(frame.stack, stack++, stackMap, c,
2135 labels);
2136 }
2137 }
2138 }
2139 frame.offset += delta + 1;
2140 readLabel(frame.offset, labels);
2141 return stackMap;
2142 }
2143
2144 /**
2145 * Reads a stack map frame type and stores it at the given index in the
2146 * given array.
2147 *
2148 * @param frame
2149 * the array where the parsed type must be stored.
2150 * @param index
2151 * the index in 'frame' where the parsed type must be stored.
2152 * @param v
2153 * the start offset of the stack map frame type to read.
2154 * @param buf
2155 * a buffer to read strings.
2156 * @param labels
2157 * the labels of the method currently being parsed, indexed by
2158 * their offset. If the parsed type is an Uninitialized type, a
2159 * new label for the corresponding NEW instruction is stored in
2160 * this array if it does not already exist.
2173 case 2:
2174 frame[index] = Opcodes.FLOAT;
2175 break;
2176 case 3:
2177 frame[index] = Opcodes.DOUBLE;
2178 break;
2179 case 4:
2180 frame[index] = Opcodes.LONG;
2181 break;
2182 case 5:
2183 frame[index] = Opcodes.NULL;
2184 break;
2185 case 6:
2186 frame[index] = Opcodes.UNINITIALIZED_THIS;
2187 break;
2188 case 7: // Object
2189 frame[index] = readClass(v, buf);
2190 v += 2;
2191 break;
2192 default: // Uninitialized
2193 frame[index] = readLabel(readUnsignedShort(v), labels);
2194 v += 2;
2195 }
2196 return v;
2197 }
2198
2199 /**
2200 * Returns the label corresponding to the given offset. The default
2201 * implementation of this method creates a label for the given offset if it
2202 * has not been already created.
2203 *
2204 * @param offset
2205 * a bytecode offset in a method.
2206 * @param labels
2207 * the already created labels, indexed by their offset. If a
2208 * label already exists for offset this method must not create a
2209 * new one. Otherwise it must store the new label in this array.
2210 * @return a non null Label, which must be equal to labels[offset].
2211 */
2212 protected Label readLabel(int offset, Label[] labels) {
2213 if (labels[offset] == null) {
2214 labels[offset] = new Label();
2215 }
2216 return labels[offset];
2217 }
2218
2219 /**
2220 * Returns the start index of the attribute_info structure of this class.
2221 *
2222 * @return the start index of the attribute_info structure of this class.
2223 */
2224 private int getAttributes() {
2225 // skips the header
2226 int u = header + 8 + readUnsignedShort(header + 6) * 2;
2227 // skips fields and methods
2228 for (int i = readUnsignedShort(u); i > 0; --i) {
2229 for (int j = readUnsignedShort(u + 8); j > 0; --j) {
2230 u += 6 + readInt(u + 12);
2231 }
2232 u += 8;
2233 }
2234 u += 2;
2235 for (int i = readUnsignedShort(u); i > 0; --i) {
2236 for (int j = readUnsignedShort(u + 8); j > 0; --j) {
2237 u += 6 + readInt(u + 12);
2238 }
2239 u += 8;
2454 cc = (char) (c & 0x0F);
2455 st = 2;
2456 }
2457 break;
2458
2459 case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char
2460 buf[strLen++] = (char) ((cc << 6) | (c & 0x3F));
2461 st = 0;
2462 break;
2463
2464 case 2: // byte 2 of 3-byte char
2465 cc = (char) ((cc << 6) | (c & 0x3F));
2466 st = 1;
2467 break;
2468 }
2469 }
2470 return new String(buf, 0, strLen);
2471 }
2472
2473 /**
2474 * Reads a class constant pool item in {@link #b b}. <i>This method is
2475 * intended for {@link Attribute} sub classes, and is normally not needed by
2476 * class generators or adapters.</i>
2477 *
2478 * @param index
2479 * the start index of an unsigned short value in {@link #b b},
2480 * whose value is the index of a class constant pool item.
2481 * @param buf
2482 * buffer to be used to read the item. This buffer must be
2483 * sufficiently large. It is not automatically resized.
2484 * @return the String corresponding to the specified class item.
2485 */
2486 public String readClass(final int index, final char[] buf) {
2487 // computes the start index of the CONSTANT_Class item in b
2488 // and reads the CONSTANT_Utf8 item designated by
2489 // the first two bytes of this CONSTANT_Class item
2490 return readUTF8(items[readUnsignedShort(index)], buf);
2491 }
2492
2493 /**
2494 * Reads a CONSTANT_Module_info item in {@code b}. This method is intended
2495 * for {@link Attribute} sub classes, and is normally not needed by class
2496 * generators or adapters.</i>
2497 *
2498 * @param index
2499 * the start index of an unsigned short value in {@link #b b},
2500 * whose value is the index of a module constant pool item.
2501 * @param buf
2502 * buffer to be used to read the item. This buffer must be
2503 * sufficiently large. It is not automatically resized.
2504 * @return the String corresponding to the specified module item.
2505 */
2506 public String readModule(int index, char[] buf) {
2507 return readUTF8(items[readUnsignedShort(index)], buf);
2508 }
2509
2510 /**
2511 * Reads a CONSTANT_Package_info item in {@code b}. This method is
2512 * intended for {@link Attribute} sub slasses, and is normally not needed
2513 * by class generators or adapters.</i>
2514 *
2515 * @param index
2516 * the start index of an unsigned short value in {@link #b b},
2517 * whose value is the index of a package constant pool item.
2518 * @param buf
2519 * buffer to be used to read the item. This buffer must be
2520 * sufficiently large. It is not automatically resized.
2521 * @return the String corresponding to the specified package item.
2522 */
2523 public String readPackage(int index, char[] buf) {
2524 return readUTF8(items[readUnsignedShort(index)], buf);
2525 }
2526
2527 /**
2528 * Reads a numeric or string constant pool item in {@link #b b}. <i>This
2529 * method is intended for {@link Attribute} sub classes, and is normally not
2530 * needed by class generators or adapters.</i>
2531 *
2532 * @param item
2533 * the index of a constant pool item.
2534 * @param buf
2535 * buffer to be used to read the item. This buffer must be
2536 * sufficiently large. It is not automatically resized.
2537 * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double},
2538 * {@link String}, {@link Type} or {@link Handle} corresponding to
2539 * the given constant pool item.
2540 */
2541 public Object readConst(final int item, final char[] buf) {
2542 int index = items[item];
2543 switch (b[index - 1]) {
2544 case ClassWriter.INT:
2545 return readInt(index);
2546 case ClassWriter.FLOAT:
2547 return Float.intBitsToFloat(readInt(index));
2548 case ClassWriter.LONG:
2549 return readLong(index);
2550 case ClassWriter.DOUBLE:
2551 return Double.longBitsToDouble(readLong(index));
2552 case ClassWriter.CLASS:
2553 case ClassWriter.MODULE:
2554 case ClassWriter.PACKAGE:
2555 return Type.getObjectType(readUTF8(index, buf));
2556 case ClassWriter.STR:
2557 return readUTF8(index, buf);
2558 case ClassWriter.MTYPE:
2559 return Type.getMethodType(readUTF8(index, buf));
2560 default: // case ClassWriter.HANDLE_BASE + [1..9]:
2561 int tag = readByte(index);
2562 int[] items = this.items;
2563 int cpIndex = items[readUnsignedShort(index + 1)];
2564 boolean itf = b[cpIndex - 1] == ClassWriter.IMETH;
2565 String owner = readClass(cpIndex, buf);
2566 cpIndex = items[readUnsignedShort(cpIndex + 2)];
2567 String name = readUTF8(cpIndex, buf);
2568 String desc = readUTF8(cpIndex + 2, buf);
2569 return new Handle(tag, owner, name, desc, itf);
2570 }
2571 }
2572 }
|
56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
57 * THE POSSIBILITY OF SUCH DAMAGE.
58 */
59 package jdk.internal.org.objectweb.asm;
60
61 import java.io.IOException;
62 import java.io.InputStream;
63
64 /**
65 * A Java class parser to make a {@link ClassVisitor} visit an existing class.
66 * This class parses a byte array conforming to the Java class file format and
67 * calls the appropriate visit methods of a given class visitor for each field,
68 * method and bytecode instruction encountered.
69 *
70 * @author Eric Bruneton
71 * @author Eugene Kuleshov
72 */
73 public class ClassReader {
74
75 /**
76 * Flag to skip method code. If this class is set <code>CODE</code>
77 * attribute won't be visited. This can be used, for example, to retrieve
78 * annotations for methods and method parameters.
79 */
80 public static final int SKIP_CODE = 1;
81
82 /**
83 * Flag to skip the debug information in the class. If this flag is set the
84 * debug information of the class is not visited, i.e. the
85 * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
86 * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be
87 * called.
88 */
89 public static final int SKIP_DEBUG = 2;
90
91 /**
92 * Flag to skip the stack map frames in the class. If this flag is set the
93 * stack map frames of the class is not visited, i.e. the
94 * {@link MethodVisitor#visitFrame visitFrame} method will not be called.
95 * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is
96 * used: it avoids visiting frames that will be ignored and recomputed from
97 * scratch in the class writer.
98 */
99 public static final int SKIP_FRAMES = 4;
100
101 /**
102 * Flag to expand the stack map frames. By default stack map frames are
103 * visited in their original format (i.e. "expanded" for classes whose
104 * version is less than V1_6, and "compressed" for the other classes). If
105 * this flag is set, stack map frames are always visited in expanded format
106 * (this option adds a decompression/recompression step in ClassReader and
107 * ClassWriter which degrades performances quite a lot).
108 */
109 public static final int EXPAND_FRAMES = 8;
110
111 /**
112 * Flag to expand the ASM pseudo instructions into an equivalent sequence of
113 * standard bytecode instructions. When resolving a forward jump it may
114 * happen that the signed 2 bytes offset reserved for it is not sufficient
115 * to store the bytecode offset. In this case the jump instruction is
116 * replaced with a temporary ASM pseudo instruction using an unsigned 2
117 * bytes offset (see Label#resolve). This internal flag is used to re-read
118 * classes containing such instructions, in order to replace them with
119 * standard instructions. In addition, when this flag is used, GOTO_W and
120 * JSR_W are <i>not</i> converted into GOTO and JSR, to make sure that
121 * infinite loops where a GOTO_W is replaced with a GOTO in ClassReader and
122 * converted back to a GOTO_W in ClassWriter cannot occur.
123 */
124 static final int EXPAND_ASM_INSNS = 256;
125
126 /**
127 * The class to be parsed. <i>The content of this array must not be
128 * modified. This field is intended for {@link Attribute} sub classes, and
129 * is normally not needed by class generators or adapters.</i>
130 */
131 public final byte[] b;
132
133 /**
134 * The start index of each constant pool item in {@link #b b}, plus one. The
135 * one byte offset skips the constant pool item tag that indicates its type.
136 */
137 private final int[] items;
138
139 /**
140 * The String objects corresponding to the CONSTANT_Utf8 items. This cache
141 * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
142 * which GREATLY improves performances (by a factor 2 to 3). This caching
143 * strategy could be extended to all constant pool items, but its benefit
144 * would not be so great for these items (because they are much less
145 * expensive to parse than CONSTANT_Utf8 items).
146 */
168 * @param b
169 * the bytecode of the class to be read.
170 */
171 public ClassReader(final byte[] b) {
172 this(b, 0, b.length);
173 }
174
175 /**
176 * Constructs a new {@link ClassReader} object.
177 *
178 * @param b
179 * the bytecode of the class to be read.
180 * @param off
181 * the start offset of the class data.
182 * @param len
183 * the length of the class data.
184 */
185 public ClassReader(final byte[] b, final int off, final int len) {
186 this.b = b;
187 // checks the class version
188 if (readShort(off + 6) > Opcodes.V9) {
189 throw new IllegalArgumentException();
190 }
191 // parses the constant pool
192 items = new int[readUnsignedShort(off + 8)];
193 int n = items.length;
194 strings = new String[n];
195 int max = 0;
196 int index = off + 10;
197 for (int i = 1; i < n; ++i) {
198 items[i] = index + 1;
199 int size;
200 switch (b[index]) {
201 case ClassWriter.FIELD:
202 case ClassWriter.METH:
203 case ClassWriter.IMETH:
204 case ClassWriter.INT:
205 case ClassWriter.FLOAT:
206 case ClassWriter.NAME_TYPE:
207 case ClassWriter.INDY:
208 size = 5;
209 break;
210 case ClassWriter.LONG:
211 case ClassWriter.DOUBLE:
212 size = 9;
213 ++i;
214 break;
215 case ClassWriter.UTF8:
216 size = 3 + readUnsignedShort(index + 1);
217 if (size > max) {
218 max = size;
219 }
220 break;
221 case ClassWriter.HANDLE:
222 size = 4;
223 break;
224 // case ClassWriter.CLASS:
225 // case ClassWriter.STR:
226 // case ClassWriter.MTYPE
227 // case ClassWriter.PACKAGE:
228 // case ClassWriter.MODULE:
229 default:
230 size = 3;
231 break;
232 }
233 index += size;
234 }
235 maxStringLength = max;
236 // the class header information starts just after the constant pool
237 header = index;
238 }
239
240 /**
241 * Returns the class's access flags (see {@link Opcodes}). This value may
242 * not reflect Deprecated and Synthetic flags when bytecode is before 1.5
243 * and those flags are represented by attributes.
244 *
245 * @return the class access flags
246 *
247 * @see ClassVisitor#visit(int, int, String, String, String, String[])
248 */
352 break;
353 }
354 case ClassWriter.HANDLE: {
355 int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
356 nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
357 item.set(ClassWriter.HANDLE_BASE + readByte(index),
358 readClass(fieldOrMethodRef, buf),
359 readUTF8(nameType, buf), readUTF8(nameType + 2, buf));
360 break;
361 }
362 case ClassWriter.INDY:
363 if (classWriter.bootstrapMethods == null) {
364 copyBootstrapMethods(classWriter, items2, buf);
365 }
366 nameType = items[readUnsignedShort(index + 2)];
367 item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf),
368 readUnsignedShort(index));
369 break;
370 // case ClassWriter.STR:
371 // case ClassWriter.CLASS:
372 // case ClassWriter.MTYPE:
373 // case ClassWriter.MODULE:
374 // case ClassWriter.PACKAGE:
375 default:
376 item.set(tag, readUTF8(index, buf), null, null);
377 break;
378 }
379
380 int index2 = item.hashCode % items2.length;
381 item.next = items2[index2];
382 items2[index2] = item;
383 }
384
385 int off = items[1] - 1;
386 classWriter.pool.putByteArray(b, off, header - off);
387 classWriter.items = items2;
388 classWriter.threshold = (int) (0.75d * ll);
389 classWriter.index = ll;
390 }
391
392 /**
393 * Copies the bootstrap method data into the given {@link ClassWriter}.
394 * Should be called before the {@link #accept(ClassVisitor,int)} method.
561 context.buffer = c;
562
563 // reads the class declaration
564 int access = readUnsignedShort(u);
565 String name = readClass(u + 2, c);
566 String superClass = readClass(u + 4, c);
567 String[] interfaces = new String[readUnsignedShort(u + 6)];
568 u += 8;
569 for (int i = 0; i < interfaces.length; ++i) {
570 interfaces[i] = readClass(u, c);
571 u += 2;
572 }
573
574 // reads the class attributes
575 String signature = null;
576 String sourceFile = null;
577 String sourceDebug = null;
578 String enclosingOwner = null;
579 String enclosingName = null;
580 String enclosingDesc = null;
581 String moduleMainClass = null;
582 int anns = 0;
583 int ianns = 0;
584 int tanns = 0;
585 int itanns = 0;
586 int innerClasses = 0;
587 int module = 0;
588 int packages = 0;
589 Attribute attributes = null;
590
591 u = getAttributes();
592 for (int i = readUnsignedShort(u); i > 0; --i) {
593 String attrName = readUTF8(u + 2, c);
594 // tests are sorted in decreasing frequency order
595 // (based on frequencies observed on typical classes)
596 if ("SourceFile".equals(attrName)) {
597 sourceFile = readUTF8(u + 8, c);
598 } else if ("InnerClasses".equals(attrName)) {
599 innerClasses = u + 8;
600 } else if ("EnclosingMethod".equals(attrName)) {
601 enclosingOwner = readClass(u + 8, c);
602 int item = readUnsignedShort(u + 10);
603 if (item != 0) {
604 enclosingName = readUTF8(items[item], c);
605 enclosingDesc = readUTF8(items[item] + 2, c);
606 }
607 } else if ("Signature".equals(attrName)) {
608 signature = readUTF8(u + 8, c);
609 } else if ("RuntimeVisibleAnnotations".equals(attrName)) {
610 anns = u + 8;
611 } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
612 tanns = u + 8;
613 } else if ("Deprecated".equals(attrName)) {
614 access |= Opcodes.ACC_DEPRECATED;
615 } else if ("Synthetic".equals(attrName)) {
616 access |= Opcodes.ACC_SYNTHETIC
617 | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
618 } else if ("SourceDebugExtension".equals(attrName)) {
619 int len = readInt(u + 4);
620 sourceDebug = readUTF(u + 8, len, new char[len]);
621 } else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
622 ianns = u + 8;
623 } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
624 itanns = u + 8;
625 } else if ("Module".equals(attrName)) {
626 module = u + 8;
627 } else if ("ModuleMainClass".equals(attrName)) {
628 moduleMainClass = readClass(u + 8, c);
629 } else if ("ModulePackages".equals(attrName)) {
630 packages = u + 10;
631 } else if ("BootstrapMethods".equals(attrName)) {
632 int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
633 for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
634 bootstrapMethods[j] = v;
635 v += 2 + readUnsignedShort(v + 2) << 1;
636 }
637 context.bootstrapMethods = bootstrapMethods;
638 } else {
639 Attribute attr = readAttribute(attrs, attrName, u + 8,
640 readInt(u + 4), c, -1, null);
641 if (attr != null) {
642 attr.next = attributes;
643 attributes = attr;
644 }
645 }
646 u += 6 + readInt(u + 4);
647 }
648
649 // visits the class declaration
650 classVisitor.visit(readInt(items[1] - 7), access, name, signature,
651 superClass, interfaces);
652
653 // visits the source and debug info
654 if ((flags & SKIP_DEBUG) == 0
655 && (sourceFile != null || sourceDebug != null)) {
656 classVisitor.visitSource(sourceFile, sourceDebug);
657 }
658
659 // visits the module info and associated attributes
660 if (module != 0) {
661 readModule(classVisitor, context, module,
662 moduleMainClass, packages);
663 }
664
665 // visits the outer class
666 if (enclosingOwner != null) {
667 classVisitor.visitOuterClass(enclosingOwner, enclosingName,
668 enclosingDesc);
669 }
670
671 // visits the class annotations and type annotations
672 if (anns != 0) {
673 for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
674 v = readAnnotationValues(v + 2, c, true,
675 classVisitor.visitAnnotation(readUTF8(v, c), true));
676 }
677 }
678 if (ianns != 0) {
679 for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
680 v = readAnnotationValues(v + 2, c, true,
681 classVisitor.visitAnnotation(readUTF8(v, c), false));
682 }
683 }
684 if (tanns != 0) {
685 for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
686 v = readAnnotationTarget(context, v);
687 v = readAnnotationValues(v + 2, c, true,
688 classVisitor.visitTypeAnnotation(context.typeRef,
689 context.typePath, readUTF8(v, c), true));
690 }
691 }
692 if (itanns != 0) {
693 for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
694 v = readAnnotationTarget(context, v);
695 v = readAnnotationValues(v + 2, c, true,
696 classVisitor.visitTypeAnnotation(context.typeRef,
697 context.typePath, readUTF8(v, c), false));
698 }
699 }
700
701 // visits the attributes
702 while (attributes != null) {
703 Attribute attr = attributes.next;
704 attributes.next = null;
705 classVisitor.visitAttribute(attributes);
706 attributes = attr;
707 }
708
709 // visits the inner classes
710 if (innerClasses != 0) {
711 int v = innerClasses + 2;
712 for (int i = readUnsignedShort(innerClasses); i > 0; --i) {
715 readUnsignedShort(v + 6));
716 v += 8;
717 }
718 }
719
720 // visits the fields and methods
721 u = header + 10 + 2 * interfaces.length;
722 for (int i = readUnsignedShort(u - 2); i > 0; --i) {
723 u = readField(classVisitor, context, u);
724 }
725 u += 2;
726 for (int i = readUnsignedShort(u - 2); i > 0; --i) {
727 u = readMethod(classVisitor, context, u);
728 }
729
730 // visits the end of the class
731 classVisitor.visitEnd();
732 }
733
734 /**
735 * Reads the module attribute and visit it.
736 *
737 * @param classVisitor
738 * the current class visitor
739 * @param context
740 * information about the class being parsed.
741 * @param u
742 * start offset of the module attribute in the class file.
743 * @param mainClass
744 * name of the main class of a module or null.
745 * @param packages
746 * start offset of the concealed package attribute.
747 */
748 private void readModule(final ClassVisitor classVisitor,
749 final Context context, int u,
750 final String mainClass, int packages) {
751
752 char[] buffer = context.buffer;
753
754 // reads module name, flags and version
755 String name = readModule(u, buffer);
756 int flags = readUnsignedShort(u + 2);
757 String version = readUTF8(u + 4, buffer);
758 u += 6;
759
760 ModuleVisitor mv = classVisitor.visitModule(name, flags, version);
761 if (mv == null) {
762 return;
763 }
764
765 // module attributes (main class, packages)
766 if (mainClass != null) {
767 mv.visitMainClass(mainClass);
768 }
769
770 if (packages != 0) {
771 for (int i = readUnsignedShort(packages - 2); i > 0; --i) {
772 String packaze = readPackage(packages, buffer);
773 mv.visitPackage(packaze);
774 packages += 2;
775 }
776 }
777
778 // reads requires
779 u += 2;
780 for (int i = readUnsignedShort(u - 2); i > 0; --i) {
781 String module = readModule(u, buffer);
782 int access = readUnsignedShort(u + 2);
783 String requireVersion = readUTF8(u + 4, buffer);
784 mv.visitRequire(module, access, requireVersion);
785 u += 6;
786 }
787
788 // reads exports
789 u += 2;
790 for (int i = readUnsignedShort(u - 2); i > 0; --i) {
791 String export = readPackage(u, buffer);
792 int access = readUnsignedShort(u + 2);
793 int exportToCount = readUnsignedShort(u + 4);
794 u += 6;
795 String[] tos = null;
796 if (exportToCount != 0) {
797 tos = new String[exportToCount];
798 for (int j = 0; j < tos.length; ++j) {
799 tos[j] = readModule(u, buffer);
800 u += 2;
801 }
802 }
803 mv.visitExport(export, access, tos);
804 }
805
806 // reads opens
807 u += 2;
808 for (int i = readUnsignedShort(u - 2); i > 0; --i) {
809 String open = readPackage(u, buffer);
810 int access = readUnsignedShort(u + 2);
811 int openToCount = readUnsignedShort(u + 4);
812 u += 6;
813 String[] tos = null;
814 if (openToCount != 0) {
815 tos = new String[openToCount];
816 for (int j = 0; j < tos.length; ++j) {
817 tos[j] = readModule(u, buffer);
818 u += 2;
819 }
820 }
821 mv.visitOpen(open, access, tos);
822 }
823
824 // read uses
825 u += 2;
826 for (int i = readUnsignedShort(u - 2); i > 0; --i) {
827 mv.visitUse(readClass(u, buffer));
828 u += 2;
829 }
830
831 // read provides
832 u += 2;
833 for (int i = readUnsignedShort(u - 2); i > 0; --i) {
834 String service = readClass(u, buffer);
835 int provideWithCount = readUnsignedShort(u + 2);
836 u += 4;
837 String[] withs = new String[provideWithCount];
838 for (int j = 0; j < withs.length; ++j) {
839 withs[j] = readClass(u, buffer);
840 u += 2;
841 }
842 mv.visitProvide(service, withs);
843 }
844
845 mv.visitEnd();
846 }
847
848 /**
849 * Reads a field and makes the given visitor visit it.
850 *
851 * @param classVisitor
852 * the visitor that must visit the field.
853 * @param context
854 * information about the class being parsed.
855 * @param u
856 * the start offset of the field in the class file.
857 * @return the offset of the first byte following the field in the class.
858 */
859 private int readField(final ClassVisitor classVisitor,
860 final Context context, int u) {
861 // reads the field declaration
862 char[] c = context.buffer;
863 int access = readUnsignedShort(u);
864 String name = readUTF8(u + 2, c);
865 String desc = readUTF8(u + 4, c);
866 u += 6;
867
868 // reads the field attributes
869 String signature = null;
870 int anns = 0;
871 int ianns = 0;
872 int tanns = 0;
873 int itanns = 0;
874 Object value = null;
875 Attribute attributes = null;
876
877 for (int i = readUnsignedShort(u); i > 0; --i) {
878 String attrName = readUTF8(u + 2, c);
879 // tests are sorted in decreasing frequency order
880 // (based on frequencies observed on typical classes)
881 if ("ConstantValue".equals(attrName)) {
882 int item = readUnsignedShort(u + 8);
883 value = item == 0 ? null : readConst(item, c);
884 } else if ("Signature".equals(attrName)) {
885 signature = readUTF8(u + 8, c);
886 } else if ("Deprecated".equals(attrName)) {
887 access |= Opcodes.ACC_DEPRECATED;
888 } else if ("Synthetic".equals(attrName)) {
889 access |= Opcodes.ACC_SYNTHETIC
890 | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
891 } else if ("RuntimeVisibleAnnotations".equals(attrName)) {
892 anns = u + 8;
893 } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
894 tanns = u + 8;
895 } else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
896 ianns = u + 8;
897 } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
898 itanns = u + 8;
899 } else {
900 Attribute attr = readAttribute(context.attrs, attrName, u + 8,
901 readInt(u + 4), c, -1, null);
902 if (attr != null) {
903 attr.next = attributes;
904 attributes = attr;
905 }
906 }
907 u += 6 + readInt(u + 4);
908 }
909 u += 2;
910
911 // visits the field declaration
912 FieldVisitor fv = classVisitor.visitField(access, name, desc,
913 signature, value);
914 if (fv == null) {
915 return u;
916 }
917
918 // visits the field annotations and type annotations
919 if (anns != 0) {
920 for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
921 v = readAnnotationValues(v + 2, c, true,
922 fv.visitAnnotation(readUTF8(v, c), true));
923 }
924 }
925 if (ianns != 0) {
926 for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
927 v = readAnnotationValues(v + 2, c, true,
928 fv.visitAnnotation(readUTF8(v, c), false));
929 }
930 }
931 if (tanns != 0) {
932 for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
933 v = readAnnotationTarget(context, v);
934 v = readAnnotationValues(v + 2, c, true,
935 fv.visitTypeAnnotation(context.typeRef,
936 context.typePath, readUTF8(v, c), true));
937 }
938 }
939 if (itanns != 0) {
940 for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
941 v = readAnnotationTarget(context, v);
942 v = readAnnotationValues(v + 2, c, true,
943 fv.visitTypeAnnotation(context.typeRef,
944 context.typePath, readUTF8(v, c), false));
945 }
946 }
947
948 // visits the field attributes
949 while (attributes != null) {
950 Attribute attr = attributes.next;
951 attributes.next = null;
952 fv.visitAttribute(attributes);
953 attributes = attr;
954 }
955
956 // visits the end of the field
957 fv.visitEnd();
958
959 return u;
993 int mpanns = 0;
994 int impanns = 0;
995 int firstAttribute = u;
996 Attribute attributes = null;
997
998 for (int i = readUnsignedShort(u); i > 0; --i) {
999 String attrName = readUTF8(u + 2, c);
1000 // tests are sorted in decreasing frequency order
1001 // (based on frequencies observed on typical classes)
1002 if ("Code".equals(attrName)) {
1003 if ((context.flags & SKIP_CODE) == 0) {
1004 code = u + 8;
1005 }
1006 } else if ("Exceptions".equals(attrName)) {
1007 exceptions = new String[readUnsignedShort(u + 8)];
1008 exception = u + 10;
1009 for (int j = 0; j < exceptions.length; ++j) {
1010 exceptions[j] = readClass(exception, c);
1011 exception += 2;
1012 }
1013 } else if ("Signature".equals(attrName)) {
1014 signature = readUTF8(u + 8, c);
1015 } else if ("Deprecated".equals(attrName)) {
1016 context.access |= Opcodes.ACC_DEPRECATED;
1017 } else if ("RuntimeVisibleAnnotations".equals(attrName)) {
1018 anns = u + 8;
1019 } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
1020 tanns = u + 8;
1021 } else if ("AnnotationDefault".equals(attrName)) {
1022 dann = u + 8;
1023 } else if ("Synthetic".equals(attrName)) {
1024 context.access |= Opcodes.ACC_SYNTHETIC
1025 | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
1026 } else if ("RuntimeInvisibleAnnotations".equals(attrName)) {
1027 ianns = u + 8;
1028 } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
1029 itanns = u + 8;
1030 } else if ("RuntimeVisibleParameterAnnotations".equals(attrName)) {
1031 mpanns = u + 8;
1032 } else if ("RuntimeInvisibleParameterAnnotations".equals(attrName)) {
1033 impanns = u + 8;
1034 } else if ("MethodParameters".equals(attrName)) {
1035 methodParameters = u + 8;
1036 } else {
1037 Attribute attr = readAttribute(context.attrs, attrName, u + 8,
1038 readInt(u + 4), c, -1, null);
1039 if (attr != null) {
1040 attr.next = attributes;
1041 attributes = attr;
1042 }
1043 }
1044 u += 6 + readInt(u + 4);
1045 }
1046 u += 2;
1047
1048 // visits the method declaration
1049 MethodVisitor mv = classVisitor.visitMethod(context.access,
1050 context.name, context.desc, signature, exceptions);
1051 if (mv == null) {
1052 return u;
1053 }
1054
1055 /*
1056 * if the returned MethodVisitor is in fact a MethodWriter, it means
1057 * there is no method adapter between the reader and the writer. If, in
1058 * addition, the writer's constant pool was copied from this reader
1059 * (mw.cw.cr == this), and the signature and exceptions of the method
1060 * have not been changed, then it is possible to skip all visit events
1061 * and just copy the original code of the method to the writer (the
1062 * access, name and descriptor can have been changed, this is not
1063 * important since they are not copied as is from the reader).
1064 */
1065 if (mv instanceof MethodWriter) {
1066 MethodWriter mw = (MethodWriter) mv;
1067 if (mw.cw.cr == this && signature == mw.signature) {
1068 boolean sameExceptions = false;
1069 if (exceptions == null) {
1070 sameExceptions = mw.exceptionCount == 0;
1071 } else if (exceptions.length == mw.exceptionCount) {
1072 sameExceptions = true;
1073 for (int j = exceptions.length - 1; j >= 0; --j) {
1074 exception -= 2;
1075 if (mw.exceptions[j] != readUnsignedShort(exception)) {
1076 sameExceptions = false;
1077 break;
1078 }
1079 }
1080 }
1081 if (sameExceptions) {
1082 /*
1083 * we do not copy directly the code into MethodWriter to
1084 * save a byte array copy operation. The real copy will be
1085 * done in ClassWriter.toByteArray().
1086 */
1087 mw.classReaderOffset = firstAttribute;
1088 mw.classReaderLength = u - firstAttribute;
1089 return u;
1090 }
1091 }
1092 }
1093
1094 // visit the method parameters
1095 if (methodParameters != 0) {
1096 for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) {
1097 mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2));
1098 }
1099 }
1100
1101 // visits the method annotations
1102 if (dann != 0) {
1103 AnnotationVisitor dv = mv.visitAnnotationDefault();
1104 readAnnotationValue(dann, c, null, dv);
1105 if (dv != null) {
1106 dv.visitEnd();
1107 }
1108 }
1109 if (anns != 0) {
1110 for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
1111 v = readAnnotationValues(v + 2, c, true,
1112 mv.visitAnnotation(readUTF8(v, c), true));
1113 }
1114 }
1115 if (ianns != 0) {
1116 for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
1117 v = readAnnotationValues(v + 2, c, true,
1118 mv.visitAnnotation(readUTF8(v, c), false));
1119 }
1120 }
1121 if (tanns != 0) {
1122 for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
1123 v = readAnnotationTarget(context, v);
1124 v = readAnnotationValues(v + 2, c, true,
1125 mv.visitTypeAnnotation(context.typeRef,
1126 context.typePath, readUTF8(v, c), true));
1127 }
1128 }
1129 if (itanns != 0) {
1130 for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
1131 v = readAnnotationTarget(context, v);
1132 v = readAnnotationValues(v + 2, c, true,
1133 mv.visitTypeAnnotation(context.typeRef,
1134 context.typePath, readUTF8(v, c), false));
1135 }
1136 }
1137 if (mpanns != 0) {
1138 readParameterAnnotations(mv, context, mpanns, true);
1139 }
1140 if (impanns != 0) {
1141 readParameterAnnotations(mv, context, impanns, false);
1142 }
1143
1144 // visits the method attributes
1145 while (attributes != null) {
1146 Attribute attr = attributes.next;
1147 attributes.next = null;
1148 mv.visitAttribute(attributes);
1149 attributes = attr;
1150 }
1151
1152 // visits the method code
1153 if (code != 0) {
1154 mv.visitCode();
1155 readCode(mv, context, code);
1156 }
1157
1158 // visits the end of the method
1159 mv.visitEnd();
1160
1167 * @param mv
1168 * the visitor that must visit the method's code.
1169 * @param context
1170 * information about the class being parsed.
1171 * @param u
1172 * the start offset of the code attribute in the class file.
1173 */
1174 private void readCode(final MethodVisitor mv, final Context context, int u) {
1175 // reads the header
1176 byte[] b = this.b;
1177 char[] c = context.buffer;
1178 int maxStack = readUnsignedShort(u);
1179 int maxLocals = readUnsignedShort(u + 2);
1180 int codeLength = readInt(u + 4);
1181 u += 8;
1182
1183 // reads the bytecode to find the labels
1184 int codeStart = u;
1185 int codeEnd = u + codeLength;
1186 Label[] labels = context.labels = new Label[codeLength + 2];
1187 createLabel(codeLength + 1, labels);
1188 while (u < codeEnd) {
1189 int offset = u - codeStart;
1190 int opcode = b[u] & 0xFF;
1191 switch (ClassWriter.TYPE[opcode]) {
1192 case ClassWriter.NOARG_INSN:
1193 case ClassWriter.IMPLVAR_INSN:
1194 u += 1;
1195 break;
1196 case ClassWriter.LABEL_INSN:
1197 createLabel(offset + readShort(u + 1), labels);
1198 u += 3;
1199 break;
1200 case ClassWriter.ASM_LABEL_INSN:
1201 createLabel(offset + readUnsignedShort(u + 1), labels);
1202 u += 3;
1203 break;
1204 case ClassWriter.LABELW_INSN:
1205 case ClassWriter.ASM_LABELW_INSN:
1206 createLabel(offset + readInt(u + 1), labels);
1207 u += 5;
1208 break;
1209 case ClassWriter.WIDE_INSN:
1210 opcode = b[u + 1] & 0xFF;
1211 if (opcode == Opcodes.IINC) {
1212 u += 6;
1213 } else {
1214 u += 4;
1215 }
1216 break;
1217 case ClassWriter.TABL_INSN:
1218 // skips 0 to 3 padding bytes
1219 u = u + 4 - (offset & 3);
1220 // reads instruction
1221 createLabel(offset + readInt(u), labels);
1222 for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) {
1223 createLabel(offset + readInt(u + 12), labels);
1224 u += 4;
1225 }
1226 u += 12;
1227 break;
1228 case ClassWriter.LOOK_INSN:
1229 // skips 0 to 3 padding bytes
1230 u = u + 4 - (offset & 3);
1231 // reads instruction
1232 createLabel(offset + readInt(u), labels);
1233 for (int i = readInt(u + 4); i > 0; --i) {
1234 createLabel(offset + readInt(u + 12), labels);
1235 u += 8;
1236 }
1237 u += 8;
1238 break;
1239 case ClassWriter.VAR_INSN:
1240 case ClassWriter.SBYTE_INSN:
1241 case ClassWriter.LDC_INSN:
1242 u += 2;
1243 break;
1244 case ClassWriter.SHORT_INSN:
1245 case ClassWriter.LDCW_INSN:
1246 case ClassWriter.FIELDORMETH_INSN:
1247 case ClassWriter.TYPE_INSN:
1248 case ClassWriter.IINC_INSN:
1249 u += 3;
1250 break;
1251 case ClassWriter.ITFMETH_INSN:
1252 case ClassWriter.INDYMETH_INSN:
1253 u += 5;
1254 break;
1255 // case MANA_INSN:
1256 default:
1257 u += 4;
1258 break;
1259 }
1260 }
1261
1262 // reads the try catch entries to find the labels, and also visits them
1263 for (int i = readUnsignedShort(u); i > 0; --i) {
1264 Label start = createLabel(readUnsignedShort(u + 2), labels);
1265 Label end = createLabel(readUnsignedShort(u + 4), labels);
1266 Label handler = createLabel(readUnsignedShort(u + 6), labels);
1267 String type = readUTF8(items[readUnsignedShort(u + 8)], c);
1268 mv.visitTryCatchBlock(start, end, handler, type);
1269 u += 8;
1270 }
1271 u += 2;
1272
1273 // reads the code attributes
1274 int[] tanns = null; // start index of each visible type annotation
1275 int[] itanns = null; // start index of each invisible type annotation
1276 int tann = 0; // current index in tanns array
1277 int itann = 0; // current index in itanns array
1278 int ntoff = -1; // next visible type annotation code offset
1279 int nitoff = -1; // next invisible type annotation code offset
1280 int varTable = 0;
1281 int varTypeTable = 0;
1282 boolean zip = true;
1283 boolean unzip = (context.flags & EXPAND_FRAMES) != 0;
1284 int stackMap = 0;
1285 int stackMapSize = 0;
1286 int frameCount = 0;
1287 Context frame = null;
1288 Attribute attributes = null;
1289
1290 for (int i = readUnsignedShort(u); i > 0; --i) {
1291 String attrName = readUTF8(u + 2, c);
1292 if ("LocalVariableTable".equals(attrName)) {
1293 if ((context.flags & SKIP_DEBUG) == 0) {
1294 varTable = u + 8;
1295 for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
1296 int label = readUnsignedShort(v + 10);
1297 createDebugLabel(label, labels);
1298 label += readUnsignedShort(v + 12);
1299 createDebugLabel(label, labels);
1300 v += 10;
1301 }
1302 }
1303 } else if ("LocalVariableTypeTable".equals(attrName)) {
1304 varTypeTable = u + 8;
1305 } else if ("LineNumberTable".equals(attrName)) {
1306 if ((context.flags & SKIP_DEBUG) == 0) {
1307 for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
1308 int label = readUnsignedShort(v + 10);
1309 createDebugLabel(label, labels);
1310 Label l = labels[label];
1311 while (l.line > 0) {
1312 if (l.next == null) {
1313 l.next = new Label();
1314 }
1315 l = l.next;
1316 }
1317 l.line = readUnsignedShort(v + 12);
1318 v += 4;
1319 }
1320 }
1321 } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) {
1322 tanns = readTypeAnnotations(mv, context, u + 8, true);
1323 ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1
1324 : readUnsignedShort(tanns[0] + 1);
1325 } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) {
1326 itanns = readTypeAnnotations(mv, context, u + 8, false);
1327 nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1
1328 : readUnsignedShort(itanns[0] + 1);
1329 } else if ("StackMapTable".equals(attrName)) {
1330 if ((context.flags & SKIP_FRAMES) == 0) {
1331 stackMap = u + 10;
1332 stackMapSize = readInt(u + 4);
1333 frameCount = readUnsignedShort(u + 8);
1334 }
1335 /*
1336 * here we do not extract the labels corresponding to the
1337 * attribute content. This would require a full parsing of the
1338 * attribute, which would need to be repeated in the second
1339 * phase (see below). Instead the content of the attribute is
1340 * read one frame at a time (i.e. after a frame has been
1341 * visited, the next frame is read), and the labels it contains
1342 * are also extracted one frame at a time. Thanks to the
1343 * ordering of frames, having only a "one frame lookahead" is
1344 * not a problem, i.e. it is not possible to see an offset
1345 * smaller than the offset of the current insn and for which no
1346 * Label exist.
1347 */
1348 /*
1349 * This is not true for UNINITIALIZED type offsets. We solve
1350 * this by parsing the stack map table without a full decoding
1351 * (see below).
1352 */
1353 } else if ("StackMap".equals(attrName)) {
1354 if ((context.flags & SKIP_FRAMES) == 0) {
1355 zip = false;
1356 stackMap = u + 10;
1357 stackMapSize = readInt(u + 4);
1358 frameCount = readUnsignedShort(u + 8);
1359 }
1360 /*
1361 * IMPORTANT! here we assume that the frames are ordered, as in
1362 * the StackMapTable attribute, although this is not guaranteed
1363 * by the attribute format.
1364 */
1365 } else {
1366 for (int j = 0; j < context.attrs.length; ++j) {
1367 if (context.attrs[j].type.equals(attrName)) {
1368 Attribute attr = context.attrs[j].read(this, u + 8,
1369 readInt(u + 4), c, codeStart - 8, labels);
1370 if (attr != null) {
1371 attr.next = attributes;
1372 attributes = attr;
1373 }
1374 }
1375 }
1376 }
1377 u += 6 + readInt(u + 4);
1378 }
1379 u += 2;
1380
1381 // generates the first (implicit) stack map frame
1382 if (stackMap != 0) {
1383 /*
1384 * for the first explicit frame the offset is not offset_delta + 1
1385 * but only offset_delta; setting the implicit frame offset to -1
1386 * allow the use of the "offset_delta + 1" rule in all cases
1387 */
1388 frame = context;
1389 frame.offset = -1;
1390 frame.mode = 0;
1391 frame.localCount = 0;
1392 frame.localDiff = 0;
1393 frame.stackCount = 0;
1394 frame.local = new Object[maxLocals];
1395 frame.stack = new Object[maxStack];
1396 if (unzip) {
1397 getImplicitFrame(context);
1398 }
1399 /*
1400 * Finds labels for UNINITIALIZED frame types. Instead of decoding
1401 * each element of the stack map table, we look for 3 consecutive
1402 * bytes that "look like" an UNINITIALIZED type (tag 8, offset
1403 * within code bounds, NEW instruction at this offset). We may find
1404 * false positives (i.e. not real UNINITIALIZED types), but this
1405 * should be rare, and the only consequence will be the creation of
1406 * an unneeded label. This is better than creating a label for each
1407 * NEW instruction, and faster than fully decoding the whole stack
1408 * map table.
1409 */
1410 for (int i = stackMap; i < stackMap + stackMapSize - 2; ++i) {
1411 if (b[i] == 8) { // UNINITIALIZED FRAME TYPE
1412 int v = readUnsignedShort(i + 1);
1413 if (v >= 0 && v < codeLength) {
1414 if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) {
1415 createLabel(v, labels);
1416 }
1417 }
1418 }
1419 }
1420 }
1421 if ((context.flags & EXPAND_ASM_INSNS) != 0
1422 && (context.flags & EXPAND_FRAMES) != 0) {
1423 // Expanding the ASM pseudo instructions can introduce F_INSERT
1424 // frames, even if the method does not currently have any frame.
1425 // Also these inserted frames must be computed by simulating the
1426 // effect of the bytecode instructions one by one, starting from the
1427 // first one and the last existing frame (or the implicit first
1428 // one). Finally, due to the way MethodWriter computes this (with
1429 // the compute = INSERTED_FRAMES option), MethodWriter needs to know
1430 // maxLocals before the first instruction is visited. For all these
1431 // reasons we always visit the implicit first frame in this case
1432 // (passing only maxLocals - the rest can be and is computed in
1433 // MethodWriter).
1434 mv.visitFrame(Opcodes.F_NEW, maxLocals, null, 0, null);
1435 }
1436
1437 // visits the instructions
1438 int opcodeDelta = (context.flags & EXPAND_ASM_INSNS) == 0 ? -33 : 0;
1439 boolean insertFrame = false;
1440 u = codeStart;
1441 while (u < codeEnd) {
1442 int offset = u - codeStart;
1443
1444 // visits the label and line number for this offset, if any
1445 Label l = labels[offset];
1446 if (l != null) {
1447 Label next = l.next;
1448 l.next = null;
1449 mv.visitLabel(l);
1450 if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) {
1451 mv.visitLineNumber(l.line, l);
1452 while (next != null) {
1453 mv.visitLineNumber(next.line, l);
1454 next = next.next;
1455 }
1456 }
1457 }
1458
1459 // visits the frame for this offset, if any
1460 while (frame != null
1461 && (frame.offset == offset || frame.offset == -1)) {
1462 // if there is a frame for this offset, makes the visitor visit
1463 // it, and reads the next frame if there is one.
1464 if (frame.offset != -1) {
1465 if (!zip || unzip) {
1466 mv.visitFrame(Opcodes.F_NEW, frame.localCount,
1467 frame.local, frame.stackCount, frame.stack);
1468 } else {
1469 mv.visitFrame(frame.mode, frame.localDiff, frame.local,
1470 frame.stackCount, frame.stack);
1471 }
1472 // if there is already a frame for this offset, there is no
1473 // need to insert a new one.
1474 insertFrame = false;
1475 }
1476 if (frameCount > 0) {
1477 stackMap = readFrame(stackMap, zip, unzip, frame);
1478 --frameCount;
1479 } else {
1480 frame = null;
1481 }
1482 }
1483 // inserts a frame for this offset, if requested by setting
1484 // insertFrame to true during the previous iteration. The actual
1485 // frame content will be computed in MethodWriter.
1486 if (insertFrame) {
1487 mv.visitFrame(ClassWriter.F_INSERT, 0, null, 0, null);
1488 insertFrame = false;
1489 }
1490
1491 // visits the instruction at this offset
1492 int opcode = b[u] & 0xFF;
1493 switch (ClassWriter.TYPE[opcode]) {
1494 case ClassWriter.NOARG_INSN:
1495 mv.visitInsn(opcode);
1496 u += 1;
1497 break;
1498 case ClassWriter.IMPLVAR_INSN:
1499 if (opcode > Opcodes.ISTORE) {
1500 opcode -= 59; // ISTORE_0
1501 mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),
1502 opcode & 0x3);
1503 } else {
1504 opcode -= 26; // ILOAD_0
1505 mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), opcode & 0x3);
1506 }
1507 u += 1;
1508 break;
1509 case ClassWriter.LABEL_INSN:
1510 mv.visitJumpInsn(opcode, labels[offset + readShort(u + 1)]);
1511 u += 3;
1512 break;
1513 case ClassWriter.LABELW_INSN:
1514 mv.visitJumpInsn(opcode + opcodeDelta, labels[offset
1515 + readInt(u + 1)]);
1516 u += 5;
1517 break;
1518 case ClassWriter.ASM_LABEL_INSN: {
1519 // changes temporary opcodes 202 to 217 (inclusive), 218
1520 // and 219 to IFEQ ... JSR (inclusive), IFNULL and
1521 // IFNONNULL
1522 opcode = opcode < 218 ? opcode - 49 : opcode - 20;
1523 Label target = labels[offset + readUnsignedShort(u + 1)];
1524 // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
1525 // <l> with IFNOTxxx <L> GOTO_W <l> L:..., where IFNOTxxx is
1526 // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
1527 // and where <L> designates the instruction just after
1528 // the GOTO_W.
1529 if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
1530 mv.visitJumpInsn(opcode + 33, target);
1531 } else {
1532 opcode = opcode <= 166 ? ((opcode + 1) ^ 1) - 1
1533 : opcode ^ 1;
1534 Label endif = createLabel(offset + 3, labels);
1535 mv.visitJumpInsn(opcode, endif);
1536 mv.visitJumpInsn(200, target); // GOTO_W
1537 // endif designates the instruction just after GOTO_W,
1538 // and is visited as part of the next instruction. Since
1539 // it is a jump target, we need to insert a frame here.
1540 insertFrame = true;
1541 }
1542 u += 3;
1543 break;
1544 }
1545 case ClassWriter.ASM_LABELW_INSN: {
1546 // replaces the pseudo GOTO_W instruction with a real one.
1547 mv.visitJumpInsn(200, labels[offset + readInt(u + 1)]);
1548 // The instruction just after is a jump target (because pseudo
1549 // GOTO_W are used in patterns IFNOTxxx <L> GOTO_W <l> L:...,
1550 // see MethodWriter), so we need to insert a frame here.
1551 insertFrame = true;
1552 u += 5;
1553 break;
1554 }
1555 case ClassWriter.WIDE_INSN:
1556 opcode = b[u + 1] & 0xFF;
1557 if (opcode == Opcodes.IINC) {
1558 mv.visitIincInsn(readUnsignedShort(u + 2), readShort(u + 4));
1559 u += 6;
1560 } else {
1561 mv.visitVarInsn(opcode, readUnsignedShort(u + 2));
1562 u += 4;
1563 }
1564 break;
1565 case ClassWriter.TABL_INSN: {
1566 // skips 0 to 3 padding bytes
1567 u = u + 4 - (offset & 3);
1568 // reads instruction
1569 int label = offset + readInt(u);
1570 int min = readInt(u + 4);
1571 int max = readInt(u + 8);
1572 Label[] table = new Label[max - min + 1];
1573 u += 12;
1574 for (int i = 0; i < table.length; ++i) {
1790 u += 2;
1791 for (int i = 0; i < offsets.length; ++i) {
1792 offsets[i] = u;
1793 int target = readInt(u);
1794 switch (target >>> 24) {
1795 case 0x00: // CLASS_TYPE_PARAMETER
1796 case 0x01: // METHOD_TYPE_PARAMETER
1797 case 0x16: // METHOD_FORMAL_PARAMETER
1798 u += 2;
1799 break;
1800 case 0x13: // FIELD
1801 case 0x14: // METHOD_RETURN
1802 case 0x15: // METHOD_RECEIVER
1803 u += 1;
1804 break;
1805 case 0x40: // LOCAL_VARIABLE
1806 case 0x41: // RESOURCE_VARIABLE
1807 for (int j = readUnsignedShort(u + 1); j > 0; --j) {
1808 int start = readUnsignedShort(u + 3);
1809 int length = readUnsignedShort(u + 5);
1810 createLabel(start, context.labels);
1811 createLabel(start + length, context.labels);
1812 u += 6;
1813 }
1814 u += 3;
1815 break;
1816 case 0x47: // CAST
1817 case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
1818 case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
1819 case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
1820 case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
1821 u += 4;
1822 break;
1823 // case 0x10: // CLASS_EXTENDS
1824 // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
1825 // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
1826 // case 0x17: // THROWS
1827 // case 0x42: // EXCEPTION_PARAMETER
1828 // case 0x43: // INSTANCEOF
1829 // case 0x44: // NEW
1830 // case 0x45: // CONSTRUCTOR_REFERENCE
1831 // case 0x46: // METHOD_REFERENCE
1870 target &= 0xFFFF0000;
1871 u += 2;
1872 break;
1873 case 0x13: // FIELD
1874 case 0x14: // METHOD_RETURN
1875 case 0x15: // METHOD_RECEIVER
1876 target &= 0xFF000000;
1877 u += 1;
1878 break;
1879 case 0x40: // LOCAL_VARIABLE
1880 case 0x41: { // RESOURCE_VARIABLE
1881 target &= 0xFF000000;
1882 int n = readUnsignedShort(u + 1);
1883 context.start = new Label[n];
1884 context.end = new Label[n];
1885 context.index = new int[n];
1886 u += 3;
1887 for (int i = 0; i < n; ++i) {
1888 int start = readUnsignedShort(u);
1889 int length = readUnsignedShort(u + 2);
1890 context.start[i] = createLabel(start, context.labels);
1891 context.end[i] = createLabel(start + length, context.labels);
1892 context.index[i] = readUnsignedShort(u + 4);
1893 u += 6;
1894 }
1895 break;
1896 }
1897 case 0x47: // CAST
1898 case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
1899 case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
1900 case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
1901 case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
1902 target &= 0xFF0000FF;
1903 u += 4;
1904 break;
1905 // case 0x10: // CLASS_EXTENDS
1906 // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
1907 // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
1908 // case 0x17: // THROWS
1909 // case 0x42: // EXCEPTION_PARAMETER
1910 // case 0x43: // INSTANCEOF
1911 // case 0x44: // NEW
2291 } else { // if (tag == FULL_FRAME) {
2292 frame.mode = Opcodes.F_FULL;
2293 int n = readUnsignedShort(stackMap);
2294 stackMap += 2;
2295 frame.localDiff = n;
2296 frame.localCount = n;
2297 for (int local = 0; n > 0; n--) {
2298 stackMap = readFrameType(frame.local, local++, stackMap, c,
2299 labels);
2300 }
2301 n = readUnsignedShort(stackMap);
2302 stackMap += 2;
2303 frame.stackCount = n;
2304 for (int stack = 0; n > 0; n--) {
2305 stackMap = readFrameType(frame.stack, stack++, stackMap, c,
2306 labels);
2307 }
2308 }
2309 }
2310 frame.offset += delta + 1;
2311 createLabel(frame.offset, labels);
2312 return stackMap;
2313 }
2314
2315 /**
2316 * Reads a stack map frame type and stores it at the given index in the
2317 * given array.
2318 *
2319 * @param frame
2320 * the array where the parsed type must be stored.
2321 * @param index
2322 * the index in 'frame' where the parsed type must be stored.
2323 * @param v
2324 * the start offset of the stack map frame type to read.
2325 * @param buf
2326 * a buffer to read strings.
2327 * @param labels
2328 * the labels of the method currently being parsed, indexed by
2329 * their offset. If the parsed type is an Uninitialized type, a
2330 * new label for the corresponding NEW instruction is stored in
2331 * this array if it does not already exist.
2344 case 2:
2345 frame[index] = Opcodes.FLOAT;
2346 break;
2347 case 3:
2348 frame[index] = Opcodes.DOUBLE;
2349 break;
2350 case 4:
2351 frame[index] = Opcodes.LONG;
2352 break;
2353 case 5:
2354 frame[index] = Opcodes.NULL;
2355 break;
2356 case 6:
2357 frame[index] = Opcodes.UNINITIALIZED_THIS;
2358 break;
2359 case 7: // Object
2360 frame[index] = readClass(v, buf);
2361 v += 2;
2362 break;
2363 default: // Uninitialized
2364 frame[index] = createLabel(readUnsignedShort(v), labels);
2365 v += 2;
2366 }
2367 return v;
2368 }
2369
2370 /**
2371 * Returns the label corresponding to the given offset. The default
2372 * implementation of this method creates a label for the given offset if it
2373 * has not been already created.
2374 *
2375 * @param offset
2376 * a bytecode offset in a method.
2377 * @param labels
2378 * the already created labels, indexed by their offset. If a
2379 * label already exists for offset this method must not create a
2380 * new one. Otherwise it must store the new label in this array.
2381 * @return a non null Label, which must be equal to labels[offset].
2382 */
2383 protected Label readLabel(int offset, Label[] labels) {
2384 if (labels[offset] == null) {
2385 labels[offset] = new Label();
2386 }
2387 return labels[offset];
2388 }
2389
2390 /**
2391 * Creates a label without the Label.DEBUG flag set, for the given offset.
2392 * The label is created with a call to {@link #readLabel} and its
2393 * Label.DEBUG flag is cleared.
2394 *
2395 * @param offset
2396 * a bytecode offset in a method.
2397 * @param labels
2398 * the already created labels, indexed by their offset.
2399 * @return a Label without the Label.DEBUG flag set.
2400 */
2401 private Label createLabel(int offset, Label[] labels) {
2402 Label label = readLabel(offset, labels);
2403 label.status &= ~Label.DEBUG;
2404 return label;
2405 }
2406
2407 /**
2408 * Creates a label with the Label.DEBUG flag set, if there is no already
2409 * existing label for the given offset (otherwise does nothing). The label
2410 * is created with a call to {@link #readLabel}.
2411 *
2412 * @param offset
2413 * a bytecode offset in a method.
2414 * @param labels
2415 * the already created labels, indexed by their offset.
2416 */
2417 private void createDebugLabel(int offset, Label[] labels) {
2418 if (labels[offset] == null) {
2419 readLabel(offset, labels).status |= Label.DEBUG;
2420 }
2421 }
2422
2423 /**
2424 * Returns the start index of the attribute_info structure of this class.
2425 *
2426 * @return the start index of the attribute_info structure of this class.
2427 */
2428 private int getAttributes() {
2429 // skips the header
2430 int u = header + 8 + readUnsignedShort(header + 6) * 2;
2431 // skips fields and methods
2432 for (int i = readUnsignedShort(u); i > 0; --i) {
2433 for (int j = readUnsignedShort(u + 8); j > 0; --j) {
2434 u += 6 + readInt(u + 12);
2435 }
2436 u += 8;
2437 }
2438 u += 2;
2439 for (int i = readUnsignedShort(u); i > 0; --i) {
2440 for (int j = readUnsignedShort(u + 8); j > 0; --j) {
2441 u += 6 + readInt(u + 12);
2442 }
2443 u += 8;
2658 cc = (char) (c & 0x0F);
2659 st = 2;
2660 }
2661 break;
2662
2663 case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char
2664 buf[strLen++] = (char) ((cc << 6) | (c & 0x3F));
2665 st = 0;
2666 break;
2667
2668 case 2: // byte 2 of 3-byte char
2669 cc = (char) ((cc << 6) | (c & 0x3F));
2670 st = 1;
2671 break;
2672 }
2673 }
2674 return new String(buf, 0, strLen);
2675 }
2676
2677 /**
2678 * Read a stringish constant item (CONSTANT_Class, CONSTANT_String,
2679 * CONSTANT_MethodType, CONSTANT_Module or CONSTANT_Package
2680 * @param index
2681 * @param buf
2682 * @return
2683 */
2684 private String readStringish(final int index, final char[] buf) {
2685 // computes the start index of the item in b
2686 // and reads the CONSTANT_Utf8 item designated by
2687 // the first two bytes of this item
2688 return readUTF8(items[readUnsignedShort(index)], buf);
2689 }
2690
2691 /**
2692 * Reads a class constant pool item in {@link #b b}. <i>This method is
2693 * intended for {@link Attribute} sub classes, and is normally not needed by
2694 * class generators or adapters.</i>
2695 *
2696 * @param index
2697 * the start index of an unsigned short value in {@link #b b},
2698 * whose value is the index of a class constant pool item.
2699 * @param buf
2700 * buffer to be used to read the item. This buffer must be
2701 * sufficiently large. It is not automatically resized.
2702 * @return the String corresponding to the specified class item.
2703 */
2704 public String readClass(final int index, final char[] buf) {
2705 return readStringish(index, buf);
2706 }
2707
2708 /**
2709 * Reads a module constant pool item in {@link #b b}. <i>This method is
2710 * intended for {@link Attribute} sub classes, and is normally not needed by
2711 * class generators or adapters.</i>
2712 *
2713 * @param index
2714 * the start index of an unsigned short value in {@link #b b},
2715 * whose value is the index of a module constant pool item.
2716 * @param buf
2717 * buffer to be used to read the item. This buffer must be
2718 * sufficiently large. It is not automatically resized.
2719 * @return the String corresponding to the specified module item.
2720 */
2721 public String readModule(final int index, final char[] buf) {
2722 return readStringish(index, buf);
2723 }
2724
2725 /**
2726 * Reads a module constant pool item in {@link #b b}. <i>This method is
2727 * intended for {@link Attribute} sub classes, and is normally not needed by
2728 * class generators or adapters.</i>
2729 *
2730 * @param index
2731 * the start index of an unsigned short value in {@link #b b},
2732 * whose value is the index of a module constant pool item.
2733 * @param buf
2734 * buffer to be used to read the item. This buffer must be
2735 * sufficiently large. It is not automatically resized.
2736 * @return the String corresponding to the specified module item.
2737 */
2738 public String readPackage(final int index, final char[] buf) {
2739 return readStringish(index, buf);
2740 }
2741
2742 /**
2743 * Reads a numeric or string constant pool item in {@link #b b}. <i>This
2744 * method is intended for {@link Attribute} sub classes, and is normally not
2745 * needed by class generators or adapters.</i>
2746 *
2747 * @param item
2748 * the index of a constant pool item.
2749 * @param buf
2750 * buffer to be used to read the item. This buffer must be
2751 * sufficiently large. It is not automatically resized.
2752 * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double},
2753 * {@link String}, {@link Type} or {@link Handle} corresponding to
2754 * the given constant pool item.
2755 */
2756 public Object readConst(final int item, final char[] buf) {
2757 int index = items[item];
2758 switch (b[index - 1]) {
2759 case ClassWriter.INT:
2760 return readInt(index);
2761 case ClassWriter.FLOAT:
2762 return Float.intBitsToFloat(readInt(index));
2763 case ClassWriter.LONG:
2764 return readLong(index);
2765 case ClassWriter.DOUBLE:
2766 return Double.longBitsToDouble(readLong(index));
2767 case ClassWriter.CLASS:
2768 return Type.getObjectType(readUTF8(index, buf));
2769 case ClassWriter.STR:
2770 return readUTF8(index, buf);
2771 case ClassWriter.MTYPE:
2772 return Type.getMethodType(readUTF8(index, buf));
2773 default: // case ClassWriter.HANDLE_BASE + [1..9]:
2774 int tag = readByte(index);
2775 int[] items = this.items;
2776 int cpIndex = items[readUnsignedShort(index + 1)];
2777 boolean itf = b[cpIndex - 1] == ClassWriter.IMETH;
2778 String owner = readClass(cpIndex, buf);
2779 cpIndex = items[readUnsignedShort(cpIndex + 2)];
2780 String name = readUTF8(cpIndex, buf);
2781 String desc = readUTF8(cpIndex + 2, buf);
2782 return new Handle(tag, owner, name, desc, itf);
2783 }
2784 }
2785 }
|