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