1 // ASM: a very small and fast Java bytecode manipulation framework 2 // Copyright (c) 2000-2011 INRIA, France Telecom 3 // All rights reserved. 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions 7 // are met: 8 // 1. Redistributions of source code must retain the above copyright 9 // notice, this list of conditions and the following disclaimer. 10 // 2. Redistributions in binary form must reproduce the above copyright 11 // notice, this list of conditions and the following disclaimer in the 12 // documentation and/or other materials provided with the distribution. 13 // 3. Neither the name of the copyright holders nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 // THE POSSIBILITY OF SUCH DAMAGE. 28 package org.objectweb.asm; 29 30 /** 31 * A {@link ClassVisitor} that generates a corresponding ClassFile structure, as defined in the Java 32 * Virtual Machine Specification (JVMS). It can be used alone, to generate a Java class "from 33 * scratch", or with one or more {@link ClassReader} and adapter {@link ClassVisitor} to generate a 34 * modified class from one or more existing Java classes. 35 * 36 * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html">JVMS 4</a> 37 * @author Eric Bruneton 38 */ 39 public class ClassWriter extends ClassVisitor { 40 41 /** 42 * A flag to automatically compute the maximum stack size and the maximum number of local 43 * variables of methods. If this flag is set, then the arguments of the {@link 44 * MethodVisitor#visitMaxs} method of the {@link MethodVisitor} returned by the {@link 45 * #visitMethod} method will be ignored, and computed automatically from the signature and the 46 * bytecode of each method. 47 * 48 * <p><b>Note:</b> for classes whose version is {@link Opcodes#V1_7} of more, this option requires 49 * valid stack map frames. The maximum stack size is then computed from these frames, and from the 50 * bytecode instructions in between. If stack map frames are not present or must be recomputed, 51 * used {@link #COMPUTE_FRAMES} instead. 52 * 53 * @see #ClassWriter(int) 54 */ 55 public static final int COMPUTE_MAXS = 1; 56 57 /** 58 * A flag to automatically compute the stack map frames of methods from scratch. If this flag is 59 * set, then the calls to the {@link MethodVisitor#visitFrame} method are ignored, and the stack 60 * map frames are recomputed from the methods bytecode. The arguments of the {@link 61 * MethodVisitor#visitMaxs} method are also ignored and recomputed from the bytecode. In other 62 * words, {@link #COMPUTE_FRAMES} implies {@link #COMPUTE_MAXS}. 63 * 64 * @see #ClassWriter(int) 65 */ 66 public static final int COMPUTE_FRAMES = 2; 67 68 /** 69 * The flags passed to the constructor. Must be zero or more of {@link #COMPUTE_MAXS} and {@link 70 * #COMPUTE_FRAMES}. 71 */ 72 private final int flags; 73 74 // Note: fields are ordered as in the ClassFile structure, and those related to attributes are 75 // ordered as in Section 4.7 of the JVMS. 76 77 /** 78 * The minor_version and major_version fields of the JVMS ClassFile structure. minor_version is 79 * stored in the 16 most significant bits, and major_version in the 16 least significant bits. 80 */ 81 private int version; 82 83 /** The symbol table for this class (contains the constant_pool and the BootstrapMethods). */ 84 private final SymbolTable symbolTable; 85 86 /** 87 * The access_flags field of the JVMS ClassFile structure. This field can contain ASM specific 88 * access flags, such as {@link Opcodes#ACC_DEPRECATED} or {@link Opcodes#ACC_RECORD}, which are 89 * removed when generating the ClassFile structure. 90 */ 91 private int accessFlags; 92 93 /** The this_class field of the JVMS ClassFile structure. */ 94 private int thisClass; 95 96 /** The super_class field of the JVMS ClassFile structure. */ 97 private int superClass; 98 99 /** The interface_count field of the JVMS ClassFile structure. */ 100 private int interfaceCount; 101 102 /** The 'interfaces' array of the JVMS ClassFile structure. */ 103 private int[] interfaces; 104 105 /** 106 * The fields of this class, stored in a linked list of {@link FieldWriter} linked via their 107 * {@link FieldWriter#fv} field. This field stores the first element of this list. 108 */ 109 private FieldWriter firstField; 110 111 /** 112 * The fields of this class, stored in a linked list of {@link FieldWriter} linked via their 113 * {@link FieldWriter#fv} field. This field stores the last element of this list. 114 */ 115 private FieldWriter lastField; 116 117 /** 118 * The methods of this class, stored in a linked list of {@link MethodWriter} linked via their 119 * {@link MethodWriter#mv} field. This field stores the first element of this list. 120 */ 121 private MethodWriter firstMethod; 122 123 /** 124 * The methods of this class, stored in a linked list of {@link MethodWriter} linked via their 125 * {@link MethodWriter#mv} field. This field stores the last element of this list. 126 */ 127 private MethodWriter lastMethod; 128 129 /** The number_of_classes field of the InnerClasses attribute, or 0. */ 130 private int numberOfInnerClasses; 131 132 /** The 'classes' array of the InnerClasses attribute, or {@literal null}. */ 133 private ByteVector innerClasses; 134 135 /** The class_index field of the EnclosingMethod attribute, or 0. */ 136 private int enclosingClassIndex; 137 138 /** The method_index field of the EnclosingMethod attribute. */ 139 private int enclosingMethodIndex; 140 141 /** The signature_index field of the Signature attribute, or 0. */ 142 private int signatureIndex; 143 144 /** The source_file_index field of the SourceFile attribute, or 0. */ 145 private int sourceFileIndex; 146 147 /** The debug_extension field of the SourceDebugExtension attribute, or {@literal null}. */ 148 private ByteVector debugExtension; 149 150 /** 151 * The last runtime visible annotation of this class. The previous ones can be accessed with the 152 * {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}. 153 */ 154 private AnnotationWriter lastRuntimeVisibleAnnotation; 155 156 /** 157 * The last runtime invisible annotation of this class. The previous ones can be accessed with the 158 * {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}. 159 */ 160 private AnnotationWriter lastRuntimeInvisibleAnnotation; 161 162 /** 163 * The last runtime visible type annotation of this class. The previous ones can be accessed with 164 * the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}. 165 */ 166 private AnnotationWriter lastRuntimeVisibleTypeAnnotation; 167 168 /** 169 * The last runtime invisible type annotation of this class. The previous ones can be accessed 170 * with the {@link AnnotationWriter#previousAnnotation} field. May be {@literal null}. 171 */ 172 private AnnotationWriter lastRuntimeInvisibleTypeAnnotation; 173 174 /** The Module attribute of this class, or {@literal null}. */ 175 private ModuleWriter moduleWriter; 176 177 /** The host_class_index field of the NestHost attribute, or 0. */ 178 private int nestHostClassIndex; 179 180 /** The number_of_classes field of the NestMembers attribute, or 0. */ 181 private int numberOfNestMemberClasses; 182 183 /** The 'classes' array of the NestMembers attribute, or {@literal null}. */ 184 private ByteVector nestMemberClasses; 185 186 /** The number_of_classes field of the PermittedSubclasses attribute, or 0. */ 187 private int numberOfPermittedSubclasses; 188 189 /** The 'classes' array of the PermittedSubclasses attribute, or {@literal null}. */ 190 private ByteVector permittedSubclasses; 191 192 /** 193 * The record components of this class, stored in a linked list of {@link RecordComponentWriter} 194 * linked via their {@link RecordComponentWriter#delegate} field. This field stores the first 195 * element of this list. 196 */ 197 private RecordComponentWriter firstRecordComponent; 198 199 /** 200 * The record components of this class, stored in a linked list of {@link RecordComponentWriter} 201 * linked via their {@link RecordComponentWriter#delegate} field. This field stores the last 202 * element of this list. 203 */ 204 private RecordComponentWriter lastRecordComponent; 205 206 /** 207 * The first non standard attribute of this class. The next ones can be accessed with the {@link 208 * Attribute#nextAttribute} field. May be {@literal null}. 209 * 210 * <p><b>WARNING</b>: this list stores the attributes in the <i>reverse</i> order of their visit. 211 * firstAttribute is actually the last attribute visited in {@link #visitAttribute}. The {@link 212 * #toByteArray} method writes the attributes in the order defined by this list, i.e. in the 213 * reverse order specified by the user. 214 */ 215 private Attribute firstAttribute; 216 217 /** 218 * Indicates what must be automatically computed in {@link MethodWriter}. Must be one of {@link 219 * MethodWriter#COMPUTE_NOTHING}, {@link MethodWriter#COMPUTE_MAX_STACK_AND_LOCAL}, {@link 220 * MethodWriter#COMPUTE_INSERTED_FRAMES}, or {@link MethodWriter#COMPUTE_ALL_FRAMES}. 221 */ 222 private int compute; 223 224 // ----------------------------------------------------------------------------------------------- 225 // Constructor 226 // ----------------------------------------------------------------------------------------------- 227 228 /** 229 * Constructs a new {@link ClassWriter} object. 230 * 231 * @param flags option flags that can be used to modify the default behavior of this class. Must 232 * be zero or more of {@link #COMPUTE_MAXS} and {@link #COMPUTE_FRAMES}. 233 */ ClassWriter(final int flags)234 public ClassWriter(final int flags) { 235 this(null, flags); 236 } 237 238 /** 239 * Constructs a new {@link ClassWriter} object and enables optimizations for "mostly add" bytecode 240 * transformations. These optimizations are the following: 241 * 242 * <ul> 243 * <li>The constant pool and bootstrap methods from the original class are copied as is in the 244 * new class, which saves time. New constant pool entries and new bootstrap methods will be 245 * added at the end if necessary, but unused constant pool entries or bootstrap methods 246 * <i>won't be removed</i>. 247 * <li>Methods that are not transformed are copied as is in the new class, directly from the 248 * original class bytecode (i.e. without emitting visit events for all the method 249 * instructions), which saves a <i>lot</i> of time. Untransformed methods are detected by 250 * the fact that the {@link ClassReader} receives {@link MethodVisitor} objects that come 251 * from a {@link ClassWriter} (and not from any other {@link ClassVisitor} instance). 252 * </ul> 253 * 254 * @param classReader the {@link ClassReader} used to read the original class. It will be used to 255 * copy the entire constant pool and bootstrap methods from the original class and also to 256 * copy other fragments of original bytecode where applicable. 257 * @param flags option flags that can be used to modify the default behavior of this class. Must 258 * be zero or more of {@link #COMPUTE_MAXS} and {@link #COMPUTE_FRAMES}. <i>These option flags 259 * do not affect methods that are copied as is in the new class. This means that neither the 260 * maximum stack size nor the stack frames will be computed for these methods</i>. 261 */ ClassWriter(final ClassReader classReader, final int flags)262 public ClassWriter(final ClassReader classReader, final int flags) { 263 super(/* latest api = */ Opcodes.ASM9); 264 this.flags = flags; 265 symbolTable = classReader == null ? new SymbolTable(this) : new SymbolTable(this, classReader); 266 if ((flags & COMPUTE_FRAMES) != 0) { 267 compute = MethodWriter.COMPUTE_ALL_FRAMES; 268 } else if ((flags & COMPUTE_MAXS) != 0) { 269 compute = MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL; 270 } else { 271 compute = MethodWriter.COMPUTE_NOTHING; 272 } 273 } 274 275 // ----------------------------------------------------------------------------------------------- 276 // Accessors 277 // ----------------------------------------------------------------------------------------------- 278 279 /** 280 * Returns true if all the given flags were passed to the constructor. 281 * 282 * @param flags some option flags. Must be zero or more of {@link #COMPUTE_MAXS} and {@link 283 * #COMPUTE_FRAMES}. 284 * @return true if all the given flags, or more, were passed to the constructor. 285 */ hasFlags(final int flags)286 public boolean hasFlags(final int flags) { 287 return (this.flags & flags) == flags; 288 } 289 290 // ----------------------------------------------------------------------------------------------- 291 // Implementation of the ClassVisitor abstract class 292 // ----------------------------------------------------------------------------------------------- 293 294 @Override visit( final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces)295 public final void visit( 296 final int version, 297 final int access, 298 final String name, 299 final String signature, 300 final String superName, 301 final String[] interfaces) { 302 this.version = version; 303 this.accessFlags = access; 304 this.thisClass = symbolTable.setMajorVersionAndClassName(version & 0xFFFF, name); 305 if (signature != null) { 306 this.signatureIndex = symbolTable.addConstantUtf8(signature); 307 } 308 this.superClass = superName == null ? 0 : symbolTable.addConstantClass(superName).index; 309 if (interfaces != null && interfaces.length > 0) { 310 interfaceCount = interfaces.length; 311 this.interfaces = new int[interfaceCount]; 312 for (int i = 0; i < interfaceCount; ++i) { 313 this.interfaces[i] = symbolTable.addConstantClass(interfaces[i]).index; 314 } 315 } 316 if (compute == MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL && (version & 0xFFFF) >= Opcodes.V1_7) { 317 compute = MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES; 318 } 319 } 320 321 @Override visitSource(final String file, final String debug)322 public final void visitSource(final String file, final String debug) { 323 if (file != null) { 324 sourceFileIndex = symbolTable.addConstantUtf8(file); 325 } 326 if (debug != null) { 327 debugExtension = new ByteVector().encodeUtf8(debug, 0, Integer.MAX_VALUE); 328 } 329 } 330 331 @Override visitModule( final String name, final int access, final String version)332 public final ModuleVisitor visitModule( 333 final String name, final int access, final String version) { 334 return moduleWriter = 335 new ModuleWriter( 336 symbolTable, 337 symbolTable.addConstantModule(name).index, 338 access, 339 version == null ? 0 : symbolTable.addConstantUtf8(version)); 340 } 341 342 @Override visitNestHost(final String nestHost)343 public final void visitNestHost(final String nestHost) { 344 nestHostClassIndex = symbolTable.addConstantClass(nestHost).index; 345 } 346 347 @Override visitOuterClass( final String owner, final String name, final String descriptor)348 public final void visitOuterClass( 349 final String owner, final String name, final String descriptor) { 350 enclosingClassIndex = symbolTable.addConstantClass(owner).index; 351 if (name != null && descriptor != null) { 352 enclosingMethodIndex = symbolTable.addConstantNameAndType(name, descriptor); 353 } 354 } 355 356 @Override visitAnnotation(final String descriptor, final boolean visible)357 public final AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { 358 if (visible) { 359 return lastRuntimeVisibleAnnotation = 360 AnnotationWriter.create(symbolTable, descriptor, lastRuntimeVisibleAnnotation); 361 } else { 362 return lastRuntimeInvisibleAnnotation = 363 AnnotationWriter.create(symbolTable, descriptor, lastRuntimeInvisibleAnnotation); 364 } 365 } 366 367 @Override visitTypeAnnotation( final int typeRef, final TypePath typePath, final String descriptor, final boolean visible)368 public final AnnotationVisitor visitTypeAnnotation( 369 final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { 370 if (visible) { 371 return lastRuntimeVisibleTypeAnnotation = 372 AnnotationWriter.create( 373 symbolTable, typeRef, typePath, descriptor, lastRuntimeVisibleTypeAnnotation); 374 } else { 375 return lastRuntimeInvisibleTypeAnnotation = 376 AnnotationWriter.create( 377 symbolTable, typeRef, typePath, descriptor, lastRuntimeInvisibleTypeAnnotation); 378 } 379 } 380 381 @Override visitAttribute(final Attribute attribute)382 public final void visitAttribute(final Attribute attribute) { 383 // Store the attributes in the <i>reverse</i> order of their visit by this method. 384 attribute.nextAttribute = firstAttribute; 385 firstAttribute = attribute; 386 } 387 388 @Override visitNestMember(final String nestMember)389 public final void visitNestMember(final String nestMember) { 390 if (nestMemberClasses == null) { 391 nestMemberClasses = new ByteVector(); 392 } 393 ++numberOfNestMemberClasses; 394 nestMemberClasses.putShort(symbolTable.addConstantClass(nestMember).index); 395 } 396 397 @Override visitPermittedSubclass(final String permittedSubclass)398 public final void visitPermittedSubclass(final String permittedSubclass) { 399 if (permittedSubclasses == null) { 400 permittedSubclasses = new ByteVector(); 401 } 402 ++numberOfPermittedSubclasses; 403 permittedSubclasses.putShort(symbolTable.addConstantClass(permittedSubclass).index); 404 } 405 406 @Override visitInnerClass( final String name, final String outerName, final String innerName, final int access)407 public final void visitInnerClass( 408 final String name, final String outerName, final String innerName, final int access) { 409 if (innerClasses == null) { 410 innerClasses = new ByteVector(); 411 } 412 // Section 4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the constant_pool table 413 // which represents a class or interface C that is not a package member must have exactly one 414 // corresponding entry in the classes array". To avoid duplicates we keep track in the info 415 // field of the Symbol of each CONSTANT_Class_info entry C whether an inner class entry has 416 // already been added for C. If so, we store the index of this inner class entry (plus one) in 417 // the info field. This trick allows duplicate detection in O(1) time. 418 Symbol nameSymbol = symbolTable.addConstantClass(name); 419 if (nameSymbol.info == 0) { 420 ++numberOfInnerClasses; 421 innerClasses.putShort(nameSymbol.index); 422 innerClasses.putShort(outerName == null ? 0 : symbolTable.addConstantClass(outerName).index); 423 innerClasses.putShort(innerName == null ? 0 : symbolTable.addConstantUtf8(innerName)); 424 innerClasses.putShort(access); 425 nameSymbol.info = numberOfInnerClasses; 426 } 427 // Else, compare the inner classes entry nameSymbol.info - 1 with the arguments of this method 428 // and throw an exception if there is a difference? 429 } 430 431 @Override visitRecordComponent( final String name, final String descriptor, final String signature)432 public final RecordComponentVisitor visitRecordComponent( 433 final String name, final String descriptor, final String signature) { 434 RecordComponentWriter recordComponentWriter = 435 new RecordComponentWriter(symbolTable, name, descriptor, signature); 436 if (firstRecordComponent == null) { 437 firstRecordComponent = recordComponentWriter; 438 } else { 439 lastRecordComponent.delegate = recordComponentWriter; 440 } 441 return lastRecordComponent = recordComponentWriter; 442 } 443 444 @Override visitField( final int access, final String name, final String descriptor, final String signature, final Object value)445 public final FieldVisitor visitField( 446 final int access, 447 final String name, 448 final String descriptor, 449 final String signature, 450 final Object value) { 451 FieldWriter fieldWriter = 452 new FieldWriter(symbolTable, access, name, descriptor, signature, value); 453 if (firstField == null) { 454 firstField = fieldWriter; 455 } else { 456 lastField.fv = fieldWriter; 457 } 458 return lastField = fieldWriter; 459 } 460 461 @Override visitMethod( final int access, final String name, final String descriptor, final String signature, final String[] exceptions)462 public final MethodVisitor visitMethod( 463 final int access, 464 final String name, 465 final String descriptor, 466 final String signature, 467 final String[] exceptions) { 468 MethodWriter methodWriter = 469 new MethodWriter(symbolTable, access, name, descriptor, signature, exceptions, compute); 470 if (firstMethod == null) { 471 firstMethod = methodWriter; 472 } else { 473 lastMethod.mv = methodWriter; 474 } 475 return lastMethod = methodWriter; 476 } 477 478 @Override visitEnd()479 public final void visitEnd() { 480 // Nothing to do. 481 } 482 483 // ----------------------------------------------------------------------------------------------- 484 // Other public methods 485 // ----------------------------------------------------------------------------------------------- 486 487 /** 488 * Returns the content of the class file that was built by this ClassWriter. 489 * 490 * @return the binary content of the JVMS ClassFile structure that was built by this ClassWriter. 491 * @throws ClassTooLargeException if the constant pool of the class is too large. 492 * @throws MethodTooLargeException if the Code attribute of a method is too large. 493 */ toByteArray()494 public byte[] toByteArray() { 495 // First step: compute the size in bytes of the ClassFile structure. 496 // The magic field uses 4 bytes, 10 mandatory fields (minor_version, major_version, 497 // constant_pool_count, access_flags, this_class, super_class, interfaces_count, fields_count, 498 // methods_count and attributes_count) use 2 bytes each, and each interface uses 2 bytes too. 499 int size = 24 + 2 * interfaceCount; 500 int fieldsCount = 0; 501 FieldWriter fieldWriter = firstField; 502 while (fieldWriter != null) { 503 ++fieldsCount; 504 size += fieldWriter.computeFieldInfoSize(); 505 fieldWriter = (FieldWriter) fieldWriter.fv; 506 } 507 int methodsCount = 0; 508 MethodWriter methodWriter = firstMethod; 509 while (methodWriter != null) { 510 ++methodsCount; 511 size += methodWriter.computeMethodInfoSize(); 512 methodWriter = (MethodWriter) methodWriter.mv; 513 } 514 515 // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS. 516 int attributesCount = 0; 517 if (innerClasses != null) { 518 ++attributesCount; 519 size += 8 + innerClasses.length; 520 symbolTable.addConstantUtf8(Constants.INNER_CLASSES); 521 } 522 if (enclosingClassIndex != 0) { 523 ++attributesCount; 524 size += 10; 525 symbolTable.addConstantUtf8(Constants.ENCLOSING_METHOD); 526 } 527 if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && (version & 0xFFFF) < Opcodes.V1_5) { 528 ++attributesCount; 529 size += 6; 530 symbolTable.addConstantUtf8(Constants.SYNTHETIC); 531 } 532 if (signatureIndex != 0) { 533 ++attributesCount; 534 size += 8; 535 symbolTable.addConstantUtf8(Constants.SIGNATURE); 536 } 537 if (sourceFileIndex != 0) { 538 ++attributesCount; 539 size += 8; 540 symbolTable.addConstantUtf8(Constants.SOURCE_FILE); 541 } 542 if (debugExtension != null) { 543 ++attributesCount; 544 size += 6 + debugExtension.length; 545 symbolTable.addConstantUtf8(Constants.SOURCE_DEBUG_EXTENSION); 546 } 547 if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) { 548 ++attributesCount; 549 size += 6; 550 symbolTable.addConstantUtf8(Constants.DEPRECATED); 551 } 552 if (lastRuntimeVisibleAnnotation != null) { 553 ++attributesCount; 554 size += 555 lastRuntimeVisibleAnnotation.computeAnnotationsSize( 556 Constants.RUNTIME_VISIBLE_ANNOTATIONS); 557 } 558 if (lastRuntimeInvisibleAnnotation != null) { 559 ++attributesCount; 560 size += 561 lastRuntimeInvisibleAnnotation.computeAnnotationsSize( 562 Constants.RUNTIME_INVISIBLE_ANNOTATIONS); 563 } 564 if (lastRuntimeVisibleTypeAnnotation != null) { 565 ++attributesCount; 566 size += 567 lastRuntimeVisibleTypeAnnotation.computeAnnotationsSize( 568 Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS); 569 } 570 if (lastRuntimeInvisibleTypeAnnotation != null) { 571 ++attributesCount; 572 size += 573 lastRuntimeInvisibleTypeAnnotation.computeAnnotationsSize( 574 Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS); 575 } 576 if (symbolTable.computeBootstrapMethodsSize() > 0) { 577 ++attributesCount; 578 size += symbolTable.computeBootstrapMethodsSize(); 579 } 580 if (moduleWriter != null) { 581 attributesCount += moduleWriter.getAttributeCount(); 582 size += moduleWriter.computeAttributesSize(); 583 } 584 if (nestHostClassIndex != 0) { 585 ++attributesCount; 586 size += 8; 587 symbolTable.addConstantUtf8(Constants.NEST_HOST); 588 } 589 if (nestMemberClasses != null) { 590 ++attributesCount; 591 size += 8 + nestMemberClasses.length; 592 symbolTable.addConstantUtf8(Constants.NEST_MEMBERS); 593 } 594 if (permittedSubclasses != null) { 595 ++attributesCount; 596 size += 8 + permittedSubclasses.length; 597 symbolTable.addConstantUtf8(Constants.PERMITTED_SUBCLASSES); 598 } 599 int recordComponentCount = 0; 600 int recordSize = 0; 601 if ((accessFlags & Opcodes.ACC_RECORD) != 0 || firstRecordComponent != null) { 602 RecordComponentWriter recordComponentWriter = firstRecordComponent; 603 while (recordComponentWriter != null) { 604 ++recordComponentCount; 605 recordSize += recordComponentWriter.computeRecordComponentInfoSize(); 606 recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate; 607 } 608 ++attributesCount; 609 size += 8 + recordSize; 610 symbolTable.addConstantUtf8(Constants.RECORD); 611 } 612 if (firstAttribute != null) { 613 attributesCount += firstAttribute.getAttributeCount(); 614 size += firstAttribute.computeAttributesSize(symbolTable); 615 } 616 // IMPORTANT: this must be the last part of the ClassFile size computation, because the previous 617 // statements can add attribute names to the constant pool, thereby changing its size! 618 size += symbolTable.getConstantPoolLength(); 619 int constantPoolCount = symbolTable.getConstantPoolCount(); 620 if (constantPoolCount > 0xFFFF) { 621 throw new ClassTooLargeException(symbolTable.getClassName(), constantPoolCount); 622 } 623 624 // Second step: allocate a ByteVector of the correct size (in order to avoid any array copy in 625 // dynamic resizes) and fill it with the ClassFile content. 626 ByteVector result = new ByteVector(size); 627 result.putInt(0xCAFEBABE).putInt(version); 628 symbolTable.putConstantPool(result); 629 int mask = (version & 0xFFFF) < Opcodes.V1_5 ? Opcodes.ACC_SYNTHETIC : 0; 630 result.putShort(accessFlags & ~mask).putShort(thisClass).putShort(superClass); 631 result.putShort(interfaceCount); 632 for (int i = 0; i < interfaceCount; ++i) { 633 result.putShort(interfaces[i]); 634 } 635 result.putShort(fieldsCount); 636 fieldWriter = firstField; 637 while (fieldWriter != null) { 638 fieldWriter.putFieldInfo(result); 639 fieldWriter = (FieldWriter) fieldWriter.fv; 640 } 641 result.putShort(methodsCount); 642 boolean hasFrames = false; 643 boolean hasAsmInstructions = false; 644 methodWriter = firstMethod; 645 while (methodWriter != null) { 646 hasFrames |= methodWriter.hasFrames(); 647 hasAsmInstructions |= methodWriter.hasAsmInstructions(); 648 methodWriter.putMethodInfo(result); 649 methodWriter = (MethodWriter) methodWriter.mv; 650 } 651 // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS. 652 result.putShort(attributesCount); 653 if (innerClasses != null) { 654 result 655 .putShort(symbolTable.addConstantUtf8(Constants.INNER_CLASSES)) 656 .putInt(innerClasses.length + 2) 657 .putShort(numberOfInnerClasses) 658 .putByteArray(innerClasses.data, 0, innerClasses.length); 659 } 660 if (enclosingClassIndex != 0) { 661 result 662 .putShort(symbolTable.addConstantUtf8(Constants.ENCLOSING_METHOD)) 663 .putInt(4) 664 .putShort(enclosingClassIndex) 665 .putShort(enclosingMethodIndex); 666 } 667 if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && (version & 0xFFFF) < Opcodes.V1_5) { 668 result.putShort(symbolTable.addConstantUtf8(Constants.SYNTHETIC)).putInt(0); 669 } 670 if (signatureIndex != 0) { 671 result 672 .putShort(symbolTable.addConstantUtf8(Constants.SIGNATURE)) 673 .putInt(2) 674 .putShort(signatureIndex); 675 } 676 if (sourceFileIndex != 0) { 677 result 678 .putShort(symbolTable.addConstantUtf8(Constants.SOURCE_FILE)) 679 .putInt(2) 680 .putShort(sourceFileIndex); 681 } 682 if (debugExtension != null) { 683 int length = debugExtension.length; 684 result 685 .putShort(symbolTable.addConstantUtf8(Constants.SOURCE_DEBUG_EXTENSION)) 686 .putInt(length) 687 .putByteArray(debugExtension.data, 0, length); 688 } 689 if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) { 690 result.putShort(symbolTable.addConstantUtf8(Constants.DEPRECATED)).putInt(0); 691 } 692 AnnotationWriter.putAnnotations( 693 symbolTable, 694 lastRuntimeVisibleAnnotation, 695 lastRuntimeInvisibleAnnotation, 696 lastRuntimeVisibleTypeAnnotation, 697 lastRuntimeInvisibleTypeAnnotation, 698 result); 699 symbolTable.putBootstrapMethods(result); 700 if (moduleWriter != null) { 701 moduleWriter.putAttributes(result); 702 } 703 if (nestHostClassIndex != 0) { 704 result 705 .putShort(symbolTable.addConstantUtf8(Constants.NEST_HOST)) 706 .putInt(2) 707 .putShort(nestHostClassIndex); 708 } 709 if (nestMemberClasses != null) { 710 result 711 .putShort(symbolTable.addConstantUtf8(Constants.NEST_MEMBERS)) 712 .putInt(nestMemberClasses.length + 2) 713 .putShort(numberOfNestMemberClasses) 714 .putByteArray(nestMemberClasses.data, 0, nestMemberClasses.length); 715 } 716 if (permittedSubclasses != null) { 717 result 718 .putShort(symbolTable.addConstantUtf8(Constants.PERMITTED_SUBCLASSES)) 719 .putInt(permittedSubclasses.length + 2) 720 .putShort(numberOfPermittedSubclasses) 721 .putByteArray(permittedSubclasses.data, 0, permittedSubclasses.length); 722 } 723 if ((accessFlags & Opcodes.ACC_RECORD) != 0 || firstRecordComponent != null) { 724 result 725 .putShort(symbolTable.addConstantUtf8(Constants.RECORD)) 726 .putInt(recordSize + 2) 727 .putShort(recordComponentCount); 728 RecordComponentWriter recordComponentWriter = firstRecordComponent; 729 while (recordComponentWriter != null) { 730 recordComponentWriter.putRecordComponentInfo(result); 731 recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate; 732 } 733 } 734 if (firstAttribute != null) { 735 firstAttribute.putAttributes(symbolTable, result); 736 } 737 738 // Third step: replace the ASM specific instructions, if any. 739 if (hasAsmInstructions) { 740 return replaceAsmInstructions(result.data, hasFrames); 741 } else { 742 return result.data; 743 } 744 } 745 746 /** 747 * Returns the equivalent of the given class file, with the ASM specific instructions replaced 748 * with standard ones. This is done with a ClassReader -> ClassWriter round trip. 749 * 750 * @param classFile a class file containing ASM specific instructions, generated by this 751 * ClassWriter. 752 * @param hasFrames whether there is at least one stack map frames in 'classFile'. 753 * @return an equivalent of 'classFile', with the ASM specific instructions replaced with standard 754 * ones. 755 */ 756 private byte[] replaceAsmInstructions(final byte[] classFile, final boolean hasFrames) { 757 final Attribute[] attributes = getAttributePrototypes(); 758 firstField = null; 759 lastField = null; 760 firstMethod = null; 761 lastMethod = null; 762 lastRuntimeVisibleAnnotation = null; 763 lastRuntimeInvisibleAnnotation = null; 764 lastRuntimeVisibleTypeAnnotation = null; 765 lastRuntimeInvisibleTypeAnnotation = null; 766 moduleWriter = null; 767 nestHostClassIndex = 0; 768 numberOfNestMemberClasses = 0; 769 nestMemberClasses = null; 770 numberOfPermittedSubclasses = 0; 771 permittedSubclasses = null; 772 firstRecordComponent = null; 773 lastRecordComponent = null; 774 firstAttribute = null; 775 compute = hasFrames ? MethodWriter.COMPUTE_INSERTED_FRAMES : MethodWriter.COMPUTE_NOTHING; 776 new ClassReader(classFile, 0, /* checkClassVersion = */ false) 777 .accept( 778 this, 779 attributes, 780 (hasFrames ? ClassReader.EXPAND_FRAMES : 0) | ClassReader.EXPAND_ASM_INSNS); 781 return toByteArray(); 782 } 783 784 /** 785 * Returns the prototypes of the attributes used by this class, its fields and its methods. 786 * 787 * @return the prototypes of the attributes used by this class, its fields and its methods. 788 */ 789 private Attribute[] getAttributePrototypes() { 790 Attribute.Set attributePrototypes = new Attribute.Set(); 791 attributePrototypes.addAttributes(firstAttribute); 792 FieldWriter fieldWriter = firstField; 793 while (fieldWriter != null) { 794 fieldWriter.collectAttributePrototypes(attributePrototypes); 795 fieldWriter = (FieldWriter) fieldWriter.fv; 796 } 797 MethodWriter methodWriter = firstMethod; 798 while (methodWriter != null) { 799 methodWriter.collectAttributePrototypes(attributePrototypes); 800 methodWriter = (MethodWriter) methodWriter.mv; 801 } 802 RecordComponentWriter recordComponentWriter = firstRecordComponent; 803 while (recordComponentWriter != null) { 804 recordComponentWriter.collectAttributePrototypes(attributePrototypes); 805 recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate; 806 } 807 return attributePrototypes.toArray(); 808 } 809 810 // ----------------------------------------------------------------------------------------------- 811 // Utility methods: constant pool management for Attribute sub classes 812 // ----------------------------------------------------------------------------------------------- 813 814 /** 815 * Adds a number or string constant to the constant pool of the class being build. Does nothing if 816 * the constant pool already contains a similar item. <i>This method is intended for {@link 817 * Attribute} sub classes, and is normally not needed by class generators or adapters.</i> 818 * 819 * @param value the value of the constant to be added to the constant pool. This parameter must be 820 * an {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double} or a {@link String}. 821 * @return the index of a new or already existing constant item with the given value. 822 */ 823 public int newConst(final Object value) { 824 return symbolTable.addConstant(value).index; 825 } 826 827 /** 828 * Adds an UTF8 string to the constant pool of the class being build. Does nothing if the constant 829 * pool already contains a similar item. <i>This method is intended for {@link Attribute} sub 830 * classes, and is normally not needed by class generators or adapters.</i> 831 * 832 * @param value the String value. 833 * @return the index of a new or already existing UTF8 item. 834 */ 835 // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility). 836 public int newUTF8(final String value) { 837 return symbolTable.addConstantUtf8(value); 838 } 839 840 /** 841 * Adds a class reference to the constant pool of the class being build. Does nothing if the 842 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 843 * sub classes, and is normally not needed by class generators or adapters.</i> 844 * 845 * @param value the internal name of the class (see {@link Type#getInternalName()}). 846 * @return the index of a new or already existing class reference item. 847 */ 848 public int newClass(final String value) { 849 return symbolTable.addConstantClass(value).index; 850 } 851 852 /** 853 * Adds a method type reference to the constant pool of the class being build. Does nothing if the 854 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 855 * sub classes, and is normally not needed by class generators or adapters.</i> 856 * 857 * @param methodDescriptor method descriptor of the method type. 858 * @return the index of a new or already existing method type reference item. 859 */ 860 public int newMethodType(final String methodDescriptor) { 861 return symbolTable.addConstantMethodType(methodDescriptor).index; 862 } 863 864 /** 865 * Adds a module reference to the constant pool of the class being build. Does nothing if the 866 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 867 * sub classes, and is normally not needed by class generators or adapters.</i> 868 * 869 * @param moduleName name of the module. 870 * @return the index of a new or already existing module reference item. 871 */ 872 public int newModule(final String moduleName) { 873 return symbolTable.addConstantModule(moduleName).index; 874 } 875 876 /** 877 * Adds a package reference to the constant pool of the class being build. Does nothing if the 878 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 879 * sub classes, and is normally not needed by class generators or adapters.</i> 880 * 881 * @param packageName name of the package in its internal form. 882 * @return the index of a new or already existing module reference item. 883 */ 884 public int newPackage(final String packageName) { 885 return symbolTable.addConstantPackage(packageName).index; 886 } 887 888 /** 889 * Adds a handle to the constant pool of the class being build. Does nothing if the constant pool 890 * already contains a similar item. <i>This method is intended for {@link Attribute} sub classes, 891 * and is normally not needed by class generators or adapters.</i> 892 * 893 * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, {@link 894 * Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, {@link 895 * Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL}, 896 * {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}. 897 * @param owner the internal name of the field or method owner class (see {@link 898 * Type#getInternalName()}). 899 * @param name the name of the field or method. 900 * @param descriptor the descriptor of the field or method. 901 * @return the index of a new or already existing method type reference item. 902 * @deprecated this method is superseded by {@link #newHandle(int, String, String, String, 903 * boolean)}. 904 */ 905 @Deprecated 906 public int newHandle( 907 final int tag, final String owner, final String name, final String descriptor) { 908 return newHandle(tag, owner, name, descriptor, tag == Opcodes.H_INVOKEINTERFACE); 909 } 910 911 /** 912 * Adds a handle to the constant pool of the class being build. Does nothing if the constant pool 913 * already contains a similar item. <i>This method is intended for {@link Attribute} sub classes, 914 * and is normally not needed by class generators or adapters.</i> 915 * 916 * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, {@link 917 * Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, {@link 918 * Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL}, 919 * {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}. 920 * @param owner the internal name of the field or method owner class (see {@link 921 * Type#getInternalName()}). 922 * @param name the name of the field or method. 923 * @param descriptor the descriptor of the field or method. 924 * @param isInterface true if the owner is an interface. 925 * @return the index of a new or already existing method type reference item. 926 */ 927 public int newHandle( 928 final int tag, 929 final String owner, 930 final String name, 931 final String descriptor, 932 final boolean isInterface) { 933 return symbolTable.addConstantMethodHandle(tag, owner, name, descriptor, isInterface).index; 934 } 935 936 /** 937 * Adds a dynamic constant reference to the constant pool of the class being build. Does nothing 938 * if the constant pool already contains a similar item. <i>This method is intended for {@link 939 * Attribute} sub classes, and is normally not needed by class generators or adapters.</i> 940 * 941 * @param name name of the invoked method. 942 * @param descriptor field descriptor of the constant type. 943 * @param bootstrapMethodHandle the bootstrap method. 944 * @param bootstrapMethodArguments the bootstrap method constant arguments. 945 * @return the index of a new or already existing dynamic constant reference item. 946 */ 947 public int newConstantDynamic( 948 final String name, 949 final String descriptor, 950 final Handle bootstrapMethodHandle, 951 final Object... bootstrapMethodArguments) { 952 return symbolTable.addConstantDynamic( 953 name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments) 954 .index; 955 } 956 957 /** 958 * Adds an invokedynamic reference to the constant pool of the class being build. Does nothing if 959 * the constant pool already contains a similar item. <i>This method is intended for {@link 960 * Attribute} sub classes, and is normally not needed by class generators or adapters.</i> 961 * 962 * @param name name of the invoked method. 963 * @param descriptor descriptor of the invoke method. 964 * @param bootstrapMethodHandle the bootstrap method. 965 * @param bootstrapMethodArguments the bootstrap method constant arguments. 966 * @return the index of a new or already existing invokedynamic reference item. 967 */ 968 public int newInvokeDynamic( 969 final String name, 970 final String descriptor, 971 final Handle bootstrapMethodHandle, 972 final Object... bootstrapMethodArguments) { 973 return symbolTable.addConstantInvokeDynamic( 974 name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments) 975 .index; 976 } 977 978 /** 979 * Adds a field reference to the constant pool of the class being build. Does nothing if the 980 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 981 * sub classes, and is normally not needed by class generators or adapters.</i> 982 * 983 * @param owner the internal name of the field's owner class (see {@link Type#getInternalName()}). 984 * @param name the field's name. 985 * @param descriptor the field's descriptor. 986 * @return the index of a new or already existing field reference item. 987 */ 988 public int newField(final String owner, final String name, final String descriptor) { 989 return symbolTable.addConstantFieldref(owner, name, descriptor).index; 990 } 991 992 /** 993 * Adds a method reference to the constant pool of the class being build. Does nothing if the 994 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 995 * sub classes, and is normally not needed by class generators or adapters.</i> 996 * 997 * @param owner the internal name of the method's owner class (see {@link 998 * Type#getInternalName()}). 999 * @param name the method's name. 1000 * @param descriptor the method's descriptor. 1001 * @param isInterface {@literal true} if {@code owner} is an interface. 1002 * @return the index of a new or already existing method reference item. 1003 */ 1004 public int newMethod( 1005 final String owner, final String name, final String descriptor, final boolean isInterface) { 1006 return symbolTable.addConstantMethodref(owner, name, descriptor, isInterface).index; 1007 } 1008 1009 /** 1010 * Adds a name and type to the constant pool of the class being build. Does nothing if the 1011 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 1012 * sub classes, and is normally not needed by class generators or adapters.</i> 1013 * 1014 * @param name a name. 1015 * @param descriptor a type descriptor. 1016 * @return the index of a new or already existing name and type item. 1017 */ 1018 public int newNameType(final String name, final String descriptor) { 1019 return symbolTable.addConstantNameAndType(name, descriptor); 1020 } 1021 1022 // ----------------------------------------------------------------------------------------------- 1023 // Default method to compute common super classes when computing stack map frames 1024 // ----------------------------------------------------------------------------------------------- 1025 1026 /** 1027 * Returns the common super type of the two given types. The default implementation of this method 1028 * <i>loads</i> the two given classes and uses the java.lang.Class methods to find the common 1029 * super class. It can be overridden to compute this common super type in other ways, in 1030 * particular without actually loading any class, or to take into account the class that is 1031 * currently being generated by this ClassWriter, which can of course not be loaded since it is 1032 * under construction. 1033 * 1034 * @param type1 the internal name of a class (see {@link Type#getInternalName()}). 1035 * @param type2 the internal name of another class (see {@link Type#getInternalName()}). 1036 * @return the internal name of the common super class of the two given classes (see {@link 1037 * Type#getInternalName()}). 1038 */ 1039 protected String getCommonSuperClass(final String type1, final String type2) { 1040 ClassLoader classLoader = getClassLoader(); 1041 Class<?> class1; 1042 try { 1043 class1 = Class.forName(type1.replace('/', '.'), false, classLoader); 1044 } catch (ClassNotFoundException e) { 1045 throw new TypeNotPresentException(type1, e); 1046 } 1047 Class<?> class2; 1048 try { 1049 class2 = Class.forName(type2.replace('/', '.'), false, classLoader); 1050 } catch (ClassNotFoundException e) { 1051 throw new TypeNotPresentException(type2, e); 1052 } 1053 if (class1.isAssignableFrom(class2)) { 1054 return type1; 1055 } 1056 if (class2.isAssignableFrom(class1)) { 1057 return type2; 1058 } 1059 if (class1.isInterface() || class2.isInterface()) { 1060 return "java/lang/Object"; 1061 } else { 1062 do { 1063 class1 = class1.getSuperclass(); 1064 } while (!class1.isAssignableFrom(class2)); 1065 return class1.getName().replace('.', '/'); 1066 } 1067 } 1068 1069 /** 1070 * Returns the {@link ClassLoader} to be used by the default implementation of {@link 1071 * #getCommonSuperClass(String, String)}, that of this {@link ClassWriter}'s runtime type by 1072 * default. 1073 * 1074 * @return ClassLoader 1075 */ 1076 protected ClassLoader getClassLoader() { 1077 return getClass().getClassLoader(); 1078 } 1079 } 1080