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_MAX_STACK_AND_LOCAL_FROM_FRAMES}, {@link 221 * MethodWriter#COMPUTE_INSERTED_FRAMES}, or {@link MethodWriter#COMPUTE_ALL_FRAMES}. 222 */ 223 private int compute; 224 225 // ----------------------------------------------------------------------------------------------- 226 // Constructor 227 // ----------------------------------------------------------------------------------------------- 228 229 /** 230 * Constructs a new {@link ClassWriter} object. 231 * 232 * @param flags option flags that can be used to modify the default behavior of this class. Must 233 * be zero or more of {@link #COMPUTE_MAXS} and {@link #COMPUTE_FRAMES}. 234 */ ClassWriter(final int flags)235 public ClassWriter(final int flags) { 236 this(null, flags); 237 } 238 239 /** 240 * Constructs a new {@link ClassWriter} object and enables optimizations for "mostly add" bytecode 241 * transformations. These optimizations are the following: 242 * 243 * <ul> 244 * <li>The constant pool and bootstrap methods from the original class are copied as is in the 245 * new class, which saves time. New constant pool entries and new bootstrap methods will be 246 * added at the end if necessary, but unused constant pool entries or bootstrap methods 247 * <i>won't be removed</i>. 248 * <li>Methods that are not transformed are copied as is in the new class, directly from the 249 * original class bytecode (i.e. without emitting visit events for all the method 250 * instructions), which saves a <i>lot</i> of time. Untransformed methods are detected by 251 * the fact that the {@link ClassReader} receives {@link MethodVisitor} objects that come 252 * from a {@link ClassWriter} (and not from any other {@link ClassVisitor} instance). 253 * </ul> 254 * 255 * @param classReader the {@link ClassReader} used to read the original class. It will be used to 256 * copy the entire constant pool and bootstrap methods from the original class and also to 257 * copy other fragments of original bytecode where applicable. 258 * @param flags option flags that can be used to modify the default behavior of this class. Must 259 * be zero or more of {@link #COMPUTE_MAXS} and {@link #COMPUTE_FRAMES}. <i>These option flags 260 * do not affect methods that are copied as is in the new class. This means that neither the 261 * maximum stack size nor the stack frames will be computed for these methods</i>. 262 */ ClassWriter(final ClassReader classReader, final int flags)263 public ClassWriter(final ClassReader classReader, final int flags) { 264 super(/* latest api = */ Opcodes.ASM9); 265 this.flags = flags; 266 symbolTable = classReader == null ? new SymbolTable(this) : new SymbolTable(this, classReader); 267 if ((flags & COMPUTE_FRAMES) != 0) { 268 compute = MethodWriter.COMPUTE_ALL_FRAMES; 269 } else if ((flags & COMPUTE_MAXS) != 0) { 270 compute = MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL; 271 } else { 272 compute = MethodWriter.COMPUTE_NOTHING; 273 } 274 } 275 276 // ----------------------------------------------------------------------------------------------- 277 // Accessors 278 // ----------------------------------------------------------------------------------------------- 279 280 /** 281 * Returns true if all the given flags were passed to the constructor. 282 * 283 * @param flags some option flags. Must be zero or more of {@link #COMPUTE_MAXS} and {@link 284 * #COMPUTE_FRAMES}. 285 * @return true if all the given flags, or more, were passed to the constructor. 286 */ hasFlags(final int flags)287 public boolean hasFlags(final int flags) { 288 return (this.flags & flags) == flags; 289 } 290 291 // ----------------------------------------------------------------------------------------------- 292 // Implementation of the ClassVisitor abstract class 293 // ----------------------------------------------------------------------------------------------- 294 295 @Override visit( final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces)296 public final void visit( 297 final int version, 298 final int access, 299 final String name, 300 final String signature, 301 final String superName, 302 final String[] interfaces) { 303 this.version = version; 304 this.accessFlags = access; 305 this.thisClass = symbolTable.setMajorVersionAndClassName(version & 0xFFFF, name); 306 if (signature != null) { 307 this.signatureIndex = symbolTable.addConstantUtf8(signature); 308 } 309 this.superClass = superName == null ? 0 : symbolTable.addConstantClass(superName).index; 310 if (interfaces != null && interfaces.length > 0) { 311 interfaceCount = interfaces.length; 312 this.interfaces = new int[interfaceCount]; 313 for (int i = 0; i < interfaceCount; ++i) { 314 this.interfaces[i] = symbolTable.addConstantClass(interfaces[i]).index; 315 } 316 } 317 if (compute == MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL && (version & 0xFFFF) >= Opcodes.V1_7) { 318 compute = MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES; 319 } 320 } 321 322 @Override visitSource(final String file, final String debug)323 public final void visitSource(final String file, final String debug) { 324 if (file != null) { 325 sourceFileIndex = symbolTable.addConstantUtf8(file); 326 } 327 if (debug != null) { 328 debugExtension = new ByteVector().encodeUtf8(debug, 0, Integer.MAX_VALUE); 329 } 330 } 331 332 @Override visitModule( final String name, final int access, final String version)333 public final ModuleVisitor visitModule( 334 final String name, final int access, final String version) { 335 return moduleWriter = 336 new ModuleWriter( 337 symbolTable, 338 symbolTable.addConstantModule(name).index, 339 access, 340 version == null ? 0 : symbolTable.addConstantUtf8(version)); 341 } 342 343 @Override visitNestHost(final String nestHost)344 public final void visitNestHost(final String nestHost) { 345 nestHostClassIndex = symbolTable.addConstantClass(nestHost).index; 346 } 347 348 @Override visitOuterClass( final String owner, final String name, final String descriptor)349 public final void visitOuterClass( 350 final String owner, final String name, final String descriptor) { 351 enclosingClassIndex = symbolTable.addConstantClass(owner).index; 352 if (name != null && descriptor != null) { 353 enclosingMethodIndex = symbolTable.addConstantNameAndType(name, descriptor); 354 } 355 } 356 357 @Override visitAnnotation(final String descriptor, final boolean visible)358 public final AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { 359 if (visible) { 360 return lastRuntimeVisibleAnnotation = 361 AnnotationWriter.create(symbolTable, descriptor, lastRuntimeVisibleAnnotation); 362 } else { 363 return lastRuntimeInvisibleAnnotation = 364 AnnotationWriter.create(symbolTable, descriptor, lastRuntimeInvisibleAnnotation); 365 } 366 } 367 368 @Override visitTypeAnnotation( final int typeRef, final TypePath typePath, final String descriptor, final boolean visible)369 public final AnnotationVisitor visitTypeAnnotation( 370 final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { 371 if (visible) { 372 return lastRuntimeVisibleTypeAnnotation = 373 AnnotationWriter.create( 374 symbolTable, typeRef, typePath, descriptor, lastRuntimeVisibleTypeAnnotation); 375 } else { 376 return lastRuntimeInvisibleTypeAnnotation = 377 AnnotationWriter.create( 378 symbolTable, typeRef, typePath, descriptor, lastRuntimeInvisibleTypeAnnotation); 379 } 380 } 381 382 @Override visitAttribute(final Attribute attribute)383 public final void visitAttribute(final Attribute attribute) { 384 // Store the attributes in the <i>reverse</i> order of their visit by this method. 385 attribute.nextAttribute = firstAttribute; 386 firstAttribute = attribute; 387 } 388 389 @Override visitNestMember(final String nestMember)390 public final void visitNestMember(final String nestMember) { 391 if (nestMemberClasses == null) { 392 nestMemberClasses = new ByteVector(); 393 } 394 ++numberOfNestMemberClasses; 395 nestMemberClasses.putShort(symbolTable.addConstantClass(nestMember).index); 396 } 397 398 @Override visitPermittedSubclass(final String permittedSubclass)399 public final void visitPermittedSubclass(final String permittedSubclass) { 400 if (permittedSubclasses == null) { 401 permittedSubclasses = new ByteVector(); 402 } 403 ++numberOfPermittedSubclasses; 404 permittedSubclasses.putShort(symbolTable.addConstantClass(permittedSubclass).index); 405 } 406 407 @Override visitInnerClass( final String name, final String outerName, final String innerName, final int access)408 public final void visitInnerClass( 409 final String name, final String outerName, final String innerName, final int access) { 410 if (innerClasses == null) { 411 innerClasses = new ByteVector(); 412 } 413 // Section 4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the constant_pool table 414 // which represents a class or interface C that is not a package member must have exactly one 415 // corresponding entry in the classes array". To avoid duplicates we keep track in the info 416 // field of the Symbol of each CONSTANT_Class_info entry C whether an inner class entry has 417 // already been added for C. If so, we store the index of this inner class entry (plus one) in 418 // the info field. This trick allows duplicate detection in O(1) time. 419 Symbol nameSymbol = symbolTable.addConstantClass(name); 420 if (nameSymbol.info == 0) { 421 ++numberOfInnerClasses; 422 innerClasses.putShort(nameSymbol.index); 423 innerClasses.putShort(outerName == null ? 0 : symbolTable.addConstantClass(outerName).index); 424 innerClasses.putShort(innerName == null ? 0 : symbolTable.addConstantUtf8(innerName)); 425 innerClasses.putShort(access); 426 nameSymbol.info = numberOfInnerClasses; 427 } 428 // Else, compare the inner classes entry nameSymbol.info - 1 with the arguments of this method 429 // and throw an exception if there is a difference? 430 } 431 432 @Override visitRecordComponent( final String name, final String descriptor, final String signature)433 public final RecordComponentVisitor visitRecordComponent( 434 final String name, final String descriptor, final String signature) { 435 RecordComponentWriter recordComponentWriter = 436 new RecordComponentWriter(symbolTable, name, descriptor, signature); 437 if (firstRecordComponent == null) { 438 firstRecordComponent = recordComponentWriter; 439 } else { 440 lastRecordComponent.delegate = recordComponentWriter; 441 } 442 return lastRecordComponent = recordComponentWriter; 443 } 444 445 @Override visitField( final int access, final String name, final String descriptor, final String signature, final Object value)446 public final FieldVisitor visitField( 447 final int access, 448 final String name, 449 final String descriptor, 450 final String signature, 451 final Object value) { 452 FieldWriter fieldWriter = 453 new FieldWriter(symbolTable, access, name, descriptor, signature, value); 454 if (firstField == null) { 455 firstField = fieldWriter; 456 } else { 457 lastField.fv = fieldWriter; 458 } 459 return lastField = fieldWriter; 460 } 461 462 @Override visitMethod( final int access, final String name, final String descriptor, final String signature, final String[] exceptions)463 public final MethodVisitor visitMethod( 464 final int access, 465 final String name, 466 final String descriptor, 467 final String signature, 468 final String[] exceptions) { 469 MethodWriter methodWriter = 470 new MethodWriter(symbolTable, access, name, descriptor, signature, exceptions, compute); 471 if (firstMethod == null) { 472 firstMethod = methodWriter; 473 } else { 474 lastMethod.mv = methodWriter; 475 } 476 return lastMethod = methodWriter; 477 } 478 479 @Override visitEnd()480 public final void visitEnd() { 481 // Nothing to do. 482 } 483 484 // ----------------------------------------------------------------------------------------------- 485 // Other public methods 486 // ----------------------------------------------------------------------------------------------- 487 488 /** 489 * Returns the content of the class file that was built by this ClassWriter. 490 * 491 * @return the binary content of the JVMS ClassFile structure that was built by this ClassWriter. 492 * @throws ClassTooLargeException if the constant pool of the class is too large. 493 * @throws MethodTooLargeException if the Code attribute of a method is too large. 494 */ toByteArray()495 public byte[] toByteArray() { 496 // First step: compute the size in bytes of the ClassFile structure. 497 // The magic field uses 4 bytes, 10 mandatory fields (minor_version, major_version, 498 // constant_pool_count, access_flags, this_class, super_class, interfaces_count, fields_count, 499 // methods_count and attributes_count) use 2 bytes each, and each interface uses 2 bytes too. 500 int size = 24 + 2 * interfaceCount; 501 int fieldsCount = 0; 502 FieldWriter fieldWriter = firstField; 503 while (fieldWriter != null) { 504 ++fieldsCount; 505 size += fieldWriter.computeFieldInfoSize(); 506 fieldWriter = (FieldWriter) fieldWriter.fv; 507 } 508 int methodsCount = 0; 509 MethodWriter methodWriter = firstMethod; 510 while (methodWriter != null) { 511 ++methodsCount; 512 size += methodWriter.computeMethodInfoSize(); 513 methodWriter = (MethodWriter) methodWriter.mv; 514 } 515 516 // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS. 517 int attributesCount = 0; 518 if (innerClasses != null) { 519 ++attributesCount; 520 size += 8 + innerClasses.length; 521 symbolTable.addConstantUtf8(Constants.INNER_CLASSES); 522 } 523 if (enclosingClassIndex != 0) { 524 ++attributesCount; 525 size += 10; 526 symbolTable.addConstantUtf8(Constants.ENCLOSING_METHOD); 527 } 528 if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && (version & 0xFFFF) < Opcodes.V1_5) { 529 ++attributesCount; 530 size += 6; 531 symbolTable.addConstantUtf8(Constants.SYNTHETIC); 532 } 533 if (signatureIndex != 0) { 534 ++attributesCount; 535 size += 8; 536 symbolTable.addConstantUtf8(Constants.SIGNATURE); 537 } 538 if (sourceFileIndex != 0) { 539 ++attributesCount; 540 size += 8; 541 symbolTable.addConstantUtf8(Constants.SOURCE_FILE); 542 } 543 if (debugExtension != null) { 544 ++attributesCount; 545 size += 6 + debugExtension.length; 546 symbolTable.addConstantUtf8(Constants.SOURCE_DEBUG_EXTENSION); 547 } 548 if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) { 549 ++attributesCount; 550 size += 6; 551 symbolTable.addConstantUtf8(Constants.DEPRECATED); 552 } 553 if (lastRuntimeVisibleAnnotation != null) { 554 ++attributesCount; 555 size += 556 lastRuntimeVisibleAnnotation.computeAnnotationsSize( 557 Constants.RUNTIME_VISIBLE_ANNOTATIONS); 558 } 559 if (lastRuntimeInvisibleAnnotation != null) { 560 ++attributesCount; 561 size += 562 lastRuntimeInvisibleAnnotation.computeAnnotationsSize( 563 Constants.RUNTIME_INVISIBLE_ANNOTATIONS); 564 } 565 if (lastRuntimeVisibleTypeAnnotation != null) { 566 ++attributesCount; 567 size += 568 lastRuntimeVisibleTypeAnnotation.computeAnnotationsSize( 569 Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS); 570 } 571 if (lastRuntimeInvisibleTypeAnnotation != null) { 572 ++attributesCount; 573 size += 574 lastRuntimeInvisibleTypeAnnotation.computeAnnotationsSize( 575 Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS); 576 } 577 if (symbolTable.computeBootstrapMethodsSize() > 0) { 578 ++attributesCount; 579 size += symbolTable.computeBootstrapMethodsSize(); 580 } 581 if (moduleWriter != null) { 582 attributesCount += moduleWriter.getAttributeCount(); 583 size += moduleWriter.computeAttributesSize(); 584 } 585 if (nestHostClassIndex != 0) { 586 ++attributesCount; 587 size += 8; 588 symbolTable.addConstantUtf8(Constants.NEST_HOST); 589 } 590 if (nestMemberClasses != null) { 591 ++attributesCount; 592 size += 8 + nestMemberClasses.length; 593 symbolTable.addConstantUtf8(Constants.NEST_MEMBERS); 594 } 595 if (permittedSubclasses != null) { 596 ++attributesCount; 597 size += 8 + permittedSubclasses.length; 598 symbolTable.addConstantUtf8(Constants.PERMITTED_SUBCLASSES); 599 } 600 int recordComponentCount = 0; 601 int recordSize = 0; 602 if ((accessFlags & Opcodes.ACC_RECORD) != 0 || firstRecordComponent != null) { 603 RecordComponentWriter recordComponentWriter = firstRecordComponent; 604 while (recordComponentWriter != null) { 605 ++recordComponentCount; 606 recordSize += recordComponentWriter.computeRecordComponentInfoSize(); 607 recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate; 608 } 609 ++attributesCount; 610 size += 8 + recordSize; 611 symbolTable.addConstantUtf8(Constants.RECORD); 612 } 613 if (firstAttribute != null) { 614 attributesCount += firstAttribute.getAttributeCount(); 615 size += firstAttribute.computeAttributesSize(symbolTable); 616 } 617 // IMPORTANT: this must be the last part of the ClassFile size computation, because the previous 618 // statements can add attribute names to the constant pool, thereby changing its size! 619 size += symbolTable.getConstantPoolLength(); 620 int constantPoolCount = symbolTable.getConstantPoolCount(); 621 if (constantPoolCount > 0xFFFF) { 622 throw new ClassTooLargeException(symbolTable.getClassName(), constantPoolCount); 623 } 624 625 // Second step: allocate a ByteVector of the correct size (in order to avoid any array copy in 626 // dynamic resizes) and fill it with the ClassFile content. 627 ByteVector result = new ByteVector(size); 628 result.putInt(0xCAFEBABE).putInt(version); 629 symbolTable.putConstantPool(result); 630 int mask = (version & 0xFFFF) < Opcodes.V1_5 ? Opcodes.ACC_SYNTHETIC : 0; 631 result.putShort(accessFlags & ~mask).putShort(thisClass).putShort(superClass); 632 result.putShort(interfaceCount); 633 for (int i = 0; i < interfaceCount; ++i) { 634 result.putShort(interfaces[i]); 635 } 636 result.putShort(fieldsCount); 637 fieldWriter = firstField; 638 while (fieldWriter != null) { 639 fieldWriter.putFieldInfo(result); 640 fieldWriter = (FieldWriter) fieldWriter.fv; 641 } 642 result.putShort(methodsCount); 643 boolean hasFrames = false; 644 boolean hasAsmInstructions = false; 645 methodWriter = firstMethod; 646 while (methodWriter != null) { 647 hasFrames |= methodWriter.hasFrames(); 648 hasAsmInstructions |= methodWriter.hasAsmInstructions(); 649 methodWriter.putMethodInfo(result); 650 methodWriter = (MethodWriter) methodWriter.mv; 651 } 652 // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS. 653 result.putShort(attributesCount); 654 if (innerClasses != null) { 655 result 656 .putShort(symbolTable.addConstantUtf8(Constants.INNER_CLASSES)) 657 .putInt(innerClasses.length + 2) 658 .putShort(numberOfInnerClasses) 659 .putByteArray(innerClasses.data, 0, innerClasses.length); 660 } 661 if (enclosingClassIndex != 0) { 662 result 663 .putShort(symbolTable.addConstantUtf8(Constants.ENCLOSING_METHOD)) 664 .putInt(4) 665 .putShort(enclosingClassIndex) 666 .putShort(enclosingMethodIndex); 667 } 668 if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && (version & 0xFFFF) < Opcodes.V1_5) { 669 result.putShort(symbolTable.addConstantUtf8(Constants.SYNTHETIC)).putInt(0); 670 } 671 if (signatureIndex != 0) { 672 result 673 .putShort(symbolTable.addConstantUtf8(Constants.SIGNATURE)) 674 .putInt(2) 675 .putShort(signatureIndex); 676 } 677 if (sourceFileIndex != 0) { 678 result 679 .putShort(symbolTable.addConstantUtf8(Constants.SOURCE_FILE)) 680 .putInt(2) 681 .putShort(sourceFileIndex); 682 } 683 if (debugExtension != null) { 684 int length = debugExtension.length; 685 result 686 .putShort(symbolTable.addConstantUtf8(Constants.SOURCE_DEBUG_EXTENSION)) 687 .putInt(length) 688 .putByteArray(debugExtension.data, 0, length); 689 } 690 if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) { 691 result.putShort(symbolTable.addConstantUtf8(Constants.DEPRECATED)).putInt(0); 692 } 693 AnnotationWriter.putAnnotations( 694 symbolTable, 695 lastRuntimeVisibleAnnotation, 696 lastRuntimeInvisibleAnnotation, 697 lastRuntimeVisibleTypeAnnotation, 698 lastRuntimeInvisibleTypeAnnotation, 699 result); 700 symbolTable.putBootstrapMethods(result); 701 if (moduleWriter != null) { 702 moduleWriter.putAttributes(result); 703 } 704 if (nestHostClassIndex != 0) { 705 result 706 .putShort(symbolTable.addConstantUtf8(Constants.NEST_HOST)) 707 .putInt(2) 708 .putShort(nestHostClassIndex); 709 } 710 if (nestMemberClasses != null) { 711 result 712 .putShort(symbolTable.addConstantUtf8(Constants.NEST_MEMBERS)) 713 .putInt(nestMemberClasses.length + 2) 714 .putShort(numberOfNestMemberClasses) 715 .putByteArray(nestMemberClasses.data, 0, nestMemberClasses.length); 716 } 717 if (permittedSubclasses != null) { 718 result 719 .putShort(symbolTable.addConstantUtf8(Constants.PERMITTED_SUBCLASSES)) 720 .putInt(permittedSubclasses.length + 2) 721 .putShort(numberOfPermittedSubclasses) 722 .putByteArray(permittedSubclasses.data, 0, permittedSubclasses.length); 723 } 724 if ((accessFlags & Opcodes.ACC_RECORD) != 0 || firstRecordComponent != null) { 725 result 726 .putShort(symbolTable.addConstantUtf8(Constants.RECORD)) 727 .putInt(recordSize + 2) 728 .putShort(recordComponentCount); 729 RecordComponentWriter recordComponentWriter = firstRecordComponent; 730 while (recordComponentWriter != null) { 731 recordComponentWriter.putRecordComponentInfo(result); 732 recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate; 733 } 734 } 735 if (firstAttribute != null) { 736 firstAttribute.putAttributes(symbolTable, result); 737 } 738 739 // Third step: replace the ASM specific instructions, if any. 740 if (hasAsmInstructions) { 741 return replaceAsmInstructions(result.data, hasFrames); 742 } else { 743 return result.data; 744 } 745 } 746 747 /** 748 * Returns the equivalent of the given class file, with the ASM specific instructions replaced 749 * with standard ones. This is done with a ClassReader -> ClassWriter round trip. 750 * 751 * @param classFile a class file containing ASM specific instructions, generated by this 752 * ClassWriter. 753 * @param hasFrames whether there is at least one stack map frames in 'classFile'. 754 * @return an equivalent of 'classFile', with the ASM specific instructions replaced with standard 755 * ones. 756 */ 757 private byte[] replaceAsmInstructions(final byte[] classFile, final boolean hasFrames) { 758 final Attribute[] attributes = getAttributePrototypes(); 759 firstField = null; 760 lastField = null; 761 firstMethod = null; 762 lastMethod = null; 763 lastRuntimeVisibleAnnotation = null; 764 lastRuntimeInvisibleAnnotation = null; 765 lastRuntimeVisibleTypeAnnotation = null; 766 lastRuntimeInvisibleTypeAnnotation = null; 767 moduleWriter = null; 768 nestHostClassIndex = 0; 769 numberOfNestMemberClasses = 0; 770 nestMemberClasses = null; 771 numberOfPermittedSubclasses = 0; 772 permittedSubclasses = null; 773 firstRecordComponent = null; 774 lastRecordComponent = null; 775 firstAttribute = null; 776 compute = hasFrames ? MethodWriter.COMPUTE_INSERTED_FRAMES : MethodWriter.COMPUTE_NOTHING; 777 new ClassReader(classFile, 0, /* checkClassVersion = */ false) 778 .accept( 779 this, 780 attributes, 781 (hasFrames ? ClassReader.EXPAND_FRAMES : 0) | ClassReader.EXPAND_ASM_INSNS); 782 return toByteArray(); 783 } 784 785 /** 786 * Returns the prototypes of the attributes used by this class, its fields and its methods. 787 * 788 * @return the prototypes of the attributes used by this class, its fields and its methods. 789 */ 790 private Attribute[] getAttributePrototypes() { 791 Attribute.Set attributePrototypes = new Attribute.Set(); 792 attributePrototypes.addAttributes(firstAttribute); 793 FieldWriter fieldWriter = firstField; 794 while (fieldWriter != null) { 795 fieldWriter.collectAttributePrototypes(attributePrototypes); 796 fieldWriter = (FieldWriter) fieldWriter.fv; 797 } 798 MethodWriter methodWriter = firstMethod; 799 while (methodWriter != null) { 800 methodWriter.collectAttributePrototypes(attributePrototypes); 801 methodWriter = (MethodWriter) methodWriter.mv; 802 } 803 RecordComponentWriter recordComponentWriter = firstRecordComponent; 804 while (recordComponentWriter != null) { 805 recordComponentWriter.collectAttributePrototypes(attributePrototypes); 806 recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate; 807 } 808 return attributePrototypes.toArray(); 809 } 810 811 // ----------------------------------------------------------------------------------------------- 812 // Utility methods: constant pool management for Attribute sub classes 813 // ----------------------------------------------------------------------------------------------- 814 815 /** 816 * Adds a number or string constant to the constant pool of the class being build. Does nothing if 817 * the constant pool already contains a similar item. <i>This method is intended for {@link 818 * Attribute} sub classes, and is normally not needed by class generators or adapters.</i> 819 * 820 * @param value the value of the constant to be added to the constant pool. This parameter must be 821 * an {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double} or a {@link String}. 822 * @return the index of a new or already existing constant item with the given value. 823 */ 824 public int newConst(final Object value) { 825 return symbolTable.addConstant(value).index; 826 } 827 828 /** 829 * Adds an UTF8 string to the constant pool of the class being build. Does nothing if the constant 830 * pool already contains a similar item. <i>This method is intended for {@link Attribute} sub 831 * classes, and is normally not needed by class generators or adapters.</i> 832 * 833 * @param value the String value. 834 * @return the index of a new or already existing UTF8 item. 835 */ 836 // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility). 837 public int newUTF8(final String value) { 838 return symbolTable.addConstantUtf8(value); 839 } 840 841 /** 842 * Adds a class reference to the constant pool of the class being build. Does nothing if the 843 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 844 * sub classes, and is normally not needed by class generators or adapters.</i> 845 * 846 * @param value the internal name of the class (see {@link Type#getInternalName()}). 847 * @return the index of a new or already existing class reference item. 848 */ 849 public int newClass(final String value) { 850 return symbolTable.addConstantClass(value).index; 851 } 852 853 /** 854 * Adds a method type reference to the constant pool of the class being build. Does nothing if the 855 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 856 * sub classes, and is normally not needed by class generators or adapters.</i> 857 * 858 * @param methodDescriptor method descriptor of the method type. 859 * @return the index of a new or already existing method type reference item. 860 */ 861 public int newMethodType(final String methodDescriptor) { 862 return symbolTable.addConstantMethodType(methodDescriptor).index; 863 } 864 865 /** 866 * Adds a module reference to the constant pool of the class being build. Does nothing if the 867 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 868 * sub classes, and is normally not needed by class generators or adapters.</i> 869 * 870 * @param moduleName name of the module. 871 * @return the index of a new or already existing module reference item. 872 */ 873 public int newModule(final String moduleName) { 874 return symbolTable.addConstantModule(moduleName).index; 875 } 876 877 /** 878 * Adds a package reference to the constant pool of the class being build. Does nothing if the 879 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 880 * sub classes, and is normally not needed by class generators or adapters.</i> 881 * 882 * @param packageName name of the package in its internal form. 883 * @return the index of a new or already existing module reference item. 884 */ 885 public int newPackage(final String packageName) { 886 return symbolTable.addConstantPackage(packageName).index; 887 } 888 889 /** 890 * Adds a handle to the constant pool of the class being build. Does nothing if the constant pool 891 * already contains a similar item. <i>This method is intended for {@link Attribute} sub classes, 892 * and is normally not needed by class generators or adapters.</i> 893 * 894 * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, {@link 895 * Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, {@link 896 * Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL}, 897 * {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}. 898 * @param owner the internal name of the field or method owner class (see {@link 899 * Type#getInternalName()}). 900 * @param name the name of the field or method. 901 * @param descriptor the descriptor of the field or method. 902 * @return the index of a new or already existing method type reference item. 903 * @deprecated this method is superseded by {@link #newHandle(int, String, String, String, 904 * boolean)}. 905 */ 906 @Deprecated 907 public int newHandle( 908 final int tag, final String owner, final String name, final String descriptor) { 909 return newHandle(tag, owner, name, descriptor, tag == Opcodes.H_INVOKEINTERFACE); 910 } 911 912 /** 913 * Adds a handle to the constant pool of the class being build. Does nothing if the constant pool 914 * already contains a similar item. <i>This method is intended for {@link Attribute} sub classes, 915 * and is normally not needed by class generators or adapters.</i> 916 * 917 * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, {@link 918 * Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, {@link 919 * Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL}, 920 * {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}. 921 * @param owner the internal name of the field or method owner class (see {@link 922 * Type#getInternalName()}). 923 * @param name the name of the field or method. 924 * @param descriptor the descriptor of the field or method. 925 * @param isInterface true if the owner is an interface. 926 * @return the index of a new or already existing method type reference item. 927 */ 928 public int newHandle( 929 final int tag, 930 final String owner, 931 final String name, 932 final String descriptor, 933 final boolean isInterface) { 934 return symbolTable.addConstantMethodHandle(tag, owner, name, descriptor, isInterface).index; 935 } 936 937 /** 938 * Adds a dynamic constant reference to the constant pool of the class being build. Does nothing 939 * if the constant pool already contains a similar item. <i>This method is intended for {@link 940 * Attribute} sub classes, and is normally not needed by class generators or adapters.</i> 941 * 942 * @param name name of the invoked method. 943 * @param descriptor field descriptor of the constant type. 944 * @param bootstrapMethodHandle the bootstrap method. 945 * @param bootstrapMethodArguments the bootstrap method constant arguments. 946 * @return the index of a new or already existing dynamic constant reference item. 947 */ 948 public int newConstantDynamic( 949 final String name, 950 final String descriptor, 951 final Handle bootstrapMethodHandle, 952 final Object... bootstrapMethodArguments) { 953 return symbolTable.addConstantDynamic( 954 name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments) 955 .index; 956 } 957 958 /** 959 * Adds an invokedynamic reference to the constant pool of the class being build. Does nothing if 960 * the constant pool already contains a similar item. <i>This method is intended for {@link 961 * Attribute} sub classes, and is normally not needed by class generators or adapters.</i> 962 * 963 * @param name name of the invoked method. 964 * @param descriptor descriptor of the invoke method. 965 * @param bootstrapMethodHandle the bootstrap method. 966 * @param bootstrapMethodArguments the bootstrap method constant arguments. 967 * @return the index of a new or already existing invokedynamic reference item. 968 */ 969 public int newInvokeDynamic( 970 final String name, 971 final String descriptor, 972 final Handle bootstrapMethodHandle, 973 final Object... bootstrapMethodArguments) { 974 return symbolTable.addConstantInvokeDynamic( 975 name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments) 976 .index; 977 } 978 979 /** 980 * Adds a field reference to the constant pool of the class being build. Does nothing if the 981 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 982 * sub classes, and is normally not needed by class generators or adapters.</i> 983 * 984 * @param owner the internal name of the field's owner class (see {@link Type#getInternalName()}). 985 * @param name the field's name. 986 * @param descriptor the field's descriptor. 987 * @return the index of a new or already existing field reference item. 988 */ 989 public int newField(final String owner, final String name, final String descriptor) { 990 return symbolTable.addConstantFieldref(owner, name, descriptor).index; 991 } 992 993 /** 994 * Adds a method reference to the constant pool of the class being build. Does nothing if the 995 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 996 * sub classes, and is normally not needed by class generators or adapters.</i> 997 * 998 * @param owner the internal name of the method's owner class (see {@link 999 * Type#getInternalName()}). 1000 * @param name the method's name. 1001 * @param descriptor the method's descriptor. 1002 * @param isInterface {@literal true} if {@code owner} is an interface. 1003 * @return the index of a new or already existing method reference item. 1004 */ 1005 public int newMethod( 1006 final String owner, final String name, final String descriptor, final boolean isInterface) { 1007 return symbolTable.addConstantMethodref(owner, name, descriptor, isInterface).index; 1008 } 1009 1010 /** 1011 * Adds a name and type to the constant pool of the class being build. Does nothing if the 1012 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 1013 * sub classes, and is normally not needed by class generators or adapters.</i> 1014 * 1015 * @param name a name. 1016 * @param descriptor a type descriptor. 1017 * @return the index of a new or already existing name and type item. 1018 */ 1019 public int newNameType(final String name, final String descriptor) { 1020 return symbolTable.addConstantNameAndType(name, descriptor); 1021 } 1022 1023 // ----------------------------------------------------------------------------------------------- 1024 // Default method to compute common super classes when computing stack map frames 1025 // ----------------------------------------------------------------------------------------------- 1026 1027 /** 1028 * Returns the common super type of the two given types. The default implementation of this method 1029 * <i>loads</i> the two given classes and uses the java.lang.Class methods to find the common 1030 * super class. It can be overridden to compute this common super type in other ways, in 1031 * particular without actually loading any class, or to take into account the class that is 1032 * currently being generated by this ClassWriter, which can of course not be loaded since it is 1033 * under construction. 1034 * 1035 * @param type1 the internal name of a class (see {@link Type#getInternalName()}). 1036 * @param type2 the internal name of another class (see {@link Type#getInternalName()}). 1037 * @return the internal name of the common super class of the two given classes (see {@link 1038 * Type#getInternalName()}). 1039 */ 1040 protected String getCommonSuperClass(final String type1, final String type2) { 1041 ClassLoader classLoader = getClassLoader(); 1042 Class<?> class1; 1043 try { 1044 class1 = Class.forName(type1.replace('/', '.'), false, classLoader); 1045 } catch (ClassNotFoundException e) { 1046 throw new TypeNotPresentException(type1, e); 1047 } 1048 Class<?> class2; 1049 try { 1050 class2 = Class.forName(type2.replace('/', '.'), false, classLoader); 1051 } catch (ClassNotFoundException e) { 1052 throw new TypeNotPresentException(type2, e); 1053 } 1054 if (class1.isAssignableFrom(class2)) { 1055 return type1; 1056 } 1057 if (class2.isAssignableFrom(class1)) { 1058 return type2; 1059 } 1060 if (class1.isInterface() || class2.isInterface()) { 1061 return "java/lang/Object"; 1062 } else { 1063 do { 1064 class1 = class1.getSuperclass(); 1065 } while (!class1.isAssignableFrom(class2)); 1066 return class1.getName().replace('.', '/'); 1067 } 1068 } 1069 1070 /** 1071 * Returns the {@link ClassLoader} to be used by the default implementation of {@link 1072 * #getCommonSuperClass(String, String)}, that of this {@link ClassWriter}'s runtime type by 1073 * default. 1074 * 1075 * @return ClassLoader 1076 */ 1077 protected ClassLoader getClassLoader() { 1078 return getClass().getClassLoader(); 1079 } 1080 } 1081