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