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