1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. Oracle designates this 7 * particular file as subject to the "Classpath" exception as provided 8 * by Oracle in the LICENSE file that accompanied this code. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 */ 24 25 /* 26 * This file is available under and governed by the GNU General Public 27 * License version 2 only, as published by the Free Software Foundation. 28 * However, the following notice accompanied the original version of this 29 * file: 30 * 31 * ASM: a very small and fast Java bytecode manipulation framework 32 * Copyright (c) 2000-2011 INRIA, France Telecom 33 * All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. Neither the name of the copyright holders nor the names of its 44 * contributors may be used to endorse or promote products derived from 45 * this software without specific prior written permission. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 51 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 52 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 53 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 54 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 57 * THE POSSIBILITY OF SUCH DAMAGE. 58 */ 59 package jdk.internal.org.objectweb.asm; 60 61 import java.io.IOException; 62 import java.io.InputStream; 63 64 /** 65 * A Java class parser to make a {@link ClassVisitor} visit an existing class. 66 * This class parses a byte array conforming to the Java class file format and 67 * calls the appropriate visit methods of a given class visitor for each field, 68 * method and bytecode instruction encountered. 69 * 70 * @author Eric Bruneton 71 * @author Eugene Kuleshov 72 */ 73 public class ClassReader { 74 75 /** 76 * Flag to skip method code. If this class is set <code>CODE</code> 77 * attribute won't be visited. This can be used, for example, to retrieve 78 * annotations for methods and method parameters. 79 */ 80 public static final int SKIP_CODE = 1; 81 82 /** 83 * Flag to skip the debug information in the class. If this flag is set the 84 * debug information of the class is not visited, i.e. the 85 * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and 86 * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be 87 * called. 88 */ 89 public static final int SKIP_DEBUG = 2; 90 91 /** 92 * Flag to skip the stack map frames in the class. If this flag is set the 93 * stack map frames of the class is not visited, i.e. the 94 * {@link MethodVisitor#visitFrame visitFrame} method will not be called. 95 * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is 96 * used: it avoids visiting frames that will be ignored and recomputed from 97 * scratch in the class writer. 98 */ 99 public static final int SKIP_FRAMES = 4; 100 101 /** 102 * Flag to expand the stack map frames. By default stack map frames are 103 * visited in their original format (i.e. "expanded" for classes whose 104 * version is less than V1_6, and "compressed" for the other classes). If 105 * this flag is set, stack map frames are always visited in expanded format 106 * (this option adds a decompression/recompression step in ClassReader and 107 * ClassWriter which degrades performances quite a lot). 108 */ 109 public static final int EXPAND_FRAMES = 8; 110 111 /** 112 * Flag to expand the ASM pseudo instructions into an equivalent sequence of 113 * standard bytecode instructions. When resolving a forward jump it may 114 * happen that the signed 2 bytes offset reserved for it is not sufficient 115 * to store the bytecode offset. In this case the jump instruction is 116 * replaced with a temporary ASM pseudo instruction using an unsigned 2 117 * bytes offset (see Label#resolve). This internal flag is used to re-read 118 * classes containing such instructions, in order to replace them with 119 * standard instructions. In addition, when this flag is used, GOTO_W and 120 * JSR_W are <i>not</i> converted into GOTO and JSR, to make sure that 121 * infinite loops where a GOTO_W is replaced with a GOTO in ClassReader and 122 * converted back to a GOTO_W in ClassWriter cannot occur. 123 */ 124 static final int EXPAND_ASM_INSNS = 256; 125 126 /** 127 * The class to be parsed. <i>The content of this array must not be 128 * modified. This field is intended for {@link Attribute} sub classes, and 129 * is normally not needed by class generators or adapters.</i> 130 */ 131 public final byte[] b; 132 133 /** 134 * The start index of each constant pool item in {@link #b b}, plus one. The 135 * one byte offset skips the constant pool item tag that indicates its type. 136 */ 137 private final int[] items; 138 139 /** 140 * The String objects corresponding to the CONSTANT_Utf8 items. This cache 141 * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item, 142 * which GREATLY improves performances (by a factor 2 to 3). This caching 143 * strategy could be extended to all constant pool items, but its benefit 144 * would not be so great for these items (because they are much less 145 * expensive to parse than CONSTANT_Utf8 items). 146 */ 147 private final String[] strings; 148 149 /** 150 * Maximum length of the strings contained in the constant pool of the 151 * class. 152 */ 153 private final int maxStringLength; 154 155 /** 156 * Start index of the class header information (access, name...) in 157 * {@link #b b}. 158 */ 159 public final int header; 160 161 // ------------------------------------------------------------------------ 162 // Constructors 163 // ------------------------------------------------------------------------ 164 165 /** 166 * Constructs a new {@link ClassReader} object. 167 * 168 * @param b 169 * the bytecode of the class to be read. 170 */ 171 public ClassReader(final byte[] b) { 172 this(b, 0, b.length); 173 } 174 175 /** 176 * Constructs a new {@link ClassReader} object. 177 * 178 * @param b 179 * the bytecode of the class to be read. 180 * @param off 181 * the start offset of the class data. 182 * @param len 183 * the length of the class data. 184 */ 185 public ClassReader(final byte[] b, final int off, final int len) { 186 this.b = b; 187 // checks the class version 188 if (readShort(off + 6) > Opcodes.V9) { 189 throw new IllegalArgumentException(); 190 } 191 // parses the constant pool 192 items = new int[readUnsignedShort(off + 8)]; 193 int n = items.length; 194 strings = new String[n]; 195 int max = 0; 196 int index = off + 10; 197 for (int i = 1; i < n; ++i) { 198 items[i] = index + 1; 199 int size; 200 switch (b[index]) { 201 case ClassWriter.FIELD: 202 case ClassWriter.METH: 203 case ClassWriter.IMETH: 204 case ClassWriter.INT: 205 case ClassWriter.FLOAT: 206 case ClassWriter.NAME_TYPE: 207 case ClassWriter.INDY: 208 size = 5; 209 break; 210 case ClassWriter.LONG: 211 case ClassWriter.DOUBLE: 212 size = 9; 213 ++i; 214 break; 215 case ClassWriter.UTF8: 216 size = 3 + readUnsignedShort(index + 1); 217 if (size > max) { 218 max = size; 219 } 220 break; 221 case ClassWriter.HANDLE: 222 size = 4; 223 break; 224 // case ClassWriter.CLASS: 225 // case ClassWriter.STR: 226 // case ClassWriter.MTYPE 227 // case ClassWriter.PACKAGE: 228 // case ClassWriter.MODULE: 229 default: 230 size = 3; 231 break; 232 } 233 index += size; 234 } 235 maxStringLength = max; 236 // the class header information starts just after the constant pool 237 header = index; 238 } 239 240 /** 241 * Returns the class's access flags (see {@link Opcodes}). This value may 242 * not reflect Deprecated and Synthetic flags when bytecode is before 1.5 243 * and those flags are represented by attributes. 244 * 245 * @return the class access flags 246 * 247 * @see ClassVisitor#visit(int, int, String, String, String, String[]) 248 */ 249 public int getAccess() { 250 return readUnsignedShort(header); 251 } 252 253 /** 254 * Returns the internal name of the class (see 255 * {@link Type#getInternalName() getInternalName}). 256 * 257 * @return the internal class name 258 * 259 * @see ClassVisitor#visit(int, int, String, String, String, String[]) 260 */ 261 public String getClassName() { 262 return readClass(header + 2, new char[maxStringLength]); 263 } 264 265 /** 266 * Returns the internal of name of the super class (see 267 * {@link Type#getInternalName() getInternalName}). For interfaces, the 268 * super class is {@link Object}. 269 * 270 * @return the internal name of super class, or <tt>null</tt> for 271 * {@link Object} class. 272 * 273 * @see ClassVisitor#visit(int, int, String, String, String, String[]) 274 */ 275 public String getSuperName() { 276 return readClass(header + 4, new char[maxStringLength]); 277 } 278 279 /** 280 * Returns the internal names of the class's interfaces (see 281 * {@link Type#getInternalName() getInternalName}). 282 * 283 * @return the array of internal names for all implemented interfaces or 284 * <tt>null</tt>. 285 * 286 * @see ClassVisitor#visit(int, int, String, String, String, String[]) 287 */ 288 public String[] getInterfaces() { 289 int index = header + 6; 290 int n = readUnsignedShort(index); 291 String[] interfaces = new String[n]; 292 if (n > 0) { 293 char[] buf = new char[maxStringLength]; 294 for (int i = 0; i < n; ++i) { 295 index += 2; 296 interfaces[i] = readClass(index, buf); 297 } 298 } 299 return interfaces; 300 } 301 302 /** 303 * Copies the constant pool data into the given {@link ClassWriter}. Should 304 * be called before the {@link #accept(ClassVisitor,int)} method. 305 * 306 * @param classWriter 307 * the {@link ClassWriter} to copy constant pool into. 308 */ 309 void copyPool(final ClassWriter classWriter) { 310 char[] buf = new char[maxStringLength]; 311 int ll = items.length; 312 Item[] items2 = new Item[ll]; 313 for (int i = 1; i < ll; i++) { 314 int index = items[i]; 315 int tag = b[index - 1]; 316 Item item = new Item(i); 317 int nameType; 318 switch (tag) { 319 case ClassWriter.FIELD: 320 case ClassWriter.METH: 321 case ClassWriter.IMETH: 322 nameType = items[readUnsignedShort(index + 2)]; 323 item.set(tag, readClass(index, buf), readUTF8(nameType, buf), 324 readUTF8(nameType + 2, buf)); 325 break; 326 case ClassWriter.INT: 327 item.set(readInt(index)); 328 break; 329 case ClassWriter.FLOAT: 330 item.set(Float.intBitsToFloat(readInt(index))); 331 break; 332 case ClassWriter.NAME_TYPE: 333 item.set(tag, readUTF8(index, buf), readUTF8(index + 2, buf), 334 null); 335 break; 336 case ClassWriter.LONG: 337 item.set(readLong(index)); 338 ++i; 339 break; 340 case ClassWriter.DOUBLE: 341 item.set(Double.longBitsToDouble(readLong(index))); 342 ++i; 343 break; 344 case ClassWriter.UTF8: { 345 String s = strings[i]; 346 if (s == null) { 347 index = items[i]; 348 s = strings[i] = readUTF(index + 2, 349 readUnsignedShort(index), buf); 350 } 351 item.set(tag, s, null, null); 352 break; 353 } 354 case ClassWriter.HANDLE: { 355 int fieldOrMethodRef = items[readUnsignedShort(index + 1)]; 356 nameType = items[readUnsignedShort(fieldOrMethodRef + 2)]; 357 item.set(ClassWriter.HANDLE_BASE + readByte(index), 358 readClass(fieldOrMethodRef, buf), 359 readUTF8(nameType, buf), readUTF8(nameType + 2, buf)); 360 break; 361 } 362 case ClassWriter.INDY: 363 if (classWriter.bootstrapMethods == null) { 364 copyBootstrapMethods(classWriter, items2, buf); 365 } 366 nameType = items[readUnsignedShort(index + 2)]; 367 item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf), 368 readUnsignedShort(index)); 369 break; 370 // case ClassWriter.STR: 371 // case ClassWriter.CLASS: 372 // case ClassWriter.MTYPE: 373 // case ClassWriter.MODULE: 374 // case ClassWriter.PACKAGE: 375 default: 376 item.set(tag, readUTF8(index, buf), null, null); 377 break; 378 } 379 380 int index2 = item.hashCode % items2.length; 381 item.next = items2[index2]; 382 items2[index2] = item; 383 } 384 385 int off = items[1] - 1; 386 classWriter.pool.putByteArray(b, off, header - off); 387 classWriter.items = items2; 388 classWriter.threshold = (int) (0.75d * ll); 389 classWriter.index = ll; 390 } 391 392 /** 393 * Copies the bootstrap method data into the given {@link ClassWriter}. 394 * Should be called before the {@link #accept(ClassVisitor,int)} method. 395 * 396 * @param classWriter 397 * the {@link ClassWriter} to copy bootstrap methods into. 398 */ 399 private void copyBootstrapMethods(final ClassWriter classWriter, 400 final Item[] items, final char[] c) { 401 // finds the "BootstrapMethods" attribute 402 int u = getAttributes(); 403 boolean found = false; 404 for (int i = readUnsignedShort(u); i > 0; --i) { 405 String attrName = readUTF8(u + 2, c); 406 if ("BootstrapMethods".equals(attrName)) { 407 found = true; 408 break; 409 } 410 u += 6 + readInt(u + 4); 411 } 412 if (!found) { 413 return; 414 } 415 // copies the bootstrap methods in the class writer 416 int boostrapMethodCount = readUnsignedShort(u + 8); 417 for (int j = 0, v = u + 10; j < boostrapMethodCount; j++) { 418 int position = v - u - 10; 419 int hashCode = readConst(readUnsignedShort(v), c).hashCode(); 420 for (int k = readUnsignedShort(v + 2); k > 0; --k) { 421 hashCode ^= readConst(readUnsignedShort(v + 4), c).hashCode(); 422 v += 2; 423 } 424 v += 4; 425 Item item = new Item(j); 426 item.set(position, hashCode & 0x7FFFFFFF); 427 int index = item.hashCode % items.length; 428 item.next = items[index]; 429 items[index] = item; 430 } 431 int attrSize = readInt(u + 4); 432 ByteVector bootstrapMethods = new ByteVector(attrSize + 62); 433 bootstrapMethods.putByteArray(b, u + 10, attrSize - 2); 434 classWriter.bootstrapMethodsCount = boostrapMethodCount; 435 classWriter.bootstrapMethods = bootstrapMethods; 436 } 437 438 /** 439 * Constructs a new {@link ClassReader} object. 440 * 441 * @param is 442 * an input stream from which to read the class. 443 * @throws IOException 444 * if a problem occurs during reading. 445 */ 446 public ClassReader(final InputStream is) throws IOException { 447 this(readClass(is, false)); 448 } 449 450 /** 451 * Constructs a new {@link ClassReader} object. 452 * 453 * @param name 454 * the binary qualified name of the class to be read. 455 * @throws IOException 456 * if an exception occurs during reading. 457 */ 458 public ClassReader(final String name) throws IOException { 459 this(readClass( 460 ClassLoader.getSystemResourceAsStream(name.replace('.', '/') 461 + ".class"), true)); 462 } 463 464 /** 465 * Reads the bytecode of a class. 466 * 467 * @param is 468 * an input stream from which to read the class. 469 * @param close 470 * true to close the input stream after reading. 471 * @return the bytecode read from the given input stream. 472 * @throws IOException 473 * if a problem occurs during reading. 474 */ 475 private static byte[] readClass(final InputStream is, boolean close) 476 throws IOException { 477 if (is == null) { 478 throw new IOException("Class not found"); 479 } 480 try { 481 byte[] b = new byte[is.available()]; 482 int len = 0; 483 while (true) { 484 int n = is.read(b, len, b.length - len); 485 if (n == -1) { 486 if (len < b.length) { 487 byte[] c = new byte[len]; 488 System.arraycopy(b, 0, c, 0, len); 489 b = c; 490 } 491 return b; 492 } 493 len += n; 494 if (len == b.length) { 495 int last = is.read(); 496 if (last < 0) { 497 return b; 498 } 499 byte[] c = new byte[b.length + 1000]; 500 System.arraycopy(b, 0, c, 0, len); 501 c[len++] = (byte) last; 502 b = c; 503 } 504 } 505 } finally { 506 if (close) { 507 is.close(); 508 } 509 } 510 } 511 512 // ------------------------------------------------------------------------ 513 // Public methods 514 // ------------------------------------------------------------------------ 515 516 /** 517 * Makes the given visitor visit the Java class of this {@link ClassReader} 518 * . This class is the one specified in the constructor (see 519 * {@link #ClassReader(byte[]) ClassReader}). 520 * 521 * @param classVisitor 522 * the visitor that must visit this class. 523 * @param flags 524 * option flags that can be used to modify the default behavior 525 * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES} 526 * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}. 527 */ 528 public void accept(final ClassVisitor classVisitor, final int flags) { 529 accept(classVisitor, new Attribute[0], flags); 530 } 531 532 /** 533 * Makes the given visitor visit the Java class of this {@link ClassReader}. 534 * This class is the one specified in the constructor (see 535 * {@link #ClassReader(byte[]) ClassReader}). 536 * 537 * @param classVisitor 538 * the visitor that must visit this class. 539 * @param attrs 540 * prototypes of the attributes that must be parsed during the 541 * visit of the class. Any attribute whose type is not equal to 542 * the type of one the prototypes will not be parsed: its byte 543 * array value will be passed unchanged to the ClassWriter. 544 * <i>This may corrupt it if this value contains references to 545 * the constant pool, or has syntactic or semantic links with a 546 * class element that has been transformed by a class adapter 547 * between the reader and the writer</i>. 548 * @param flags 549 * option flags that can be used to modify the default behavior 550 * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES} 551 * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}. 552 */ 553 public void accept(final ClassVisitor classVisitor, 554 final Attribute[] attrs, final int flags) { 555 int u = header; // current offset in the class file 556 char[] c = new char[maxStringLength]; // buffer used to read strings 557 558 Context context = new Context(); 559 context.attrs = attrs; 560 context.flags = flags; 561 context.buffer = c; 562 563 // reads the class declaration 564 int access = readUnsignedShort(u); 565 String name = readClass(u + 2, c); 566 String superClass = readClass(u + 4, c); 567 String[] interfaces = new String[readUnsignedShort(u + 6)]; 568 u += 8; 569 for (int i = 0; i < interfaces.length; ++i) { 570 interfaces[i] = readClass(u, c); 571 u += 2; 572 } 573 574 // reads the class attributes 575 String signature = null; 576 String sourceFile = null; 577 String sourceDebug = null; 578 String enclosingOwner = null; 579 String enclosingName = null; 580 String enclosingDesc = null; 581 String moduleMainClass = null; 582 int anns = 0; 583 int ianns = 0; 584 int tanns = 0; 585 int itanns = 0; 586 int innerClasses = 0; 587 int module = 0; 588 int packages = 0; 589 Attribute attributes = null; 590 591 u = getAttributes(); 592 for (int i = readUnsignedShort(u); i > 0; --i) { 593 String attrName = readUTF8(u + 2, c); 594 // tests are sorted in decreasing frequency order 595 // (based on frequencies observed on typical classes) 596 if ("SourceFile".equals(attrName)) { 597 sourceFile = readUTF8(u + 8, c); 598 } else if ("InnerClasses".equals(attrName)) { 599 innerClasses = u + 8; 600 } else if ("EnclosingMethod".equals(attrName)) { 601 enclosingOwner = readClass(u + 8, c); 602 int item = readUnsignedShort(u + 10); 603 if (item != 0) { 604 enclosingName = readUTF8(items[item], c); 605 enclosingDesc = readUTF8(items[item] + 2, c); 606 } 607 } else if ("Signature".equals(attrName)) { 608 signature = readUTF8(u + 8, c); 609 } else if ("RuntimeVisibleAnnotations".equals(attrName)) { 610 anns = u + 8; 611 } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) { 612 tanns = u + 8; 613 } else if ("Deprecated".equals(attrName)) { 614 access |= Opcodes.ACC_DEPRECATED; 615 } else if ("Synthetic".equals(attrName)) { 616 access |= Opcodes.ACC_SYNTHETIC 617 | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; 618 } else if ("SourceDebugExtension".equals(attrName)) { 619 int len = readInt(u + 4); 620 sourceDebug = readUTF(u + 8, len, new char[len]); 621 } else if ("RuntimeInvisibleAnnotations".equals(attrName)) { 622 ianns = u + 8; 623 } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) { 624 itanns = u + 8; 625 } else if ("Module".equals(attrName)) { 626 module = u + 8; 627 } else if ("ModuleMainClass".equals(attrName)) { 628 moduleMainClass = readClass(u + 8, c); 629 } else if ("ModulePackages".equals(attrName)) { 630 packages = u + 10; 631 } else if ("BootstrapMethods".equals(attrName)) { 632 int[] bootstrapMethods = new int[readUnsignedShort(u + 8)]; 633 for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) { 634 bootstrapMethods[j] = v; 635 v += 2 + readUnsignedShort(v + 2) << 1; 636 } 637 context.bootstrapMethods = bootstrapMethods; 638 } else { 639 Attribute attr = readAttribute(attrs, attrName, u + 8, 640 readInt(u + 4), c, -1, null); 641 if (attr != null) { 642 attr.next = attributes; 643 attributes = attr; 644 } 645 } 646 u += 6 + readInt(u + 4); 647 } 648 649 // visits the class declaration 650 classVisitor.visit(readInt(items[1] - 7), access, name, signature, 651 superClass, interfaces); 652 653 // visits the source and debug info 654 if ((flags & SKIP_DEBUG) == 0 655 && (sourceFile != null || sourceDebug != null)) { 656 classVisitor.visitSource(sourceFile, sourceDebug); 657 } 658 659 // visits the module info and associated attributes 660 if (module != 0) { 661 readModule(classVisitor, context, module, 662 moduleMainClass, packages); 663 } 664 665 // visits the outer class 666 if (enclosingOwner != null) { 667 classVisitor.visitOuterClass(enclosingOwner, enclosingName, 668 enclosingDesc); 669 } 670 671 // visits the class annotations and type annotations 672 if (anns != 0) { 673 for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { 674 v = readAnnotationValues(v + 2, c, true, 675 classVisitor.visitAnnotation(readUTF8(v, c), true)); 676 } 677 } 678 if (ianns != 0) { 679 for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { 680 v = readAnnotationValues(v + 2, c, true, 681 classVisitor.visitAnnotation(readUTF8(v, c), false)); 682 } 683 } 684 if (tanns != 0) { 685 for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { 686 v = readAnnotationTarget(context, v); 687 v = readAnnotationValues(v + 2, c, true, 688 classVisitor.visitTypeAnnotation(context.typeRef, 689 context.typePath, readUTF8(v, c), true)); 690 } 691 } 692 if (itanns != 0) { 693 for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { 694 v = readAnnotationTarget(context, v); 695 v = readAnnotationValues(v + 2, c, true, 696 classVisitor.visitTypeAnnotation(context.typeRef, 697 context.typePath, readUTF8(v, c), false)); 698 } 699 } 700 701 // visits the attributes 702 while (attributes != null) { 703 Attribute attr = attributes.next; 704 attributes.next = null; 705 classVisitor.visitAttribute(attributes); 706 attributes = attr; 707 } 708 709 // visits the inner classes 710 if (innerClasses != 0) { 711 int v = innerClasses + 2; 712 for (int i = readUnsignedShort(innerClasses); i > 0; --i) { 713 classVisitor.visitInnerClass(readClass(v, c), 714 readClass(v + 2, c), readUTF8(v + 4, c), 715 readUnsignedShort(v + 6)); 716 v += 8; 717 } 718 } 719 720 // visits the fields and methods 721 u = header + 10 + 2 * interfaces.length; 722 for (int i = readUnsignedShort(u - 2); i > 0; --i) { 723 u = readField(classVisitor, context, u); 724 } 725 u += 2; 726 for (int i = readUnsignedShort(u - 2); i > 0; --i) { 727 u = readMethod(classVisitor, context, u); 728 } 729 730 // visits the end of the class 731 classVisitor.visitEnd(); 732 } 733 734 /** 735 * Reads the module attribute and visit it. 736 * 737 * @param classVisitor 738 * the current class visitor 739 * @param context 740 * information about the class being parsed. 741 * @param u 742 * start offset of the module attribute in the class file. 743 * @param mainClass 744 * name of the main class of a module or null. 745 * @param packages 746 * start offset of the concealed package attribute. 747 */ 748 private void readModule(final ClassVisitor classVisitor, 749 final Context context, int u, 750 final String mainClass, int packages) { 751 752 char[] buffer = context.buffer; 753 754 // reads module name, flags and version 755 String name = readModule(u, buffer); 756 int flags = readUnsignedShort(u + 2); 757 String version = readUTF8(u + 4, buffer); 758 u += 6; 759 760 ModuleVisitor mv = classVisitor.visitModule(name, flags, version); 761 if (mv == null) { 762 return; 763 } 764 765 // module attributes (main class, packages) 766 if (mainClass != null) { 767 mv.visitMainClass(mainClass); 768 } 769 770 if (packages != 0) { 771 for (int i = readUnsignedShort(packages - 2); i > 0; --i) { 772 String packaze = readPackage(packages, buffer); 773 mv.visitPackage(packaze); 774 packages += 2; 775 } 776 } 777 778 // reads requires 779 u += 2; 780 for (int i = readUnsignedShort(u - 2); i > 0; --i) { 781 String module = readModule(u, buffer); 782 int access = readUnsignedShort(u + 2); 783 String requireVersion = readUTF8(u + 4, buffer); 784 mv.visitRequire(module, access, requireVersion); 785 u += 6; 786 } 787 788 // reads exports 789 u += 2; 790 for (int i = readUnsignedShort(u - 2); i > 0; --i) { 791 String export = readPackage(u, buffer); 792 int access = readUnsignedShort(u + 2); 793 int exportToCount = readUnsignedShort(u + 4); 794 u += 6; 795 String[] tos = null; 796 if (exportToCount != 0) { 797 tos = new String[exportToCount]; 798 for (int j = 0; j < tos.length; ++j) { 799 tos[j] = readModule(u, buffer); 800 u += 2; 801 } 802 } 803 mv.visitExport(export, access, tos); 804 } 805 806 // reads opens 807 u += 2; 808 for (int i = readUnsignedShort(u - 2); i > 0; --i) { 809 String open = readPackage(u, buffer); 810 int access = readUnsignedShort(u + 2); 811 int openToCount = readUnsignedShort(u + 4); 812 u += 6; 813 String[] tos = null; 814 if (openToCount != 0) { 815 tos = new String[openToCount]; 816 for (int j = 0; j < tos.length; ++j) { 817 tos[j] = readModule(u, buffer); 818 u += 2; 819 } 820 } 821 mv.visitOpen(open, access, tos); 822 } 823 824 // read uses 825 u += 2; 826 for (int i = readUnsignedShort(u - 2); i > 0; --i) { 827 mv.visitUse(readClass(u, buffer)); 828 u += 2; 829 } 830 831 // read provides 832 u += 2; 833 for (int i = readUnsignedShort(u - 2); i > 0; --i) { 834 String service = readClass(u, buffer); 835 int provideWithCount = readUnsignedShort(u + 2); 836 u += 4; 837 String[] withs = new String[provideWithCount]; 838 for (int j = 0; j < withs.length; ++j) { 839 withs[j] = readClass(u, buffer); 840 u += 2; 841 } 842 mv.visitProvide(service, withs); 843 } 844 845 mv.visitEnd(); 846 } 847 848 /** 849 * Reads a field and makes the given visitor visit it. 850 * 851 * @param classVisitor 852 * the visitor that must visit the field. 853 * @param context 854 * information about the class being parsed. 855 * @param u 856 * the start offset of the field in the class file. 857 * @return the offset of the first byte following the field in the class. 858 */ 859 private int readField(final ClassVisitor classVisitor, 860 final Context context, int u) { 861 // reads the field declaration 862 char[] c = context.buffer; 863 int access = readUnsignedShort(u); 864 String name = readUTF8(u + 2, c); 865 String desc = readUTF8(u + 4, c); 866 u += 6; 867 868 // reads the field attributes 869 String signature = null; 870 int anns = 0; 871 int ianns = 0; 872 int tanns = 0; 873 int itanns = 0; 874 Object value = null; 875 Attribute attributes = null; 876 877 for (int i = readUnsignedShort(u); i > 0; --i) { 878 String attrName = readUTF8(u + 2, c); 879 // tests are sorted in decreasing frequency order 880 // (based on frequencies observed on typical classes) 881 if ("ConstantValue".equals(attrName)) { 882 int item = readUnsignedShort(u + 8); 883 value = item == 0 ? null : readConst(item, c); 884 } else if ("Signature".equals(attrName)) { 885 signature = readUTF8(u + 8, c); 886 } else if ("Deprecated".equals(attrName)) { 887 access |= Opcodes.ACC_DEPRECATED; 888 } else if ("Synthetic".equals(attrName)) { 889 access |= Opcodes.ACC_SYNTHETIC 890 | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; 891 } else if ("RuntimeVisibleAnnotations".equals(attrName)) { 892 anns = u + 8; 893 } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) { 894 tanns = u + 8; 895 } else if ("RuntimeInvisibleAnnotations".equals(attrName)) { 896 ianns = u + 8; 897 } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) { 898 itanns = u + 8; 899 } else { 900 Attribute attr = readAttribute(context.attrs, attrName, u + 8, 901 readInt(u + 4), c, -1, null); 902 if (attr != null) { 903 attr.next = attributes; 904 attributes = attr; 905 } 906 } 907 u += 6 + readInt(u + 4); 908 } 909 u += 2; 910 911 // visits the field declaration 912 FieldVisitor fv = classVisitor.visitField(access, name, desc, 913 signature, value); 914 if (fv == null) { 915 return u; 916 } 917 918 // visits the field annotations and type annotations 919 if (anns != 0) { 920 for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { 921 v = readAnnotationValues(v + 2, c, true, 922 fv.visitAnnotation(readUTF8(v, c), true)); 923 } 924 } 925 if (ianns != 0) { 926 for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { 927 v = readAnnotationValues(v + 2, c, true, 928 fv.visitAnnotation(readUTF8(v, c), false)); 929 } 930 } 931 if (tanns != 0) { 932 for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { 933 v = readAnnotationTarget(context, v); 934 v = readAnnotationValues(v + 2, c, true, 935 fv.visitTypeAnnotation(context.typeRef, 936 context.typePath, readUTF8(v, c), true)); 937 } 938 } 939 if (itanns != 0) { 940 for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { 941 v = readAnnotationTarget(context, v); 942 v = readAnnotationValues(v + 2, c, true, 943 fv.visitTypeAnnotation(context.typeRef, 944 context.typePath, readUTF8(v, c), false)); 945 } 946 } 947 948 // visits the field attributes 949 while (attributes != null) { 950 Attribute attr = attributes.next; 951 attributes.next = null; 952 fv.visitAttribute(attributes); 953 attributes = attr; 954 } 955 956 // visits the end of the field 957 fv.visitEnd(); 958 959 return u; 960 } 961 962 /** 963 * Reads a method and makes the given visitor visit it. 964 * 965 * @param classVisitor 966 * the visitor that must visit the method. 967 * @param context 968 * information about the class being parsed. 969 * @param u 970 * the start offset of the method in the class file. 971 * @return the offset of the first byte following the method in the class. 972 */ 973 private int readMethod(final ClassVisitor classVisitor, 974 final Context context, int u) { 975 // reads the method declaration 976 char[] c = context.buffer; 977 context.access = readUnsignedShort(u); 978 context.name = readUTF8(u + 2, c); 979 context.desc = readUTF8(u + 4, c); 980 u += 6; 981 982 // reads the method attributes 983 int code = 0; 984 int exception = 0; 985 String[] exceptions = null; 986 String signature = null; 987 int methodParameters = 0; 988 int anns = 0; 989 int ianns = 0; 990 int tanns = 0; 991 int itanns = 0; 992 int dann = 0; 993 int mpanns = 0; 994 int impanns = 0; 995 int firstAttribute = u; 996 Attribute attributes = null; 997 998 for (int i = readUnsignedShort(u); i > 0; --i) { 999 String attrName = readUTF8(u + 2, c); 1000 // tests are sorted in decreasing frequency order 1001 // (based on frequencies observed on typical classes) 1002 if ("Code".equals(attrName)) { 1003 if ((context.flags & SKIP_CODE) == 0) { 1004 code = u + 8; 1005 } 1006 } else if ("Exceptions".equals(attrName)) { 1007 exceptions = new String[readUnsignedShort(u + 8)]; 1008 exception = u + 10; 1009 for (int j = 0; j < exceptions.length; ++j) { 1010 exceptions[j] = readClass(exception, c); 1011 exception += 2; 1012 } 1013 } else if ("Signature".equals(attrName)) { 1014 signature = readUTF8(u + 8, c); 1015 } else if ("Deprecated".equals(attrName)) { 1016 context.access |= Opcodes.ACC_DEPRECATED; 1017 } else if ("RuntimeVisibleAnnotations".equals(attrName)) { 1018 anns = u + 8; 1019 } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) { 1020 tanns = u + 8; 1021 } else if ("AnnotationDefault".equals(attrName)) { 1022 dann = u + 8; 1023 } else if ("Synthetic".equals(attrName)) { 1024 context.access |= Opcodes.ACC_SYNTHETIC 1025 | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE; 1026 } else if ("RuntimeInvisibleAnnotations".equals(attrName)) { 1027 ianns = u + 8; 1028 } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) { 1029 itanns = u + 8; 1030 } else if ("RuntimeVisibleParameterAnnotations".equals(attrName)) { 1031 mpanns = u + 8; 1032 } else if ("RuntimeInvisibleParameterAnnotations".equals(attrName)) { 1033 impanns = u + 8; 1034 } else if ("MethodParameters".equals(attrName)) { 1035 methodParameters = u + 8; 1036 } else { 1037 Attribute attr = readAttribute(context.attrs, attrName, u + 8, 1038 readInt(u + 4), c, -1, null); 1039 if (attr != null) { 1040 attr.next = attributes; 1041 attributes = attr; 1042 } 1043 } 1044 u += 6 + readInt(u + 4); 1045 } 1046 u += 2; 1047 1048 // visits the method declaration 1049 MethodVisitor mv = classVisitor.visitMethod(context.access, 1050 context.name, context.desc, signature, exceptions); 1051 if (mv == null) { 1052 return u; 1053 } 1054 1055 /* 1056 * if the returned MethodVisitor is in fact a MethodWriter, it means 1057 * there is no method adapter between the reader and the writer. If, in 1058 * addition, the writer's constant pool was copied from this reader 1059 * (mw.cw.cr == this), and the signature and exceptions of the method 1060 * have not been changed, then it is possible to skip all visit events 1061 * and just copy the original code of the method to the writer (the 1062 * access, name and descriptor can have been changed, this is not 1063 * important since they are not copied as is from the reader). 1064 */ 1065 if (mv instanceof MethodWriter) { 1066 MethodWriter mw = (MethodWriter) mv; 1067 if (mw.cw.cr == this && signature == mw.signature) { 1068 boolean sameExceptions = false; 1069 if (exceptions == null) { 1070 sameExceptions = mw.exceptionCount == 0; 1071 } else if (exceptions.length == mw.exceptionCount) { 1072 sameExceptions = true; 1073 for (int j = exceptions.length - 1; j >= 0; --j) { 1074 exception -= 2; 1075 if (mw.exceptions[j] != readUnsignedShort(exception)) { 1076 sameExceptions = false; 1077 break; 1078 } 1079 } 1080 } 1081 if (sameExceptions) { 1082 /* 1083 * we do not copy directly the code into MethodWriter to 1084 * save a byte array copy operation. The real copy will be 1085 * done in ClassWriter.toByteArray(). 1086 */ 1087 mw.classReaderOffset = firstAttribute; 1088 mw.classReaderLength = u - firstAttribute; 1089 return u; 1090 } 1091 } 1092 } 1093 1094 // visit the method parameters 1095 if (methodParameters != 0) { 1096 for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) { 1097 mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2)); 1098 } 1099 } 1100 1101 // visits the method annotations 1102 if (dann != 0) { 1103 AnnotationVisitor dv = mv.visitAnnotationDefault(); 1104 readAnnotationValue(dann, c, null, dv); 1105 if (dv != null) { 1106 dv.visitEnd(); 1107 } 1108 } 1109 if (anns != 0) { 1110 for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) { 1111 v = readAnnotationValues(v + 2, c, true, 1112 mv.visitAnnotation(readUTF8(v, c), true)); 1113 } 1114 } 1115 if (ianns != 0) { 1116 for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) { 1117 v = readAnnotationValues(v + 2, c, true, 1118 mv.visitAnnotation(readUTF8(v, c), false)); 1119 } 1120 } 1121 if (tanns != 0) { 1122 for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) { 1123 v = readAnnotationTarget(context, v); 1124 v = readAnnotationValues(v + 2, c, true, 1125 mv.visitTypeAnnotation(context.typeRef, 1126 context.typePath, readUTF8(v, c), true)); 1127 } 1128 } 1129 if (itanns != 0) { 1130 for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) { 1131 v = readAnnotationTarget(context, v); 1132 v = readAnnotationValues(v + 2, c, true, 1133 mv.visitTypeAnnotation(context.typeRef, 1134 context.typePath, readUTF8(v, c), false)); 1135 } 1136 } 1137 if (mpanns != 0) { 1138 readParameterAnnotations(mv, context, mpanns, true); 1139 } 1140 if (impanns != 0) { 1141 readParameterAnnotations(mv, context, impanns, false); 1142 } 1143 1144 // visits the method attributes 1145 while (attributes != null) { 1146 Attribute attr = attributes.next; 1147 attributes.next = null; 1148 mv.visitAttribute(attributes); 1149 attributes = attr; 1150 } 1151 1152 // visits the method code 1153 if (code != 0) { 1154 mv.visitCode(); 1155 readCode(mv, context, code); 1156 } 1157 1158 // visits the end of the method 1159 mv.visitEnd(); 1160 1161 return u; 1162 } 1163 1164 /** 1165 * Reads the bytecode of a method and makes the given visitor visit it. 1166 * 1167 * @param mv 1168 * the visitor that must visit the method's code. 1169 * @param context 1170 * information about the class being parsed. 1171 * @param u 1172 * the start offset of the code attribute in the class file. 1173 */ 1174 private void readCode(final MethodVisitor mv, final Context context, int u) { 1175 // reads the header 1176 byte[] b = this.b; 1177 char[] c = context.buffer; 1178 int maxStack = readUnsignedShort(u); 1179 int maxLocals = readUnsignedShort(u + 2); 1180 int codeLength = readInt(u + 4); 1181 u += 8; 1182 1183 // reads the bytecode to find the labels 1184 int codeStart = u; 1185 int codeEnd = u + codeLength; 1186 Label[] labels = context.labels = new Label[codeLength + 2]; 1187 createLabel(codeLength + 1, labels); 1188 while (u < codeEnd) { 1189 int offset = u - codeStart; 1190 int opcode = b[u] & 0xFF; 1191 switch (ClassWriter.TYPE[opcode]) { 1192 case ClassWriter.NOARG_INSN: 1193 case ClassWriter.IMPLVAR_INSN: 1194 u += 1; 1195 break; 1196 case ClassWriter.LABEL_INSN: 1197 createLabel(offset + readShort(u + 1), labels); 1198 u += 3; 1199 break; 1200 case ClassWriter.ASM_LABEL_INSN: 1201 createLabel(offset + readUnsignedShort(u + 1), labels); 1202 u += 3; 1203 break; 1204 case ClassWriter.LABELW_INSN: 1205 case ClassWriter.ASM_LABELW_INSN: 1206 createLabel(offset + readInt(u + 1), labels); 1207 u += 5; 1208 break; 1209 case ClassWriter.WIDE_INSN: 1210 opcode = b[u + 1] & 0xFF; 1211 if (opcode == Opcodes.IINC) { 1212 u += 6; 1213 } else { 1214 u += 4; 1215 } 1216 break; 1217 case ClassWriter.TABL_INSN: 1218 // skips 0 to 3 padding bytes 1219 u = u + 4 - (offset & 3); 1220 // reads instruction 1221 createLabel(offset + readInt(u), labels); 1222 for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) { 1223 createLabel(offset + readInt(u + 12), labels); 1224 u += 4; 1225 } 1226 u += 12; 1227 break; 1228 case ClassWriter.LOOK_INSN: 1229 // skips 0 to 3 padding bytes 1230 u = u + 4 - (offset & 3); 1231 // reads instruction 1232 createLabel(offset + readInt(u), labels); 1233 for (int i = readInt(u + 4); i > 0; --i) { 1234 createLabel(offset + readInt(u + 12), labels); 1235 u += 8; 1236 } 1237 u += 8; 1238 break; 1239 case ClassWriter.VAR_INSN: 1240 case ClassWriter.SBYTE_INSN: 1241 case ClassWriter.LDC_INSN: 1242 u += 2; 1243 break; 1244 case ClassWriter.SHORT_INSN: 1245 case ClassWriter.LDCW_INSN: 1246 case ClassWriter.FIELDORMETH_INSN: 1247 case ClassWriter.TYPE_INSN: 1248 case ClassWriter.IINC_INSN: 1249 u += 3; 1250 break; 1251 case ClassWriter.ITFMETH_INSN: 1252 case ClassWriter.INDYMETH_INSN: 1253 u += 5; 1254 break; 1255 // case MANA_INSN: 1256 default: 1257 u += 4; 1258 break; 1259 } 1260 } 1261 1262 // reads the try catch entries to find the labels, and also visits them 1263 for (int i = readUnsignedShort(u); i > 0; --i) { 1264 Label start = createLabel(readUnsignedShort(u + 2), labels); 1265 Label end = createLabel(readUnsignedShort(u + 4), labels); 1266 Label handler = createLabel(readUnsignedShort(u + 6), labels); 1267 String type = readUTF8(items[readUnsignedShort(u + 8)], c); 1268 mv.visitTryCatchBlock(start, end, handler, type); 1269 u += 8; 1270 } 1271 u += 2; 1272 1273 // reads the code attributes 1274 int[] tanns = null; // start index of each visible type annotation 1275 int[] itanns = null; // start index of each invisible type annotation 1276 int tann = 0; // current index in tanns array 1277 int itann = 0; // current index in itanns array 1278 int ntoff = -1; // next visible type annotation code offset 1279 int nitoff = -1; // next invisible type annotation code offset 1280 int varTable = 0; 1281 int varTypeTable = 0; 1282 boolean zip = true; 1283 boolean unzip = (context.flags & EXPAND_FRAMES) != 0; 1284 int stackMap = 0; 1285 int stackMapSize = 0; 1286 int frameCount = 0; 1287 Context frame = null; 1288 Attribute attributes = null; 1289 1290 for (int i = readUnsignedShort(u); i > 0; --i) { 1291 String attrName = readUTF8(u + 2, c); 1292 if ("LocalVariableTable".equals(attrName)) { 1293 if ((context.flags & SKIP_DEBUG) == 0) { 1294 varTable = u + 8; 1295 for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { 1296 int label = readUnsignedShort(v + 10); 1297 createDebugLabel(label, labels); 1298 label += readUnsignedShort(v + 12); 1299 createDebugLabel(label, labels); 1300 v += 10; 1301 } 1302 } 1303 } else if ("LocalVariableTypeTable".equals(attrName)) { 1304 varTypeTable = u + 8; 1305 } else if ("LineNumberTable".equals(attrName)) { 1306 if ((context.flags & SKIP_DEBUG) == 0) { 1307 for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) { 1308 int label = readUnsignedShort(v + 10); 1309 createDebugLabel(label, labels); 1310 Label l = labels[label]; 1311 while (l.line > 0) { 1312 if (l.next == null) { 1313 l.next = new Label(); 1314 } 1315 l = l.next; 1316 } 1317 l.line = readUnsignedShort(v + 12); 1318 v += 4; 1319 } 1320 } 1321 } else if ("RuntimeVisibleTypeAnnotations".equals(attrName)) { 1322 tanns = readTypeAnnotations(mv, context, u + 8, true); 1323 ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1 1324 : readUnsignedShort(tanns[0] + 1); 1325 } else if ("RuntimeInvisibleTypeAnnotations".equals(attrName)) { 1326 itanns = readTypeAnnotations(mv, context, u + 8, false); 1327 nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1 1328 : readUnsignedShort(itanns[0] + 1); 1329 } else if ("StackMapTable".equals(attrName)) { 1330 if ((context.flags & SKIP_FRAMES) == 0) { 1331 stackMap = u + 10; 1332 stackMapSize = readInt(u + 4); 1333 frameCount = readUnsignedShort(u + 8); 1334 } 1335 /* 1336 * here we do not extract the labels corresponding to the 1337 * attribute content. This would require a full parsing of the 1338 * attribute, which would need to be repeated in the second 1339 * phase (see below). Instead the content of the attribute is 1340 * read one frame at a time (i.e. after a frame has been 1341 * visited, the next frame is read), and the labels it contains 1342 * are also extracted one frame at a time. Thanks to the 1343 * ordering of frames, having only a "one frame lookahead" is 1344 * not a problem, i.e. it is not possible to see an offset 1345 * smaller than the offset of the current insn and for which no 1346 * Label exist. 1347 */ 1348 /* 1349 * This is not true for UNINITIALIZED type offsets. We solve 1350 * this by parsing the stack map table without a full decoding 1351 * (see below). 1352 */ 1353 } else if ("StackMap".equals(attrName)) { 1354 if ((context.flags & SKIP_FRAMES) == 0) { 1355 zip = false; 1356 stackMap = u + 10; 1357 stackMapSize = readInt(u + 4); 1358 frameCount = readUnsignedShort(u + 8); 1359 } 1360 /* 1361 * IMPORTANT! here we assume that the frames are ordered, as in 1362 * the StackMapTable attribute, although this is not guaranteed 1363 * by the attribute format. 1364 */ 1365 } else { 1366 for (int j = 0; j < context.attrs.length; ++j) { 1367 if (context.attrs[j].type.equals(attrName)) { 1368 Attribute attr = context.attrs[j].read(this, u + 8, 1369 readInt(u + 4), c, codeStart - 8, labels); 1370 if (attr != null) { 1371 attr.next = attributes; 1372 attributes = attr; 1373 } 1374 } 1375 } 1376 } 1377 u += 6 + readInt(u + 4); 1378 } 1379 u += 2; 1380 1381 // generates the first (implicit) stack map frame 1382 if (stackMap != 0) { 1383 /* 1384 * for the first explicit frame the offset is not offset_delta + 1 1385 * but only offset_delta; setting the implicit frame offset to -1 1386 * allow the use of the "offset_delta + 1" rule in all cases 1387 */ 1388 frame = context; 1389 frame.offset = -1; 1390 frame.mode = 0; 1391 frame.localCount = 0; 1392 frame.localDiff = 0; 1393 frame.stackCount = 0; 1394 frame.local = new Object[maxLocals]; 1395 frame.stack = new Object[maxStack]; 1396 if (unzip) { 1397 getImplicitFrame(context); 1398 } 1399 /* 1400 * Finds labels for UNINITIALIZED frame types. Instead of decoding 1401 * each element of the stack map table, we look for 3 consecutive 1402 * bytes that "look like" an UNINITIALIZED type (tag 8, offset 1403 * within code bounds, NEW instruction at this offset). We may find 1404 * false positives (i.e. not real UNINITIALIZED types), but this 1405 * should be rare, and the only consequence will be the creation of 1406 * an unneeded label. This is better than creating a label for each 1407 * NEW instruction, and faster than fully decoding the whole stack 1408 * map table. 1409 */ 1410 for (int i = stackMap; i < stackMap + stackMapSize - 2; ++i) { 1411 if (b[i] == 8) { // UNINITIALIZED FRAME TYPE 1412 int v = readUnsignedShort(i + 1); 1413 if (v >= 0 && v < codeLength) { 1414 if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) { 1415 createLabel(v, labels); 1416 } 1417 } 1418 } 1419 } 1420 } 1421 if ((context.flags & EXPAND_ASM_INSNS) != 0 1422 && (context.flags & EXPAND_FRAMES) != 0) { 1423 // Expanding the ASM pseudo instructions can introduce F_INSERT 1424 // frames, even if the method does not currently have any frame. 1425 // Also these inserted frames must be computed by simulating the 1426 // effect of the bytecode instructions one by one, starting from the 1427 // first one and the last existing frame (or the implicit first 1428 // one). Finally, due to the way MethodWriter computes this (with 1429 // the compute = INSERTED_FRAMES option), MethodWriter needs to know 1430 // maxLocals before the first instruction is visited. For all these 1431 // reasons we always visit the implicit first frame in this case 1432 // (passing only maxLocals - the rest can be and is computed in 1433 // MethodWriter). 1434 mv.visitFrame(Opcodes.F_NEW, maxLocals, null, 0, null); 1435 } 1436 1437 // visits the instructions 1438 int opcodeDelta = (context.flags & EXPAND_ASM_INSNS) == 0 ? -33 : 0; 1439 boolean insertFrame = false; 1440 u = codeStart; 1441 while (u < codeEnd) { 1442 int offset = u - codeStart; 1443 1444 // visits the label and line number for this offset, if any 1445 Label l = labels[offset]; 1446 if (l != null) { 1447 Label next = l.next; 1448 l.next = null; 1449 mv.visitLabel(l); 1450 if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) { 1451 mv.visitLineNumber(l.line, l); 1452 while (next != null) { 1453 mv.visitLineNumber(next.line, l); 1454 next = next.next; 1455 } 1456 } 1457 } 1458 1459 // visits the frame for this offset, if any 1460 while (frame != null 1461 && (frame.offset == offset || frame.offset == -1)) { 1462 // if there is a frame for this offset, makes the visitor visit 1463 // it, and reads the next frame if there is one. 1464 if (frame.offset != -1) { 1465 if (!zip || unzip) { 1466 mv.visitFrame(Opcodes.F_NEW, frame.localCount, 1467 frame.local, frame.stackCount, frame.stack); 1468 } else { 1469 mv.visitFrame(frame.mode, frame.localDiff, frame.local, 1470 frame.stackCount, frame.stack); 1471 } 1472 // if there is already a frame for this offset, there is no 1473 // need to insert a new one. 1474 insertFrame = false; 1475 } 1476 if (frameCount > 0) { 1477 stackMap = readFrame(stackMap, zip, unzip, frame); 1478 --frameCount; 1479 } else { 1480 frame = null; 1481 } 1482 } 1483 // inserts a frame for this offset, if requested by setting 1484 // insertFrame to true during the previous iteration. The actual 1485 // frame content will be computed in MethodWriter. 1486 if (insertFrame) { 1487 mv.visitFrame(ClassWriter.F_INSERT, 0, null, 0, null); 1488 insertFrame = false; 1489 } 1490 1491 // visits the instruction at this offset 1492 int opcode = b[u] & 0xFF; 1493 switch (ClassWriter.TYPE[opcode]) { 1494 case ClassWriter.NOARG_INSN: 1495 mv.visitInsn(opcode); 1496 u += 1; 1497 break; 1498 case ClassWriter.IMPLVAR_INSN: 1499 if (opcode > Opcodes.ISTORE) { 1500 opcode -= 59; // ISTORE_0 1501 mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2), 1502 opcode & 0x3); 1503 } else { 1504 opcode -= 26; // ILOAD_0 1505 mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), opcode & 0x3); 1506 } 1507 u += 1; 1508 break; 1509 case ClassWriter.LABEL_INSN: 1510 mv.visitJumpInsn(opcode, labels[offset + readShort(u + 1)]); 1511 u += 3; 1512 break; 1513 case ClassWriter.LABELW_INSN: 1514 mv.visitJumpInsn(opcode + opcodeDelta, labels[offset 1515 + readInt(u + 1)]); 1516 u += 5; 1517 break; 1518 case ClassWriter.ASM_LABEL_INSN: { 1519 // changes temporary opcodes 202 to 217 (inclusive), 218 1520 // and 219 to IFEQ ... JSR (inclusive), IFNULL and 1521 // IFNONNULL 1522 opcode = opcode < 218 ? opcode - 49 : opcode - 20; 1523 Label target = labels[offset + readUnsignedShort(u + 1)]; 1524 // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx 1525 // <l> with IFNOTxxx <L> GOTO_W <l> L:..., where IFNOTxxx is 1526 // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) 1527 // and where <L> designates the instruction just after 1528 // the GOTO_W. 1529 if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) { 1530 mv.visitJumpInsn(opcode + 33, target); 1531 } else { 1532 opcode = opcode <= 166 ? ((opcode + 1) ^ 1) - 1 1533 : opcode ^ 1; 1534 Label endif = createLabel(offset + 3, labels); 1535 mv.visitJumpInsn(opcode, endif); 1536 mv.visitJumpInsn(200, target); // GOTO_W 1537 // endif designates the instruction just after GOTO_W, 1538 // and is visited as part of the next instruction. Since 1539 // it is a jump target, we need to insert a frame here. 1540 insertFrame = true; 1541 } 1542 u += 3; 1543 break; 1544 } 1545 case ClassWriter.ASM_LABELW_INSN: { 1546 // replaces the pseudo GOTO_W instruction with a real one. 1547 mv.visitJumpInsn(200, labels[offset + readInt(u + 1)]); 1548 // The instruction just after is a jump target (because pseudo 1549 // GOTO_W are used in patterns IFNOTxxx <L> GOTO_W <l> L:..., 1550 // see MethodWriter), so we need to insert a frame here. 1551 insertFrame = true; 1552 u += 5; 1553 break; 1554 } 1555 case ClassWriter.WIDE_INSN: 1556 opcode = b[u + 1] & 0xFF; 1557 if (opcode == Opcodes.IINC) { 1558 mv.visitIincInsn(readUnsignedShort(u + 2), readShort(u + 4)); 1559 u += 6; 1560 } else { 1561 mv.visitVarInsn(opcode, readUnsignedShort(u + 2)); 1562 u += 4; 1563 } 1564 break; 1565 case ClassWriter.TABL_INSN: { 1566 // skips 0 to 3 padding bytes 1567 u = u + 4 - (offset & 3); 1568 // reads instruction 1569 int label = offset + readInt(u); 1570 int min = readInt(u + 4); 1571 int max = readInt(u + 8); 1572 Label[] table = new Label[max - min + 1]; 1573 u += 12; 1574 for (int i = 0; i < table.length; ++i) { 1575 table[i] = labels[offset + readInt(u)]; 1576 u += 4; 1577 } 1578 mv.visitTableSwitchInsn(min, max, labels[label], table); 1579 break; 1580 } 1581 case ClassWriter.LOOK_INSN: { 1582 // skips 0 to 3 padding bytes 1583 u = u + 4 - (offset & 3); 1584 // reads instruction 1585 int label = offset + readInt(u); 1586 int len = readInt(u + 4); 1587 int[] keys = new int[len]; 1588 Label[] values = new Label[len]; 1589 u += 8; 1590 for (int i = 0; i < len; ++i) { 1591 keys[i] = readInt(u); 1592 values[i] = labels[offset + readInt(u + 4)]; 1593 u += 8; 1594 } 1595 mv.visitLookupSwitchInsn(labels[label], keys, values); 1596 break; 1597 } 1598 case ClassWriter.VAR_INSN: 1599 mv.visitVarInsn(opcode, b[u + 1] & 0xFF); 1600 u += 2; 1601 break; 1602 case ClassWriter.SBYTE_INSN: 1603 mv.visitIntInsn(opcode, b[u + 1]); 1604 u += 2; 1605 break; 1606 case ClassWriter.SHORT_INSN: 1607 mv.visitIntInsn(opcode, readShort(u + 1)); 1608 u += 3; 1609 break; 1610 case ClassWriter.LDC_INSN: 1611 mv.visitLdcInsn(readConst(b[u + 1] & 0xFF, c)); 1612 u += 2; 1613 break; 1614 case ClassWriter.LDCW_INSN: 1615 mv.visitLdcInsn(readConst(readUnsignedShort(u + 1), c)); 1616 u += 3; 1617 break; 1618 case ClassWriter.FIELDORMETH_INSN: 1619 case ClassWriter.ITFMETH_INSN: { 1620 int cpIndex = items[readUnsignedShort(u + 1)]; 1621 boolean itf = b[cpIndex - 1] == ClassWriter.IMETH; 1622 String iowner = readClass(cpIndex, c); 1623 cpIndex = items[readUnsignedShort(cpIndex + 2)]; 1624 String iname = readUTF8(cpIndex, c); 1625 String idesc = readUTF8(cpIndex + 2, c); 1626 if (opcode < Opcodes.INVOKEVIRTUAL) { 1627 mv.visitFieldInsn(opcode, iowner, iname, idesc); 1628 } else { 1629 mv.visitMethodInsn(opcode, iowner, iname, idesc, itf); 1630 } 1631 if (opcode == Opcodes.INVOKEINTERFACE) { 1632 u += 5; 1633 } else { 1634 u += 3; 1635 } 1636 break; 1637 } 1638 case ClassWriter.INDYMETH_INSN: { 1639 int cpIndex = items[readUnsignedShort(u + 1)]; 1640 int bsmIndex = context.bootstrapMethods[readUnsignedShort(cpIndex)]; 1641 Handle bsm = (Handle) readConst(readUnsignedShort(bsmIndex), c); 1642 int bsmArgCount = readUnsignedShort(bsmIndex + 2); 1643 Object[] bsmArgs = new Object[bsmArgCount]; 1644 bsmIndex += 4; 1645 for (int i = 0; i < bsmArgCount; i++) { 1646 bsmArgs[i] = readConst(readUnsignedShort(bsmIndex), c); 1647 bsmIndex += 2; 1648 } 1649 cpIndex = items[readUnsignedShort(cpIndex + 2)]; 1650 String iname = readUTF8(cpIndex, c); 1651 String idesc = readUTF8(cpIndex + 2, c); 1652 mv.visitInvokeDynamicInsn(iname, idesc, bsm, bsmArgs); 1653 u += 5; 1654 break; 1655 } 1656 case ClassWriter.TYPE_INSN: 1657 mv.visitTypeInsn(opcode, readClass(u + 1, c)); 1658 u += 3; 1659 break; 1660 case ClassWriter.IINC_INSN: 1661 mv.visitIincInsn(b[u + 1] & 0xFF, b[u + 2]); 1662 u += 3; 1663 break; 1664 // case MANA_INSN: 1665 default: 1666 mv.visitMultiANewArrayInsn(readClass(u + 1, c), b[u + 3] & 0xFF); 1667 u += 4; 1668 break; 1669 } 1670 1671 // visit the instruction annotations, if any 1672 while (tanns != null && tann < tanns.length && ntoff <= offset) { 1673 if (ntoff == offset) { 1674 int v = readAnnotationTarget(context, tanns[tann]); 1675 readAnnotationValues(v + 2, c, true, 1676 mv.visitInsnAnnotation(context.typeRef, 1677 context.typePath, readUTF8(v, c), true)); 1678 } 1679 ntoff = ++tann >= tanns.length || readByte(tanns[tann]) < 0x43 ? -1 1680 : readUnsignedShort(tanns[tann] + 1); 1681 } 1682 while (itanns != null && itann < itanns.length && nitoff <= offset) { 1683 if (nitoff == offset) { 1684 int v = readAnnotationTarget(context, itanns[itann]); 1685 readAnnotationValues(v + 2, c, true, 1686 mv.visitInsnAnnotation(context.typeRef, 1687 context.typePath, readUTF8(v, c), false)); 1688 } 1689 nitoff = ++itann >= itanns.length 1690 || readByte(itanns[itann]) < 0x43 ? -1 1691 : readUnsignedShort(itanns[itann] + 1); 1692 } 1693 } 1694 if (labels[codeLength] != null) { 1695 mv.visitLabel(labels[codeLength]); 1696 } 1697 1698 // visits the local variable tables 1699 if ((context.flags & SKIP_DEBUG) == 0 && varTable != 0) { 1700 int[] typeTable = null; 1701 if (varTypeTable != 0) { 1702 u = varTypeTable + 2; 1703 typeTable = new int[readUnsignedShort(varTypeTable) * 3]; 1704 for (int i = typeTable.length; i > 0;) { 1705 typeTable[--i] = u + 6; // signature 1706 typeTable[--i] = readUnsignedShort(u + 8); // index 1707 typeTable[--i] = readUnsignedShort(u); // start 1708 u += 10; 1709 } 1710 } 1711 u = varTable + 2; 1712 for (int i = readUnsignedShort(varTable); i > 0; --i) { 1713 int start = readUnsignedShort(u); 1714 int length = readUnsignedShort(u + 2); 1715 int index = readUnsignedShort(u + 8); 1716 String vsignature = null; 1717 if (typeTable != null) { 1718 for (int j = 0; j < typeTable.length; j += 3) { 1719 if (typeTable[j] == start && typeTable[j + 1] == index) { 1720 vsignature = readUTF8(typeTable[j + 2], c); 1721 break; 1722 } 1723 } 1724 } 1725 mv.visitLocalVariable(readUTF8(u + 4, c), readUTF8(u + 6, c), 1726 vsignature, labels[start], labels[start + length], 1727 index); 1728 u += 10; 1729 } 1730 } 1731 1732 // visits the local variables type annotations 1733 if (tanns != null) { 1734 for (int i = 0; i < tanns.length; ++i) { 1735 if ((readByte(tanns[i]) >> 1) == (0x40 >> 1)) { 1736 int v = readAnnotationTarget(context, tanns[i]); 1737 v = readAnnotationValues(v + 2, c, true, 1738 mv.visitLocalVariableAnnotation(context.typeRef, 1739 context.typePath, context.start, 1740 context.end, context.index, readUTF8(v, c), 1741 true)); 1742 } 1743 } 1744 } 1745 if (itanns != null) { 1746 for (int i = 0; i < itanns.length; ++i) { 1747 if ((readByte(itanns[i]) >> 1) == (0x40 >> 1)) { 1748 int v = readAnnotationTarget(context, itanns[i]); 1749 v = readAnnotationValues(v + 2, c, true, 1750 mv.visitLocalVariableAnnotation(context.typeRef, 1751 context.typePath, context.start, 1752 context.end, context.index, readUTF8(v, c), 1753 false)); 1754 } 1755 } 1756 } 1757 1758 // visits the code attributes 1759 while (attributes != null) { 1760 Attribute attr = attributes.next; 1761 attributes.next = null; 1762 mv.visitAttribute(attributes); 1763 attributes = attr; 1764 } 1765 1766 // visits the max stack and max locals values 1767 mv.visitMaxs(maxStack, maxLocals); 1768 } 1769 1770 /** 1771 * Parses a type annotation table to find the labels, and to visit the try 1772 * catch block annotations. 1773 * 1774 * @param u 1775 * the start offset of a type annotation table. 1776 * @param mv 1777 * the method visitor to be used to visit the try catch block 1778 * annotations. 1779 * @param context 1780 * information about the class being parsed. 1781 * @param visible 1782 * if the type annotation table to parse contains runtime visible 1783 * annotations. 1784 * @return the start offset of each type annotation in the parsed table. 1785 */ 1786 private int[] readTypeAnnotations(final MethodVisitor mv, 1787 final Context context, int u, boolean visible) { 1788 char[] c = context.buffer; 1789 int[] offsets = new int[readUnsignedShort(u)]; 1790 u += 2; 1791 for (int i = 0; i < offsets.length; ++i) { 1792 offsets[i] = u; 1793 int target = readInt(u); 1794 switch (target >>> 24) { 1795 case 0x00: // CLASS_TYPE_PARAMETER 1796 case 0x01: // METHOD_TYPE_PARAMETER 1797 case 0x16: // METHOD_FORMAL_PARAMETER 1798 u += 2; 1799 break; 1800 case 0x13: // FIELD 1801 case 0x14: // METHOD_RETURN 1802 case 0x15: // METHOD_RECEIVER 1803 u += 1; 1804 break; 1805 case 0x40: // LOCAL_VARIABLE 1806 case 0x41: // RESOURCE_VARIABLE 1807 for (int j = readUnsignedShort(u + 1); j > 0; --j) { 1808 int start = readUnsignedShort(u + 3); 1809 int length = readUnsignedShort(u + 5); 1810 createLabel(start, context.labels); 1811 createLabel(start + length, context.labels); 1812 u += 6; 1813 } 1814 u += 3; 1815 break; 1816 case 0x47: // CAST 1817 case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT 1818 case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT 1819 case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT 1820 case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT 1821 u += 4; 1822 break; 1823 // case 0x10: // CLASS_EXTENDS 1824 // case 0x11: // CLASS_TYPE_PARAMETER_BOUND 1825 // case 0x12: // METHOD_TYPE_PARAMETER_BOUND 1826 // case 0x17: // THROWS 1827 // case 0x42: // EXCEPTION_PARAMETER 1828 // case 0x43: // INSTANCEOF 1829 // case 0x44: // NEW 1830 // case 0x45: // CONSTRUCTOR_REFERENCE 1831 // case 0x46: // METHOD_REFERENCE 1832 default: 1833 u += 3; 1834 break; 1835 } 1836 int pathLength = readByte(u); 1837 if ((target >>> 24) == 0x42) { 1838 TypePath path = pathLength == 0 ? null : new TypePath(b, u); 1839 u += 1 + 2 * pathLength; 1840 u = readAnnotationValues(u + 2, c, true, 1841 mv.visitTryCatchAnnotation(target, path, 1842 readUTF8(u, c), visible)); 1843 } else { 1844 u = readAnnotationValues(u + 3 + 2 * pathLength, c, true, null); 1845 } 1846 } 1847 return offsets; 1848 } 1849 1850 /** 1851 * Parses the header of a type annotation to extract its target_type and 1852 * target_path (the result is stored in the given context), and returns the 1853 * start offset of the rest of the type_annotation structure (i.e. the 1854 * offset to the type_index field, which is followed by 1855 * num_element_value_pairs and then the name,value pairs). 1856 * 1857 * @param context 1858 * information about the class being parsed. This is where the 1859 * extracted target_type and target_path must be stored. 1860 * @param u 1861 * the start offset of a type_annotation structure. 1862 * @return the start offset of the rest of the type_annotation structure. 1863 */ 1864 private int readAnnotationTarget(final Context context, int u) { 1865 int target = readInt(u); 1866 switch (target >>> 24) { 1867 case 0x00: // CLASS_TYPE_PARAMETER 1868 case 0x01: // METHOD_TYPE_PARAMETER 1869 case 0x16: // METHOD_FORMAL_PARAMETER 1870 target &= 0xFFFF0000; 1871 u += 2; 1872 break; 1873 case 0x13: // FIELD 1874 case 0x14: // METHOD_RETURN 1875 case 0x15: // METHOD_RECEIVER 1876 target &= 0xFF000000; 1877 u += 1; 1878 break; 1879 case 0x40: // LOCAL_VARIABLE 1880 case 0x41: { // RESOURCE_VARIABLE 1881 target &= 0xFF000000; 1882 int n = readUnsignedShort(u + 1); 1883 context.start = new Label[n]; 1884 context.end = new Label[n]; 1885 context.index = new int[n]; 1886 u += 3; 1887 for (int i = 0; i < n; ++i) { 1888 int start = readUnsignedShort(u); 1889 int length = readUnsignedShort(u + 2); 1890 context.start[i] = createLabel(start, context.labels); 1891 context.end[i] = createLabel(start + length, context.labels); 1892 context.index[i] = readUnsignedShort(u + 4); 1893 u += 6; 1894 } 1895 break; 1896 } 1897 case 0x47: // CAST 1898 case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT 1899 case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT 1900 case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT 1901 case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT 1902 target &= 0xFF0000FF; 1903 u += 4; 1904 break; 1905 // case 0x10: // CLASS_EXTENDS 1906 // case 0x11: // CLASS_TYPE_PARAMETER_BOUND 1907 // case 0x12: // METHOD_TYPE_PARAMETER_BOUND 1908 // case 0x17: // THROWS 1909 // case 0x42: // EXCEPTION_PARAMETER 1910 // case 0x43: // INSTANCEOF 1911 // case 0x44: // NEW 1912 // case 0x45: // CONSTRUCTOR_REFERENCE 1913 // case 0x46: // METHOD_REFERENCE 1914 default: 1915 target &= (target >>> 24) < 0x43 ? 0xFFFFFF00 : 0xFF000000; 1916 u += 3; 1917 break; 1918 } 1919 int pathLength = readByte(u); 1920 context.typeRef = target; 1921 context.typePath = pathLength == 0 ? null : new TypePath(b, u); 1922 return u + 1 + 2 * pathLength; 1923 } 1924 1925 /** 1926 * Reads parameter annotations and makes the given visitor visit them. 1927 * 1928 * @param mv 1929 * the visitor that must visit the annotations. 1930 * @param context 1931 * information about the class being parsed. 1932 * @param v 1933 * start offset in {@link #b b} of the annotations to be read. 1934 * @param visible 1935 * <tt>true</tt> if the annotations to be read are visible at 1936 * runtime. 1937 */ 1938 private void readParameterAnnotations(final MethodVisitor mv, 1939 final Context context, int v, final boolean visible) { 1940 int i; 1941 int n = b[v++] & 0xFF; 1942 // workaround for a bug in javac (javac compiler generates a parameter 1943 // annotation array whose size is equal to the number of parameters in 1944 // the Java source file, while it should generate an array whose size is 1945 // equal to the number of parameters in the method descriptor - which 1946 // includes the synthetic parameters added by the compiler). This work- 1947 // around supposes that the synthetic parameters are the first ones. 1948 int synthetics = Type.getArgumentTypes(context.desc).length - n; 1949 AnnotationVisitor av; 1950 for (i = 0; i < synthetics; ++i) { 1951 // virtual annotation to detect synthetic parameters in MethodWriter 1952 av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false); 1953 if (av != null) { 1954 av.visitEnd(); 1955 } 1956 } 1957 char[] c = context.buffer; 1958 for (; i < n + synthetics; ++i) { 1959 int j = readUnsignedShort(v); 1960 v += 2; 1961 for (; j > 0; --j) { 1962 av = mv.visitParameterAnnotation(i, readUTF8(v, c), visible); 1963 v = readAnnotationValues(v + 2, c, true, av); 1964 } 1965 } 1966 } 1967 1968 /** 1969 * Reads the values of an annotation and makes the given visitor visit them. 1970 * 1971 * @param v 1972 * the start offset in {@link #b b} of the values to be read 1973 * (including the unsigned short that gives the number of 1974 * values). 1975 * @param buf 1976 * buffer to be used to call {@link #readUTF8 readUTF8}, 1977 * {@link #readClass(int,char[]) readClass} or {@link #readConst 1978 * readConst}. 1979 * @param named 1980 * if the annotation values are named or not. 1981 * @param av 1982 * the visitor that must visit the values. 1983 * @return the end offset of the annotation values. 1984 */ 1985 private int readAnnotationValues(int v, final char[] buf, 1986 final boolean named, final AnnotationVisitor av) { 1987 int i = readUnsignedShort(v); 1988 v += 2; 1989 if (named) { 1990 for (; i > 0; --i) { 1991 v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av); 1992 } 1993 } else { 1994 for (; i > 0; --i) { 1995 v = readAnnotationValue(v, buf, null, av); 1996 } 1997 } 1998 if (av != null) { 1999 av.visitEnd(); 2000 } 2001 return v; 2002 } 2003 2004 /** 2005 * Reads a value of an annotation and makes the given visitor visit it. 2006 * 2007 * @param v 2008 * the start offset in {@link #b b} of the value to be read 2009 * (<i>not including the value name constant pool index</i>). 2010 * @param buf 2011 * buffer to be used to call {@link #readUTF8 readUTF8}, 2012 * {@link #readClass(int,char[]) readClass} or {@link #readConst 2013 * readConst}. 2014 * @param name 2015 * the name of the value to be read. 2016 * @param av 2017 * the visitor that must visit the value. 2018 * @return the end offset of the annotation value. 2019 */ 2020 private int readAnnotationValue(int v, final char[] buf, final String name, 2021 final AnnotationVisitor av) { 2022 int i; 2023 if (av == null) { 2024 switch (b[v] & 0xFF) { 2025 case 'e': // enum_const_value 2026 return v + 5; 2027 case '@': // annotation_value 2028 return readAnnotationValues(v + 3, buf, true, null); 2029 case '[': // array_value 2030 return readAnnotationValues(v + 1, buf, false, null); 2031 default: 2032 return v + 3; 2033 } 2034 } 2035 switch (b[v++] & 0xFF) { 2036 case 'I': // pointer to CONSTANT_Integer 2037 case 'J': // pointer to CONSTANT_Long 2038 case 'F': // pointer to CONSTANT_Float 2039 case 'D': // pointer to CONSTANT_Double 2040 av.visit(name, readConst(readUnsignedShort(v), buf)); 2041 v += 2; 2042 break; 2043 case 'B': // pointer to CONSTANT_Byte 2044 av.visit(name, (byte) readInt(items[readUnsignedShort(v)])); 2045 v += 2; 2046 break; 2047 case 'Z': // pointer to CONSTANT_Boolean 2048 av.visit(name, 2049 readInt(items[readUnsignedShort(v)]) == 0 ? Boolean.FALSE 2050 : Boolean.TRUE); 2051 v += 2; 2052 break; 2053 case 'S': // pointer to CONSTANT_Short 2054 av.visit(name, (short) readInt(items[readUnsignedShort(v)])); 2055 v += 2; 2056 break; 2057 case 'C': // pointer to CONSTANT_Char 2058 av.visit(name, (char) readInt(items[readUnsignedShort(v)])); 2059 v += 2; 2060 break; 2061 case 's': // pointer to CONSTANT_Utf8 2062 av.visit(name, readUTF8(v, buf)); 2063 v += 2; 2064 break; 2065 case 'e': // enum_const_value 2066 av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf)); 2067 v += 4; 2068 break; 2069 case 'c': // class_info 2070 av.visit(name, Type.getType(readUTF8(v, buf))); 2071 v += 2; 2072 break; 2073 case '@': // annotation_value 2074 v = readAnnotationValues(v + 2, buf, true, 2075 av.visitAnnotation(name, readUTF8(v, buf))); 2076 break; 2077 case '[': // array_value 2078 int size = readUnsignedShort(v); 2079 v += 2; 2080 if (size == 0) { 2081 return readAnnotationValues(v - 2, buf, false, 2082 av.visitArray(name)); 2083 } 2084 switch (this.b[v++] & 0xFF) { 2085 case 'B': 2086 byte[] bv = new byte[size]; 2087 for (i = 0; i < size; i++) { 2088 bv[i] = (byte) readInt(items[readUnsignedShort(v)]); 2089 v += 3; 2090 } 2091 av.visit(name, bv); 2092 --v; 2093 break; 2094 case 'Z': 2095 boolean[] zv = new boolean[size]; 2096 for (i = 0; i < size; i++) { 2097 zv[i] = readInt(items[readUnsignedShort(v)]) != 0; 2098 v += 3; 2099 } 2100 av.visit(name, zv); 2101 --v; 2102 break; 2103 case 'S': 2104 short[] sv = new short[size]; 2105 for (i = 0; i < size; i++) { 2106 sv[i] = (short) readInt(items[readUnsignedShort(v)]); 2107 v += 3; 2108 } 2109 av.visit(name, sv); 2110 --v; 2111 break; 2112 case 'C': 2113 char[] cv = new char[size]; 2114 for (i = 0; i < size; i++) { 2115 cv[i] = (char) readInt(items[readUnsignedShort(v)]); 2116 v += 3; 2117 } 2118 av.visit(name, cv); 2119 --v; 2120 break; 2121 case 'I': 2122 int[] iv = new int[size]; 2123 for (i = 0; i < size; i++) { 2124 iv[i] = readInt(items[readUnsignedShort(v)]); 2125 v += 3; 2126 } 2127 av.visit(name, iv); 2128 --v; 2129 break; 2130 case 'J': 2131 long[] lv = new long[size]; 2132 for (i = 0; i < size; i++) { 2133 lv[i] = readLong(items[readUnsignedShort(v)]); 2134 v += 3; 2135 } 2136 av.visit(name, lv); 2137 --v; 2138 break; 2139 case 'F': 2140 float[] fv = new float[size]; 2141 for (i = 0; i < size; i++) { 2142 fv[i] = Float 2143 .intBitsToFloat(readInt(items[readUnsignedShort(v)])); 2144 v += 3; 2145 } 2146 av.visit(name, fv); 2147 --v; 2148 break; 2149 case 'D': 2150 double[] dv = new double[size]; 2151 for (i = 0; i < size; i++) { 2152 dv[i] = Double 2153 .longBitsToDouble(readLong(items[readUnsignedShort(v)])); 2154 v += 3; 2155 } 2156 av.visit(name, dv); 2157 --v; 2158 break; 2159 default: 2160 v = readAnnotationValues(v - 3, buf, false, av.visitArray(name)); 2161 } 2162 } 2163 return v; 2164 } 2165 2166 /** 2167 * Computes the implicit frame of the method currently being parsed (as 2168 * defined in the given {@link Context}) and stores it in the given context. 2169 * 2170 * @param frame 2171 * information about the class being parsed. 2172 */ 2173 private void getImplicitFrame(final Context frame) { 2174 String desc = frame.desc; 2175 Object[] locals = frame.local; 2176 int local = 0; 2177 if ((frame.access & Opcodes.ACC_STATIC) == 0) { 2178 if ("<init>".equals(frame.name)) { 2179 locals[local++] = Opcodes.UNINITIALIZED_THIS; 2180 } else { 2181 locals[local++] = readClass(header + 2, frame.buffer); 2182 } 2183 } 2184 int i = 1; 2185 loop: while (true) { 2186 int j = i; 2187 switch (desc.charAt(i++)) { 2188 case 'Z': 2189 case 'C': 2190 case 'B': 2191 case 'S': 2192 case 'I': 2193 locals[local++] = Opcodes.INTEGER; 2194 break; 2195 case 'F': 2196 locals[local++] = Opcodes.FLOAT; 2197 break; 2198 case 'J': 2199 locals[local++] = Opcodes.LONG; 2200 break; 2201 case 'D': 2202 locals[local++] = Opcodes.DOUBLE; 2203 break; 2204 case '[': 2205 while (desc.charAt(i) == '[') { 2206 ++i; 2207 } 2208 if (desc.charAt(i) == 'L') { 2209 ++i; 2210 while (desc.charAt(i) != ';') { 2211 ++i; 2212 } 2213 } 2214 locals[local++] = desc.substring(j, ++i); 2215 break; 2216 case 'L': 2217 while (desc.charAt(i) != ';') { 2218 ++i; 2219 } 2220 locals[local++] = desc.substring(j + 1, i++); 2221 break; 2222 default: 2223 break loop; 2224 } 2225 } 2226 frame.localCount = local; 2227 } 2228 2229 /** 2230 * Reads a stack map frame and stores the result in the given 2231 * {@link Context} object. 2232 * 2233 * @param stackMap 2234 * the start offset of a stack map frame in the class file. 2235 * @param zip 2236 * if the stack map frame at stackMap is compressed or not. 2237 * @param unzip 2238 * if the stack map frame must be uncompressed. 2239 * @param frame 2240 * where the parsed stack map frame must be stored. 2241 * @return the offset of the first byte following the parsed frame. 2242 */ 2243 private int readFrame(int stackMap, boolean zip, boolean unzip, 2244 Context frame) { 2245 char[] c = frame.buffer; 2246 Label[] labels = frame.labels; 2247 int tag; 2248 int delta; 2249 if (zip) { 2250 tag = b[stackMap++] & 0xFF; 2251 } else { 2252 tag = MethodWriter.FULL_FRAME; 2253 frame.offset = -1; 2254 } 2255 frame.localDiff = 0; 2256 if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME) { 2257 delta = tag; 2258 frame.mode = Opcodes.F_SAME; 2259 frame.stackCount = 0; 2260 } else if (tag < MethodWriter.RESERVED) { 2261 delta = tag - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME; 2262 stackMap = readFrameType(frame.stack, 0, stackMap, c, labels); 2263 frame.mode = Opcodes.F_SAME1; 2264 frame.stackCount = 1; 2265 } else { 2266 delta = readUnsignedShort(stackMap); 2267 stackMap += 2; 2268 if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) { 2269 stackMap = readFrameType(frame.stack, 0, stackMap, c, labels); 2270 frame.mode = Opcodes.F_SAME1; 2271 frame.stackCount = 1; 2272 } else if (tag >= MethodWriter.CHOP_FRAME 2273 && tag < MethodWriter.SAME_FRAME_EXTENDED) { 2274 frame.mode = Opcodes.F_CHOP; 2275 frame.localDiff = MethodWriter.SAME_FRAME_EXTENDED - tag; 2276 frame.localCount -= frame.localDiff; 2277 frame.stackCount = 0; 2278 } else if (tag == MethodWriter.SAME_FRAME_EXTENDED) { 2279 frame.mode = Opcodes.F_SAME; 2280 frame.stackCount = 0; 2281 } else if (tag < MethodWriter.FULL_FRAME) { 2282 int local = unzip ? frame.localCount : 0; 2283 for (int i = tag - MethodWriter.SAME_FRAME_EXTENDED; i > 0; i--) { 2284 stackMap = readFrameType(frame.local, local++, stackMap, c, 2285 labels); 2286 } 2287 frame.mode = Opcodes.F_APPEND; 2288 frame.localDiff = tag - MethodWriter.SAME_FRAME_EXTENDED; 2289 frame.localCount += frame.localDiff; 2290 frame.stackCount = 0; 2291 } else { // if (tag == FULL_FRAME) { 2292 frame.mode = Opcodes.F_FULL; 2293 int n = readUnsignedShort(stackMap); 2294 stackMap += 2; 2295 frame.localDiff = n; 2296 frame.localCount = n; 2297 for (int local = 0; n > 0; n--) { 2298 stackMap = readFrameType(frame.local, local++, stackMap, c, 2299 labels); 2300 } 2301 n = readUnsignedShort(stackMap); 2302 stackMap += 2; 2303 frame.stackCount = n; 2304 for (int stack = 0; n > 0; n--) { 2305 stackMap = readFrameType(frame.stack, stack++, stackMap, c, 2306 labels); 2307 } 2308 } 2309 } 2310 frame.offset += delta + 1; 2311 createLabel(frame.offset, labels); 2312 return stackMap; 2313 } 2314 2315 /** 2316 * Reads a stack map frame type and stores it at the given index in the 2317 * given array. 2318 * 2319 * @param frame 2320 * the array where the parsed type must be stored. 2321 * @param index 2322 * the index in 'frame' where the parsed type must be stored. 2323 * @param v 2324 * the start offset of the stack map frame type to read. 2325 * @param buf 2326 * a buffer to read strings. 2327 * @param labels 2328 * the labels of the method currently being parsed, indexed by 2329 * their offset. If the parsed type is an Uninitialized type, a 2330 * new label for the corresponding NEW instruction is stored in 2331 * this array if it does not already exist. 2332 * @return the offset of the first byte after the parsed type. 2333 */ 2334 private int readFrameType(final Object[] frame, final int index, int v, 2335 final char[] buf, final Label[] labels) { 2336 int type = b[v++] & 0xFF; 2337 switch (type) { 2338 case 0: 2339 frame[index] = Opcodes.TOP; 2340 break; 2341 case 1: 2342 frame[index] = Opcodes.INTEGER; 2343 break; 2344 case 2: 2345 frame[index] = Opcodes.FLOAT; 2346 break; 2347 case 3: 2348 frame[index] = Opcodes.DOUBLE; 2349 break; 2350 case 4: 2351 frame[index] = Opcodes.LONG; 2352 break; 2353 case 5: 2354 frame[index] = Opcodes.NULL; 2355 break; 2356 case 6: 2357 frame[index] = Opcodes.UNINITIALIZED_THIS; 2358 break; 2359 case 7: // Object 2360 frame[index] = readClass(v, buf); 2361 v += 2; 2362 break; 2363 default: // Uninitialized 2364 frame[index] = createLabel(readUnsignedShort(v), labels); 2365 v += 2; 2366 } 2367 return v; 2368 } 2369 2370 /** 2371 * Returns the label corresponding to the given offset. The default 2372 * implementation of this method creates a label for the given offset if it 2373 * has not been already created. 2374 * 2375 * @param offset 2376 * a bytecode offset in a method. 2377 * @param labels 2378 * the already created labels, indexed by their offset. If a 2379 * label already exists for offset this method must not create a 2380 * new one. Otherwise it must store the new label in this array. 2381 * @return a non null Label, which must be equal to labels[offset]. 2382 */ 2383 protected Label readLabel(int offset, Label[] labels) { 2384 if (labels[offset] == null) { 2385 labels[offset] = new Label(); 2386 } 2387 return labels[offset]; 2388 } 2389 2390 /** 2391 * Creates a label without the Label.DEBUG flag set, for the given offset. 2392 * The label is created with a call to {@link #readLabel} and its 2393 * Label.DEBUG flag is cleared. 2394 * 2395 * @param offset 2396 * a bytecode offset in a method. 2397 * @param labels 2398 * the already created labels, indexed by their offset. 2399 * @return a Label without the Label.DEBUG flag set. 2400 */ 2401 private Label createLabel(int offset, Label[] labels) { 2402 Label label = readLabel(offset, labels); 2403 label.status &= ~Label.DEBUG; 2404 return label; 2405 } 2406 2407 /** 2408 * Creates a label with the Label.DEBUG flag set, if there is no already 2409 * existing label for the given offset (otherwise does nothing). The label 2410 * is created with a call to {@link #readLabel}. 2411 * 2412 * @param offset 2413 * a bytecode offset in a method. 2414 * @param labels 2415 * the already created labels, indexed by their offset. 2416 */ 2417 private void createDebugLabel(int offset, Label[] labels) { 2418 if (labels[offset] == null) { 2419 readLabel(offset, labels).status |= Label.DEBUG; 2420 } 2421 } 2422 2423 /** 2424 * Returns the start index of the attribute_info structure of this class. 2425 * 2426 * @return the start index of the attribute_info structure of this class. 2427 */ 2428 private int getAttributes() { 2429 // skips the header 2430 int u = header + 8 + readUnsignedShort(header + 6) * 2; 2431 // skips fields and methods 2432 for (int i = readUnsignedShort(u); i > 0; --i) { 2433 for (int j = readUnsignedShort(u + 8); j > 0; --j) { 2434 u += 6 + readInt(u + 12); 2435 } 2436 u += 8; 2437 } 2438 u += 2; 2439 for (int i = readUnsignedShort(u); i > 0; --i) { 2440 for (int j = readUnsignedShort(u + 8); j > 0; --j) { 2441 u += 6 + readInt(u + 12); 2442 } 2443 u += 8; 2444 } 2445 // the attribute_info structure starts just after the methods 2446 return u + 2; 2447 } 2448 2449 /** 2450 * Reads an attribute in {@link #b b}. 2451 * 2452 * @param attrs 2453 * prototypes of the attributes that must be parsed during the 2454 * visit of the class. Any attribute whose type is not equal to 2455 * the type of one the prototypes is ignored (i.e. an empty 2456 * {@link Attribute} instance is returned). 2457 * @param type 2458 * the type of the attribute. 2459 * @param off 2460 * index of the first byte of the attribute's content in 2461 * {@link #b b}. The 6 attribute header bytes, containing the 2462 * type and the length of the attribute, are not taken into 2463 * account here (they have already been read). 2464 * @param len 2465 * the length of the attribute's content. 2466 * @param buf 2467 * buffer to be used to call {@link #readUTF8 readUTF8}, 2468 * {@link #readClass(int,char[]) readClass} or {@link #readConst 2469 * readConst}. 2470 * @param codeOff 2471 * index of the first byte of code's attribute content in 2472 * {@link #b b}, or -1 if the attribute to be read is not a code 2473 * attribute. The 6 attribute header bytes, containing the type 2474 * and the length of the attribute, are not taken into account 2475 * here. 2476 * @param labels 2477 * the labels of the method's code, or <tt>null</tt> if the 2478 * attribute to be read is not a code attribute. 2479 * @return the attribute that has been read, or <tt>null</tt> to skip this 2480 * attribute. 2481 */ 2482 private Attribute readAttribute(final Attribute[] attrs, final String type, 2483 final int off, final int len, final char[] buf, final int codeOff, 2484 final Label[] labels) { 2485 for (int i = 0; i < attrs.length; ++i) { 2486 if (attrs[i].type.equals(type)) { 2487 return attrs[i].read(this, off, len, buf, codeOff, labels); 2488 } 2489 } 2490 return new Attribute(type).read(this, off, len, null, -1, null); 2491 } 2492 2493 // ------------------------------------------------------------------------ 2494 // Utility methods: low level parsing 2495 // ------------------------------------------------------------------------ 2496 2497 /** 2498 * Returns the number of constant pool items in {@link #b b}. 2499 * 2500 * @return the number of constant pool items in {@link #b b}. 2501 */ 2502 public int getItemCount() { 2503 return items.length; 2504 } 2505 2506 /** 2507 * Returns the start index of the constant pool item in {@link #b b}, plus 2508 * one. <i>This method is intended for {@link Attribute} sub classes, and is 2509 * normally not needed by class generators or adapters.</i> 2510 * 2511 * @param item 2512 * the index a constant pool item. 2513 * @return the start index of the constant pool item in {@link #b b}, plus 2514 * one. 2515 */ 2516 public int getItem(final int item) { 2517 return items[item]; 2518 } 2519 2520 /** 2521 * Returns the maximum length of the strings contained in the constant pool 2522 * of the class. 2523 * 2524 * @return the maximum length of the strings contained in the constant pool 2525 * of the class. 2526 */ 2527 public int getMaxStringLength() { 2528 return maxStringLength; 2529 } 2530 2531 /** 2532 * Reads a byte value in {@link #b b}. <i>This method is intended for 2533 * {@link Attribute} sub classes, and is normally not needed by class 2534 * generators or adapters.</i> 2535 * 2536 * @param index 2537 * the start index of the value to be read in {@link #b b}. 2538 * @return the read value. 2539 */ 2540 public int readByte(final int index) { 2541 return b[index] & 0xFF; 2542 } 2543 2544 /** 2545 * Reads an unsigned short value in {@link #b b}. <i>This method is intended 2546 * for {@link Attribute} sub classes, and is normally not needed by class 2547 * generators or adapters.</i> 2548 * 2549 * @param index 2550 * the start index of the value to be read in {@link #b b}. 2551 * @return the read value. 2552 */ 2553 public int readUnsignedShort(final int index) { 2554 byte[] b = this.b; 2555 return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF); 2556 } 2557 2558 /** 2559 * Reads a signed short value in {@link #b b}. <i>This method is intended 2560 * for {@link Attribute} sub classes, and is normally not needed by class 2561 * generators or adapters.</i> 2562 * 2563 * @param index 2564 * the start index of the value to be read in {@link #b b}. 2565 * @return the read value. 2566 */ 2567 public short readShort(final int index) { 2568 byte[] b = this.b; 2569 return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF)); 2570 } 2571 2572 /** 2573 * Reads a signed int value in {@link #b b}. <i>This method is intended for 2574 * {@link Attribute} sub classes, and is normally not needed by class 2575 * generators or adapters.</i> 2576 * 2577 * @param index 2578 * the start index of the value to be read in {@link #b b}. 2579 * @return the read value. 2580 */ 2581 public int readInt(final int index) { 2582 byte[] b = this.b; 2583 return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16) 2584 | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF); 2585 } 2586 2587 /** 2588 * Reads a signed long value in {@link #b b}. <i>This method is intended for 2589 * {@link Attribute} sub classes, and is normally not needed by class 2590 * generators or adapters.</i> 2591 * 2592 * @param index 2593 * the start index of the value to be read in {@link #b b}. 2594 * @return the read value. 2595 */ 2596 public long readLong(final int index) { 2597 long l1 = readInt(index); 2598 long l0 = readInt(index + 4) & 0xFFFFFFFFL; 2599 return (l1 << 32) | l0; 2600 } 2601 2602 /** 2603 * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method 2604 * is intended for {@link Attribute} sub classes, and is normally not needed 2605 * by class generators or adapters.</i> 2606 * 2607 * @param index 2608 * the start index of an unsigned short value in {@link #b b}, 2609 * whose value is the index of an UTF8 constant pool item. 2610 * @param buf 2611 * buffer to be used to read the item. This buffer must be 2612 * sufficiently large. It is not automatically resized. 2613 * @return the String corresponding to the specified UTF8 item. 2614 */ 2615 public String readUTF8(int index, final char[] buf) { 2616 int item = readUnsignedShort(index); 2617 if (index == 0 || item == 0) { 2618 return null; 2619 } 2620 String s = strings[item]; 2621 if (s != null) { 2622 return s; 2623 } 2624 index = items[item]; 2625 return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf); 2626 } 2627 2628 /** 2629 * Reads UTF8 string in {@link #b b}. 2630 * 2631 * @param index 2632 * start offset of the UTF8 string to be read. 2633 * @param utfLen 2634 * length of the UTF8 string to be read. 2635 * @param buf 2636 * buffer to be used to read the string. This buffer must be 2637 * sufficiently large. It is not automatically resized. 2638 * @return the String corresponding to the specified UTF8 string. 2639 */ 2640 private String readUTF(int index, final int utfLen, final char[] buf) { 2641 int endIndex = index + utfLen; 2642 byte[] b = this.b; 2643 int strLen = 0; 2644 int c; 2645 int st = 0; 2646 char cc = 0; 2647 while (index < endIndex) { 2648 c = b[index++]; 2649 switch (st) { 2650 case 0: 2651 c = c & 0xFF; 2652 if (c < 0x80) { // 0xxxxxxx 2653 buf[strLen++] = (char) c; 2654 } else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx 2655 cc = (char) (c & 0x1F); 2656 st = 1; 2657 } else { // 1110 xxxx 10xx xxxx 10xx xxxx 2658 cc = (char) (c & 0x0F); 2659 st = 2; 2660 } 2661 break; 2662 2663 case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char 2664 buf[strLen++] = (char) ((cc << 6) | (c & 0x3F)); 2665 st = 0; 2666 break; 2667 2668 case 2: // byte 2 of 3-byte char 2669 cc = (char) ((cc << 6) | (c & 0x3F)); 2670 st = 1; 2671 break; 2672 } 2673 } 2674 return new String(buf, 0, strLen); 2675 } 2676 2677 /** 2678 * Read a stringish constant item (CONSTANT_Class, CONSTANT_String, 2679 * CONSTANT_MethodType, CONSTANT_Module or CONSTANT_Package 2680 * @param index 2681 * @param buf 2682 * @return 2683 */ 2684 private String readStringish(final int index, final char[] buf) { 2685 // computes the start index of the item in b 2686 // and reads the CONSTANT_Utf8 item designated by 2687 // the first two bytes of this item 2688 return readUTF8(items[readUnsignedShort(index)], buf); 2689 } 2690 2691 /** 2692 * Reads a class constant pool item in {@link #b b}. <i>This method is 2693 * intended for {@link Attribute} sub classes, and is normally not needed by 2694 * class generators or adapters.</i> 2695 * 2696 * @param index 2697 * the start index of an unsigned short value in {@link #b b}, 2698 * whose value is the index of a class constant pool item. 2699 * @param buf 2700 * buffer to be used to read the item. This buffer must be 2701 * sufficiently large. It is not automatically resized. 2702 * @return the String corresponding to the specified class item. 2703 */ 2704 public String readClass(final int index, final char[] buf) { 2705 return readStringish(index, buf); 2706 } 2707 2708 /** 2709 * Reads a module constant pool item in {@link #b b}. <i>This method is 2710 * intended for {@link Attribute} sub classes, and is normally not needed by 2711 * class generators or adapters.</i> 2712 * 2713 * @param index 2714 * the start index of an unsigned short value in {@link #b b}, 2715 * whose value is the index of a module constant pool item. 2716 * @param buf 2717 * buffer to be used to read the item. This buffer must be 2718 * sufficiently large. It is not automatically resized. 2719 * @return the String corresponding to the specified module item. 2720 */ 2721 public String readModule(final int index, final char[] buf) { 2722 return readStringish(index, buf); 2723 } 2724 2725 /** 2726 * Reads a module constant pool item in {@link #b b}. <i>This method is 2727 * intended for {@link Attribute} sub classes, and is normally not needed by 2728 * class generators or adapters.</i> 2729 * 2730 * @param index 2731 * the start index of an unsigned short value in {@link #b b}, 2732 * whose value is the index of a module constant pool item. 2733 * @param buf 2734 * buffer to be used to read the item. This buffer must be 2735 * sufficiently large. It is not automatically resized. 2736 * @return the String corresponding to the specified module item. 2737 */ 2738 public String readPackage(final int index, final char[] buf) { 2739 return readStringish(index, buf); 2740 } 2741 2742 /** 2743 * Reads a numeric or string constant pool item in {@link #b b}. <i>This 2744 * method is intended for {@link Attribute} sub classes, and is normally not 2745 * needed by class generators or adapters.</i> 2746 * 2747 * @param item 2748 * the index of a constant pool item. 2749 * @param buf 2750 * buffer to be used to read the item. This buffer must be 2751 * sufficiently large. It is not automatically resized. 2752 * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double}, 2753 * {@link String}, {@link Type} or {@link Handle} corresponding to 2754 * the given constant pool item. 2755 */ 2756 public Object readConst(final int item, final char[] buf) { 2757 int index = items[item]; 2758 switch (b[index - 1]) { 2759 case ClassWriter.INT: 2760 return readInt(index); 2761 case ClassWriter.FLOAT: 2762 return Float.intBitsToFloat(readInt(index)); 2763 case ClassWriter.LONG: 2764 return readLong(index); 2765 case ClassWriter.DOUBLE: 2766 return Double.longBitsToDouble(readLong(index)); 2767 case ClassWriter.CLASS: 2768 return Type.getObjectType(readUTF8(index, buf)); 2769 case ClassWriter.STR: 2770 return readUTF8(index, buf); 2771 case ClassWriter.MTYPE: 2772 return Type.getMethodType(readUTF8(index, buf)); 2773 default: // case ClassWriter.HANDLE_BASE + [1..9]: 2774 int tag = readByte(index); 2775 int[] items = this.items; 2776 int cpIndex = items[readUnsignedShort(index + 1)]; 2777 boolean itf = b[cpIndex - 1] == ClassWriter.IMETH; 2778 String owner = readClass(cpIndex, buf); 2779 cpIndex = items[readUnsignedShort(cpIndex + 2)]; 2780 String name = readUTF8(cpIndex, buf); 2781 String desc = readUTF8(cpIndex + 2, buf); 2782 return new Handle(tag, owner, name, desc, itf); 2783 } 2784 } 2785 }