001// ASM: a very small and fast Java bytecode manipulation framework 002// Copyright (c) 2000-2011 INRIA, France Telecom 003// All rights reserved. 004// 005// Redistribution and use in source and binary forms, with or without 006// modification, are permitted provided that the following conditions 007// are met: 008// 1. Redistributions of source code must retain the above copyright 009// notice, this list of conditions and the following disclaimer. 010// 2. Redistributions in binary form must reproduce the above copyright 011// notice, this list of conditions and the following disclaimer in the 012// documentation and/or other materials provided with the distribution. 013// 3. Neither the name of the copyright holders nor the names of its 014// contributors may be used to endorse or promote products derived from 015// this software without specific prior written permission. 016// 017// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 018// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 019// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 020// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 021// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 022// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 023// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 024// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 025// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 026// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 027// THE POSSIBILITY OF SUCH DAMAGE. 028package io.ebean.enhance.asm; 029 030/** 031 * A {@link ClassVisitor} that generates a corresponding ClassFile structure, as defined in the Java 032 * Virtual Machine Specification (JVMS). It can be used alone, to generate a Java class "from 033 * scratch", or with one or more {@link ClassReader} and adapter {@link ClassVisitor} to generate a 034 * modified class from one or more existing Java classes. 035 * 036 * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html">JVMS 4</a> 037 * @author Eric Bruneton 038 */ 039public class ClassWriter extends ClassVisitor { 040 041 /** 042 * A flag to automatically compute the maximum stack size and the maximum number of local 043 * variables of methods. If this flag is set, then the arguments of the {@link 044 * MethodVisitor#visitMaxs} method of the {@link MethodVisitor} returned by the {@link 045 * #visitMethod} method will be ignored, and computed automatically from the signature and the 046 * bytecode of each method. 047 * 048 * <p><b>Note:</b> for classes whose version is {@link Opcodes#V1_7} of more, this option requires 049 * valid stack map frames. The maximum stack size is then computed from these frames, and from the 050 * bytecode instructions in between. If stack map frames are not present or must be recomputed, 051 * used {@link #COMPUTE_FRAMES} instead. 052 * 053 * @see #ClassWriter(int) 054 */ 055 public static final int COMPUTE_MAXS = 1; 056 057 /** 058 * A flag to automatically compute the stack map frames of methods from scratch. If this flag is 059 * set, then the calls to the {@link MethodVisitor#visitFrame} method are ignored, and the stack 060 * map frames are recomputed from the methods bytecode. The arguments of the {@link 061 * MethodVisitor#visitMaxs} method are also ignored and recomputed from the bytecode. In other 062 * words, {@link #COMPUTE_FRAMES} implies {@link #COMPUTE_MAXS}. 063 * 064 * @see #ClassWriter(int) 065 */ 066 public static final int COMPUTE_FRAMES = 2; 067 068 /** 069 * The flags passed to the constructor. Must be zero or more of {@link #COMPUTE_MAXS} and {@link 070 * #COMPUTE_FRAMES}. 071 */ 072 private final int flags; 073 074 // Note: fields are ordered as in the ClassFile structure, and those related to attributes are 075 // ordered as in Section 4.7 of the JVMS. 076 077 /** 078 * The minor_version and major_version fields of the JVMS ClassFile structure. minor_version is 079 * stored in the 16 most significant bits, and major_version in the 16 least significant bits. 080 */ 081 private int version; 082 083 /** The symbol table for this class (contains the constant_pool and the BootstrapMethods). */ 084 private final SymbolTable symbolTable; 085 086 /** 087 * The access_flags field of the JVMS ClassFile structure. This field can contain ASM specific 088 * access flags, such as {@link Opcodes#ACC_DEPRECATED} or {@link Opcodes#ACC_RECORD}, which are 089 * removed when generating the ClassFile structure. 090 */ 091 private int accessFlags; 092 093 /** The this_class field of the JVMS ClassFile structure. */ 094 private int thisClass; 095 096 /** The super_class field of the JVMS ClassFile structure. */ 097 private int superClass; 098 099 /** 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 */ 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 */ 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 setFlags(flags); 268 } 269 270 // ----------------------------------------------------------------------------------------------- 271 // Accessors 272 // ----------------------------------------------------------------------------------------------- 273 274 /** 275 * Returns true if all the given flags were passed to the constructor. 276 * 277 * @param flags some option flags. Must be zero or more of {@link #COMPUTE_MAXS} and {@link 278 * #COMPUTE_FRAMES}. 279 * @return true if all the given flags, or more, were passed to the constructor. 280 */ 281 public boolean hasFlags(final int flags) { 282 return (this.flags & flags) == flags; 283 } 284 285 // ----------------------------------------------------------------------------------------------- 286 // Implementation of the ClassVisitor abstract class 287 // ----------------------------------------------------------------------------------------------- 288 289 @Override 290 public final void visit( 291 final int version, 292 final int access, 293 final String name, 294 final String signature, 295 final String superName, 296 final String[] interfaces) { 297 this.version = version; 298 this.accessFlags = access; 299 this.thisClass = symbolTable.setMajorVersionAndClassName(version & 0xFFFF, name); 300 if (signature != null) { 301 this.signatureIndex = symbolTable.addConstantUtf8(signature); 302 } 303 this.superClass = superName == null ? 0 : symbolTable.addConstantClass(superName).index; 304 if (interfaces != null && interfaces.length > 0) { 305 interfaceCount = interfaces.length; 306 this.interfaces = new int[interfaceCount]; 307 for (int i = 0; i < interfaceCount; ++i) { 308 this.interfaces[i] = symbolTable.addConstantClass(interfaces[i]).index; 309 } 310 } 311 if (compute == MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL && (version & 0xFFFF) >= Opcodes.V1_7) { 312 compute = MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL_FROM_FRAMES; 313 } 314 } 315 316 @Override 317 public final void visitSource(final String file, final String debug) { 318 if (file != null) { 319 sourceFileIndex = symbolTable.addConstantUtf8(file); 320 } 321 if (debug != null) { 322 debugExtension = new ByteVector().encodeUtf8(debug, 0, Integer.MAX_VALUE); 323 } 324 } 325 326 @Override 327 public final ModuleVisitor visitModule( 328 final String name, final int access, final String version) { 329 return moduleWriter = 330 new ModuleWriter( 331 symbolTable, 332 symbolTable.addConstantModule(name).index, 333 access, 334 version == null ? 0 : symbolTable.addConstantUtf8(version)); 335 } 336 337 @Override 338 public final void visitNestHost(final String nestHost) { 339 nestHostClassIndex = symbolTable.addConstantClass(nestHost).index; 340 } 341 342 @Override 343 public final void visitOuterClass( 344 final String owner, final String name, final String descriptor) { 345 enclosingClassIndex = symbolTable.addConstantClass(owner).index; 346 if (name != null && descriptor != null) { 347 enclosingMethodIndex = symbolTable.addConstantNameAndType(name, descriptor); 348 } 349 } 350 351 @Override 352 public final AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) { 353 if (visible) { 354 return lastRuntimeVisibleAnnotation = 355 AnnotationWriter.create(symbolTable, descriptor, lastRuntimeVisibleAnnotation); 356 } else { 357 return lastRuntimeInvisibleAnnotation = 358 AnnotationWriter.create(symbolTable, descriptor, lastRuntimeInvisibleAnnotation); 359 } 360 } 361 362 @Override 363 public final AnnotationVisitor visitTypeAnnotation( 364 final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) { 365 if (visible) { 366 return lastRuntimeVisibleTypeAnnotation = 367 AnnotationWriter.create( 368 symbolTable, typeRef, typePath, descriptor, lastRuntimeVisibleTypeAnnotation); 369 } else { 370 return lastRuntimeInvisibleTypeAnnotation = 371 AnnotationWriter.create( 372 symbolTable, typeRef, typePath, descriptor, lastRuntimeInvisibleTypeAnnotation); 373 } 374 } 375 376 @Override 377 public final void visitAttribute(final Attribute attribute) { 378 // Store the attributes in the <i>reverse</i> order of their visit by this method. 379 attribute.nextAttribute = firstAttribute; 380 firstAttribute = attribute; 381 } 382 383 @Override 384 public final void visitNestMember(final String nestMember) { 385 if (nestMemberClasses == null) { 386 nestMemberClasses = new ByteVector(); 387 } 388 ++numberOfNestMemberClasses; 389 nestMemberClasses.putShort(symbolTable.addConstantClass(nestMember).index); 390 } 391 392 @Override 393 public final void visitPermittedSubclass(final String permittedSubclass) { 394 if (permittedSubclasses == null) { 395 permittedSubclasses = new ByteVector(); 396 } 397 ++numberOfPermittedSubclasses; 398 permittedSubclasses.putShort(symbolTable.addConstantClass(permittedSubclass).index); 399 } 400 401 @Override 402 public final void visitInnerClass( 403 final String name, final String outerName, final String innerName, final int access) { 404 if (innerClasses == null) { 405 innerClasses = new ByteVector(); 406 } 407 // Section 4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the constant_pool table 408 // which represents a class or interface C that is not a package member must have exactly one 409 // corresponding entry in the classes array". To avoid duplicates we keep track in the info 410 // field of the Symbol of each CONSTANT_Class_info entry C whether an inner class entry has 411 // already been added for C. If so, we store the index of this inner class entry (plus one) in 412 // the info field. This trick allows duplicate detection in O(1) time. 413 Symbol nameSymbol = symbolTable.addConstantClass(name); 414 if (nameSymbol.info == 0) { 415 ++numberOfInnerClasses; 416 innerClasses.putShort(nameSymbol.index); 417 innerClasses.putShort(outerName == null ? 0 : symbolTable.addConstantClass(outerName).index); 418 innerClasses.putShort(innerName == null ? 0 : symbolTable.addConstantUtf8(innerName)); 419 innerClasses.putShort(access); 420 nameSymbol.info = numberOfInnerClasses; 421 } 422 // Else, compare the inner classes entry nameSymbol.info - 1 with the arguments of this method 423 // and throw an exception if there is a difference? 424 } 425 426 @Override 427 public final RecordComponentVisitor visitRecordComponent( 428 final String name, final String descriptor, final String signature) { 429 RecordComponentWriter recordComponentWriter = 430 new RecordComponentWriter(symbolTable, name, descriptor, signature); 431 if (firstRecordComponent == null) { 432 firstRecordComponent = recordComponentWriter; 433 } else { 434 lastRecordComponent.delegate = recordComponentWriter; 435 } 436 return lastRecordComponent = recordComponentWriter; 437 } 438 439 @Override 440 public final FieldVisitor visitField( 441 final int access, 442 final String name, 443 final String descriptor, 444 final String signature, 445 final Object value) { 446 FieldWriter fieldWriter = 447 new FieldWriter(symbolTable, access, name, descriptor, signature, value); 448 if (firstField == null) { 449 firstField = fieldWriter; 450 } else { 451 lastField.fv = fieldWriter; 452 } 453 return lastField = fieldWriter; 454 } 455 456 @Override 457 public final MethodVisitor visitMethod( 458 final int access, 459 final String name, 460 final String descriptor, 461 final String signature, 462 final String[] exceptions) { 463 MethodWriter methodWriter = 464 new MethodWriter(symbolTable, access, name, descriptor, signature, exceptions, compute); 465 if (firstMethod == null) { 466 firstMethod = methodWriter; 467 } else { 468 lastMethod.mv = methodWriter; 469 } 470 return lastMethod = methodWriter; 471 } 472 473 @Override 474 public final void visitEnd() { 475 // Nothing to do. 476 } 477 478 // ----------------------------------------------------------------------------------------------- 479 // Other public methods 480 // ----------------------------------------------------------------------------------------------- 481 482 /** 483 * Returns the content of the class file that was built by this ClassWriter. 484 * 485 * @return the binary content of the JVMS ClassFile structure that was built by this ClassWriter. 486 * @throws ClassTooLargeException if the constant pool of the class is too large. 487 * @throws MethodTooLargeException if the Code attribute of a method is too large. 488 */ 489 public byte[] toByteArray() { 490 // First step: compute the size in bytes of the ClassFile structure. 491 // The magic field uses 4 bytes, 10 mandatory fields (minor_version, major_version, 492 // constant_pool_count, access_flags, this_class, super_class, interfaces_count, fields_count, 493 // methods_count and attributes_count) use 2 bytes each, and each interface uses 2 bytes too. 494 int size = 24 + 2 * interfaceCount; 495 int fieldsCount = 0; 496 FieldWriter fieldWriter = firstField; 497 while (fieldWriter != null) { 498 ++fieldsCount; 499 size += fieldWriter.computeFieldInfoSize(); 500 fieldWriter = (FieldWriter) fieldWriter.fv; 501 } 502 int methodsCount = 0; 503 MethodWriter methodWriter = firstMethod; 504 while (methodWriter != null) { 505 ++methodsCount; 506 size += methodWriter.computeMethodInfoSize(); 507 methodWriter = (MethodWriter) methodWriter.mv; 508 } 509 510 // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS. 511 int attributesCount = 0; 512 if (innerClasses != null) { 513 ++attributesCount; 514 size += 8 + innerClasses.length; 515 symbolTable.addConstantUtf8(Constants.INNER_CLASSES); 516 } 517 if (enclosingClassIndex != 0) { 518 ++attributesCount; 519 size += 10; 520 symbolTable.addConstantUtf8(Constants.ENCLOSING_METHOD); 521 } 522 if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && (version & 0xFFFF) < Opcodes.V1_5) { 523 ++attributesCount; 524 size += 6; 525 symbolTable.addConstantUtf8(Constants.SYNTHETIC); 526 } 527 if (signatureIndex != 0) { 528 ++attributesCount; 529 size += 8; 530 symbolTable.addConstantUtf8(Constants.SIGNATURE); 531 } 532 if (sourceFileIndex != 0) { 533 ++attributesCount; 534 size += 8; 535 symbolTable.addConstantUtf8(Constants.SOURCE_FILE); 536 } 537 if (debugExtension != null) { 538 ++attributesCount; 539 size += 6 + debugExtension.length; 540 symbolTable.addConstantUtf8(Constants.SOURCE_DEBUG_EXTENSION); 541 } 542 if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) { 543 ++attributesCount; 544 size += 6; 545 symbolTable.addConstantUtf8(Constants.DEPRECATED); 546 } 547 if (lastRuntimeVisibleAnnotation != null) { 548 ++attributesCount; 549 size += 550 lastRuntimeVisibleAnnotation.computeAnnotationsSize( 551 Constants.RUNTIME_VISIBLE_ANNOTATIONS); 552 } 553 if (lastRuntimeInvisibleAnnotation != null) { 554 ++attributesCount; 555 size += 556 lastRuntimeInvisibleAnnotation.computeAnnotationsSize( 557 Constants.RUNTIME_INVISIBLE_ANNOTATIONS); 558 } 559 if (lastRuntimeVisibleTypeAnnotation != null) { 560 ++attributesCount; 561 size += 562 lastRuntimeVisibleTypeAnnotation.computeAnnotationsSize( 563 Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS); 564 } 565 if (lastRuntimeInvisibleTypeAnnotation != null) { 566 ++attributesCount; 567 size += 568 lastRuntimeInvisibleTypeAnnotation.computeAnnotationsSize( 569 Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS); 570 } 571 if (symbolTable.computeBootstrapMethodsSize() > 0) { 572 ++attributesCount; 573 size += symbolTable.computeBootstrapMethodsSize(); 574 } 575 if (moduleWriter != null) { 576 attributesCount += moduleWriter.getAttributeCount(); 577 size += moduleWriter.computeAttributesSize(); 578 } 579 if (nestHostClassIndex != 0) { 580 ++attributesCount; 581 size += 8; 582 symbolTable.addConstantUtf8(Constants.NEST_HOST); 583 } 584 if (nestMemberClasses != null) { 585 ++attributesCount; 586 size += 8 + nestMemberClasses.length; 587 symbolTable.addConstantUtf8(Constants.NEST_MEMBERS); 588 } 589 if (permittedSubclasses != null) { 590 ++attributesCount; 591 size += 8 + permittedSubclasses.length; 592 symbolTable.addConstantUtf8(Constants.PERMITTED_SUBCLASSES); 593 } 594 int recordComponentCount = 0; 595 int recordSize = 0; 596 if ((accessFlags & Opcodes.ACC_RECORD) != 0 || firstRecordComponent != null) { 597 RecordComponentWriter recordComponentWriter = firstRecordComponent; 598 while (recordComponentWriter != null) { 599 ++recordComponentCount; 600 recordSize += recordComponentWriter.computeRecordComponentInfoSize(); 601 recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate; 602 } 603 ++attributesCount; 604 size += 8 + recordSize; 605 symbolTable.addConstantUtf8(Constants.RECORD); 606 } 607 if (firstAttribute != null) { 608 attributesCount += firstAttribute.getAttributeCount(); 609 size += firstAttribute.computeAttributesSize(symbolTable); 610 } 611 // IMPORTANT: this must be the last part of the ClassFile size computation, because the previous 612 // statements can add attribute names to the constant pool, thereby changing its size! 613 size += symbolTable.getConstantPoolLength(); 614 int constantPoolCount = symbolTable.getConstantPoolCount(); 615 if (constantPoolCount > 0xFFFF) { 616 throw new ClassTooLargeException(symbolTable.getClassName(), constantPoolCount); 617 } 618 619 // Second step: allocate a ByteVector of the correct size (in order to avoid any array copy in 620 // dynamic resizes) and fill it with the ClassFile content. 621 ByteVector result = new ByteVector(size); 622 result.putInt(0xCAFEBABE).putInt(version); 623 symbolTable.putConstantPool(result); 624 int mask = (version & 0xFFFF) < Opcodes.V1_5 ? Opcodes.ACC_SYNTHETIC : 0; 625 result.putShort(accessFlags & ~mask).putShort(thisClass).putShort(superClass); 626 result.putShort(interfaceCount); 627 for (int i = 0; i < interfaceCount; ++i) { 628 result.putShort(interfaces[i]); 629 } 630 result.putShort(fieldsCount); 631 fieldWriter = firstField; 632 while (fieldWriter != null) { 633 fieldWriter.putFieldInfo(result); 634 fieldWriter = (FieldWriter) fieldWriter.fv; 635 } 636 result.putShort(methodsCount); 637 boolean hasFrames = false; 638 boolean hasAsmInstructions = false; 639 methodWriter = firstMethod; 640 while (methodWriter != null) { 641 hasFrames |= methodWriter.hasFrames(); 642 hasAsmInstructions |= methodWriter.hasAsmInstructions(); 643 methodWriter.putMethodInfo(result); 644 methodWriter = (MethodWriter) methodWriter.mv; 645 } 646 // For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS. 647 result.putShort(attributesCount); 648 if (innerClasses != null) { 649 result 650 .putShort(symbolTable.addConstantUtf8(Constants.INNER_CLASSES)) 651 .putInt(innerClasses.length + 2) 652 .putShort(numberOfInnerClasses) 653 .putByteArray(innerClasses.data, 0, innerClasses.length); 654 } 655 if (enclosingClassIndex != 0) { 656 result 657 .putShort(symbolTable.addConstantUtf8(Constants.ENCLOSING_METHOD)) 658 .putInt(4) 659 .putShort(enclosingClassIndex) 660 .putShort(enclosingMethodIndex); 661 } 662 if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && (version & 0xFFFF) < Opcodes.V1_5) { 663 result.putShort(symbolTable.addConstantUtf8(Constants.SYNTHETIC)).putInt(0); 664 } 665 if (signatureIndex != 0) { 666 result 667 .putShort(symbolTable.addConstantUtf8(Constants.SIGNATURE)) 668 .putInt(2) 669 .putShort(signatureIndex); 670 } 671 if (sourceFileIndex != 0) { 672 result 673 .putShort(symbolTable.addConstantUtf8(Constants.SOURCE_FILE)) 674 .putInt(2) 675 .putShort(sourceFileIndex); 676 } 677 if (debugExtension != null) { 678 int length = debugExtension.length; 679 result 680 .putShort(symbolTable.addConstantUtf8(Constants.SOURCE_DEBUG_EXTENSION)) 681 .putInt(length) 682 .putByteArray(debugExtension.data, 0, length); 683 } 684 if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) { 685 result.putShort(symbolTable.addConstantUtf8(Constants.DEPRECATED)).putInt(0); 686 } 687 AnnotationWriter.putAnnotations( 688 symbolTable, 689 lastRuntimeVisibleAnnotation, 690 lastRuntimeInvisibleAnnotation, 691 lastRuntimeVisibleTypeAnnotation, 692 lastRuntimeInvisibleTypeAnnotation, 693 result); 694 symbolTable.putBootstrapMethods(result); 695 if (moduleWriter != null) { 696 moduleWriter.putAttributes(result); 697 } 698 if (nestHostClassIndex != 0) { 699 result 700 .putShort(symbolTable.addConstantUtf8(Constants.NEST_HOST)) 701 .putInt(2) 702 .putShort(nestHostClassIndex); 703 } 704 if (nestMemberClasses != null) { 705 result 706 .putShort(symbolTable.addConstantUtf8(Constants.NEST_MEMBERS)) 707 .putInt(nestMemberClasses.length + 2) 708 .putShort(numberOfNestMemberClasses) 709 .putByteArray(nestMemberClasses.data, 0, nestMemberClasses.length); 710 } 711 if (permittedSubclasses != null) { 712 result 713 .putShort(symbolTable.addConstantUtf8(Constants.PERMITTED_SUBCLASSES)) 714 .putInt(permittedSubclasses.length + 2) 715 .putShort(numberOfPermittedSubclasses) 716 .putByteArray(permittedSubclasses.data, 0, permittedSubclasses.length); 717 } 718 if ((accessFlags & Opcodes.ACC_RECORD) != 0 || firstRecordComponent != null) { 719 result 720 .putShort(symbolTable.addConstantUtf8(Constants.RECORD)) 721 .putInt(recordSize + 2) 722 .putShort(recordComponentCount); 723 RecordComponentWriter recordComponentWriter = firstRecordComponent; 724 while (recordComponentWriter != null) { 725 recordComponentWriter.putRecordComponentInfo(result); 726 recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate; 727 } 728 } 729 if (firstAttribute != null) { 730 firstAttribute.putAttributes(symbolTable, result); 731 } 732 733 // Third step: replace the ASM specific instructions, if any. 734 if (hasAsmInstructions) { 735 return replaceAsmInstructions(result.data, hasFrames); 736 } else { 737 return result.data; 738 } 739 } 740 741 /** 742 * Returns the equivalent of the given class file, with the ASM specific instructions replaced 743 * with standard ones. This is done with a ClassReader -> ClassWriter round trip. 744 * 745 * @param classFile a class file containing ASM specific instructions, generated by this 746 * ClassWriter. 747 * @param hasFrames whether there is at least one stack map frames in 'classFile'. 748 * @return an equivalent of 'classFile', with the ASM specific instructions replaced with standard 749 * ones. 750 */ 751 private byte[] replaceAsmInstructions(final byte[] classFile, final boolean hasFrames) { 752 final Attribute[] attributes = getAttributePrototypes(); 753 firstField = null; 754 lastField = null; 755 firstMethod = null; 756 lastMethod = null; 757 lastRuntimeVisibleAnnotation = null; 758 lastRuntimeInvisibleAnnotation = null; 759 lastRuntimeVisibleTypeAnnotation = null; 760 lastRuntimeInvisibleTypeAnnotation = null; 761 moduleWriter = null; 762 nestHostClassIndex = 0; 763 numberOfNestMemberClasses = 0; 764 nestMemberClasses = null; 765 numberOfPermittedSubclasses = 0; 766 permittedSubclasses = null; 767 firstRecordComponent = null; 768 lastRecordComponent = null; 769 firstAttribute = null; 770 compute = hasFrames ? MethodWriter.COMPUTE_INSERTED_FRAMES : MethodWriter.COMPUTE_NOTHING; 771 new ClassReader(classFile, 0, /* checkClassVersion= */ false) 772 .accept( 773 this, 774 attributes, 775 (hasFrames ? ClassReader.EXPAND_FRAMES : 0) | ClassReader.EXPAND_ASM_INSNS); 776 return toByteArray(); 777 } 778 779 /** 780 * Returns the prototypes of the attributes used by this class, its fields and its methods. 781 * 782 * @return the prototypes of the attributes used by this class, its fields and its methods. 783 */ 784 private Attribute[] getAttributePrototypes() { 785 Attribute.Set attributePrototypes = new Attribute.Set(); 786 attributePrototypes.addAttributes(firstAttribute); 787 FieldWriter fieldWriter = firstField; 788 while (fieldWriter != null) { 789 fieldWriter.collectAttributePrototypes(attributePrototypes); 790 fieldWriter = (FieldWriter) fieldWriter.fv; 791 } 792 MethodWriter methodWriter = firstMethod; 793 while (methodWriter != null) { 794 methodWriter.collectAttributePrototypes(attributePrototypes); 795 methodWriter = (MethodWriter) methodWriter.mv; 796 } 797 RecordComponentWriter recordComponentWriter = firstRecordComponent; 798 while (recordComponentWriter != null) { 799 recordComponentWriter.collectAttributePrototypes(attributePrototypes); 800 recordComponentWriter = (RecordComponentWriter) recordComponentWriter.delegate; 801 } 802 return attributePrototypes.toArray(); 803 } 804 805 // ----------------------------------------------------------------------------------------------- 806 // Utility methods: constant pool management for Attribute sub classes 807 // ----------------------------------------------------------------------------------------------- 808 809 /** 810 * Adds a number or string constant to the constant pool of the class being build. Does nothing if 811 * the constant pool already contains a similar item. <i>This method is intended for {@link 812 * Attribute} sub classes, and is normally not needed by class generators or adapters.</i> 813 * 814 * @param value the value of the constant to be added to the constant pool. This parameter must be 815 * an {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double} or a {@link String}. 816 * @return the index of a new or already existing constant item with the given value. 817 */ 818 public int newConst(final Object value) { 819 return symbolTable.addConstant(value).index; 820 } 821 822 /** 823 * Adds an UTF8 string to the constant pool of the class being build. Does nothing if the constant 824 * pool already contains a similar item. <i>This method is intended for {@link Attribute} sub 825 * classes, and is normally not needed by class generators or adapters.</i> 826 * 827 * @param value the String value. 828 * @return the index of a new or already existing UTF8 item. 829 */ 830 // DontCheck(AbbreviationAsWordInName): can't be renamed (for backward binary compatibility). 831 public int newUTF8(final String value) { 832 return symbolTable.addConstantUtf8(value); 833 } 834 835 /** 836 * Adds a class reference to the constant pool of the class being build. Does nothing if the 837 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 838 * sub classes, and is normally not needed by class generators or adapters.</i> 839 * 840 * @param value the internal name of the class (see {@link Type#getInternalName()}). 841 * @return the index of a new or already existing class reference item. 842 */ 843 public int newClass(final String value) { 844 return symbolTable.addConstantClass(value).index; 845 } 846 847 /** 848 * Adds a method type reference to the constant pool of the class being build. Does nothing if the 849 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 850 * sub classes, and is normally not needed by class generators or adapters.</i> 851 * 852 * @param methodDescriptor method descriptor of the method type. 853 * @return the index of a new or already existing method type reference item. 854 */ 855 public int newMethodType(final String methodDescriptor) { 856 return symbolTable.addConstantMethodType(methodDescriptor).index; 857 } 858 859 /** 860 * Adds a module reference to the constant pool of the class being build. Does nothing if the 861 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 862 * sub classes, and is normally not needed by class generators or adapters.</i> 863 * 864 * @param moduleName name of the module. 865 * @return the index of a new or already existing module reference item. 866 */ 867 public int newModule(final String moduleName) { 868 return symbolTable.addConstantModule(moduleName).index; 869 } 870 871 /** 872 * Adds a package reference to the constant pool of the class being build. Does nothing if the 873 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 874 * sub classes, and is normally not needed by class generators or adapters.</i> 875 * 876 * @param packageName name of the package in its internal form. 877 * @return the index of a new or already existing module reference item. 878 */ 879 public int newPackage(final String packageName) { 880 return symbolTable.addConstantPackage(packageName).index; 881 } 882 883 /** 884 * Adds a handle to the constant pool of the class being build. Does nothing if the constant pool 885 * already contains a similar item. <i>This method is intended for {@link Attribute} sub classes, 886 * and is normally not needed by class generators or adapters.</i> 887 * 888 * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, {@link 889 * Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, {@link 890 * Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL}, 891 * {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}. 892 * @param owner the internal name of the field or method owner class (see {@link 893 * Type#getInternalName()}). 894 * @param name the name of the field or method. 895 * @param descriptor the descriptor of the field or method. 896 * @return the index of a new or already existing method type reference item. 897 * @deprecated this method is superseded by {@link #newHandle(int, String, String, String, 898 * boolean)}. 899 */ 900 @Deprecated 901 public int newHandle( 902 final int tag, final String owner, final String name, final String descriptor) { 903 return newHandle(tag, owner, name, descriptor, tag == Opcodes.H_INVOKEINTERFACE); 904 } 905 906 /** 907 * Adds a handle to the constant pool of the class being build. Does nothing if the constant pool 908 * already contains a similar item. <i>This method is intended for {@link Attribute} sub classes, 909 * and is normally not needed by class generators or adapters.</i> 910 * 911 * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD}, {@link 912 * Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, {@link 913 * Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL}, 914 * {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}. 915 * @param owner the internal name of the field or method owner class (see {@link 916 * Type#getInternalName()}). 917 * @param name the name of the field or method. 918 * @param descriptor the descriptor of the field or method. 919 * @param isInterface true if the owner is an interface. 920 * @return the index of a new or already existing method type reference item. 921 */ 922 public int newHandle( 923 final int tag, 924 final String owner, 925 final String name, 926 final String descriptor, 927 final boolean isInterface) { 928 return symbolTable.addConstantMethodHandle(tag, owner, name, descriptor, isInterface).index; 929 } 930 931 /** 932 * Adds a dynamic constant reference to the constant pool of the class being build. Does nothing 933 * if the constant pool already contains a similar item. <i>This method is intended for {@link 934 * Attribute} sub classes, and is normally not needed by class generators or adapters.</i> 935 * 936 * @param name name of the invoked method. 937 * @param descriptor field descriptor of the constant type. 938 * @param bootstrapMethodHandle the bootstrap method. 939 * @param bootstrapMethodArguments the bootstrap method constant arguments. 940 * @return the index of a new or already existing dynamic constant reference item. 941 */ 942 public int newConstantDynamic( 943 final String name, 944 final String descriptor, 945 final Handle bootstrapMethodHandle, 946 final Object... bootstrapMethodArguments) { 947 return symbolTable.addConstantDynamic( 948 name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments) 949 .index; 950 } 951 952 /** 953 * Adds an invokedynamic reference to the constant pool of the class being build. Does nothing if 954 * the constant pool already contains a similar item. <i>This method is intended for {@link 955 * Attribute} sub classes, and is normally not needed by class generators or adapters.</i> 956 * 957 * @param name name of the invoked method. 958 * @param descriptor descriptor of the invoke method. 959 * @param bootstrapMethodHandle the bootstrap method. 960 * @param bootstrapMethodArguments the bootstrap method constant arguments. 961 * @return the index of a new or already existing invokedynamic reference item. 962 */ 963 public int newInvokeDynamic( 964 final String name, 965 final String descriptor, 966 final Handle bootstrapMethodHandle, 967 final Object... bootstrapMethodArguments) { 968 return symbolTable.addConstantInvokeDynamic( 969 name, descriptor, bootstrapMethodHandle, bootstrapMethodArguments) 970 .index; 971 } 972 973 /** 974 * Adds a field reference to the constant pool of the class being build. Does nothing if the 975 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 976 * sub classes, and is normally not needed by class generators or adapters.</i> 977 * 978 * @param owner the internal name of the field's owner class (see {@link Type#getInternalName()}). 979 * @param name the field's name. 980 * @param descriptor the field's descriptor. 981 * @return the index of a new or already existing field reference item. 982 */ 983 public int newField(final String owner, final String name, final String descriptor) { 984 return symbolTable.addConstantFieldref(owner, name, descriptor).index; 985 } 986 987 /** 988 * Adds a method reference to the constant pool of the class being build. Does nothing if the 989 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 990 * sub classes, and is normally not needed by class generators or adapters.</i> 991 * 992 * @param owner the internal name of the method's owner class (see {@link 993 * Type#getInternalName()}). 994 * @param name the method's name. 995 * @param descriptor the method's descriptor. 996 * @param isInterface {@literal true} if {@code owner} is an interface. 997 * @return the index of a new or already existing method reference item. 998 */ 999 public int newMethod( 1000 final String owner, final String name, final String descriptor, final boolean isInterface) { 1001 return symbolTable.addConstantMethodref(owner, name, descriptor, isInterface).index; 1002 } 1003 1004 /** 1005 * Adds a name and type to the constant pool of the class being build. Does nothing if the 1006 * constant pool already contains a similar item. <i>This method is intended for {@link Attribute} 1007 * sub classes, and is normally not needed by class generators or adapters.</i> 1008 * 1009 * @param name a name. 1010 * @param descriptor a type descriptor. 1011 * @return the index of a new or already existing name and type item. 1012 */ 1013 public int newNameType(final String name, final String descriptor) { 1014 return symbolTable.addConstantNameAndType(name, descriptor); 1015 } 1016 1017 /** 1018 * Changes the computation strategy of method properties like max stack size, max number of local 1019 * variables, and frames. 1020 * 1021 * <p><b>WARNING</b>: {@link #setFlags(int)} method changes the behavior of new method visitors 1022 * returned from {@link #visitMethod(int, String, String, String, String[])}. The behavior will be 1023 * changed only after the next method visitor is returned. All the previously returned method 1024 * visitors keep their previous behavior. 1025 * 1026 * @param flags option flags that can be used to modify the default behavior of this class. Must 1027 * be zero or more of {@link #COMPUTE_MAXS} and {@link #COMPUTE_FRAMES}. 1028 */ 1029 public final void setFlags(final int flags) { 1030 if ((flags & ClassWriter.COMPUTE_FRAMES) != 0) { 1031 compute = MethodWriter.COMPUTE_ALL_FRAMES; 1032 } else if ((flags & ClassWriter.COMPUTE_MAXS) != 0) { 1033 compute = MethodWriter.COMPUTE_MAX_STACK_AND_LOCAL; 1034 } else { 1035 compute = MethodWriter.COMPUTE_NOTHING; 1036 } 1037 } 1038 1039 // ----------------------------------------------------------------------------------------------- 1040 // Default method to compute common super classes when computing stack map frames 1041 // ----------------------------------------------------------------------------------------------- 1042 1043 /** 1044 * Returns the common super type of the two given types. The default implementation of this method 1045 * <i>loads</i> the two given classes and uses the java.lang.Class methods to find the common 1046 * super class. It can be overridden to compute this common super type in other ways, in 1047 * particular without actually loading any class, or to take into account the class that is 1048 * currently being generated by this ClassWriter, which can of course not be loaded since it is 1049 * under construction. 1050 * 1051 * @param type1 the internal name of a class (see {@link Type#getInternalName()}). 1052 * @param type2 the internal name of another class (see {@link Type#getInternalName()}). 1053 * @return the internal name of the common super class of the two given classes (see {@link 1054 * Type#getInternalName()}). 1055 */ 1056 protected String getCommonSuperClass(final String type1, final String type2) { 1057 ClassLoader classLoader = getClassLoader(); 1058 Class<?> class1; 1059 try { 1060 class1 = Class.forName(type1.replace('/', '.'), false, classLoader); 1061 } catch (ClassNotFoundException e) { 1062 throw new TypeNotPresentException(type1, e); 1063 } 1064 Class<?> class2; 1065 try { 1066 class2 = Class.forName(type2.replace('/', '.'), false, classLoader); 1067 } catch (ClassNotFoundException e) { 1068 throw new TypeNotPresentException(type2, e); 1069 } 1070 if (class1.isAssignableFrom(class2)) { 1071 return type1; 1072 } 1073 if (class2.isAssignableFrom(class1)) { 1074 return type2; 1075 } 1076 if (class1.isInterface() || class2.isInterface()) { 1077 return "java/lang/Object"; 1078 } else { 1079 do { 1080 class1 = class1.getSuperclass(); 1081 } while (!class1.isAssignableFrom(class2)); 1082 return class1.getName().replace('.', '/'); 1083 } 1084 } 1085 1086 /** 1087 * Returns the {@link ClassLoader} to be used by the default implementation of {@link 1088 * #getCommonSuperClass(String, String)}, that of this {@link ClassWriter}'s runtime type by 1089 * default. 1090 * 1091 * @return ClassLoader 1092 */ 1093 protected ClassLoader getClassLoader() { 1094 return getClass().getClassLoader(); 1095 } 1096}