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