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