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 * An {@link AnnotationVisitor} that generates a corresponding 'annotation' or 'type_annotation' 32 * structure, as defined in the Java Virtual Machine Specification (JVMS). AnnotationWriter 33 * instances can be chained in a doubly linked list, from which Runtime[In]Visible[Type]Annotations 34 * attributes can be generated with the {@link #putAnnotations} method. Similarly, arrays of such 35 * lists can be used to generate Runtime[In]VisibleParameterAnnotations attributes. 36 * 37 * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16">JVMS 38 * 4.7.16</a> 39 * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20">JVMS 40 * 4.7.20</a> 41 * @author Eric Bruneton 42 * @author Eugene Kuleshov 43 */ 44 final class AnnotationWriter extends AnnotationVisitor { 45 46 /** Where the constants used in this AnnotationWriter must be stored. */ 47 private final SymbolTable symbolTable; 48 49 /** 50 * Whether values are named or not. AnnotationWriter instances used for annotation default and 51 * annotation arrays use unnamed values (i.e. they generate an 'element_value' structure for each 52 * value, instead of an element_name_index followed by an element_value). 53 */ 54 private final boolean useNamedValues; 55 56 /** 57 * The 'annotation' or 'type_annotation' JVMS structure corresponding to the annotation values 58 * visited so far. All the fields of these structures, except the last one - the 59 * element_value_pairs array, must be set before this ByteVector is passed to the constructor 60 * (num_element_value_pairs can be set to 0, it is reset to the correct value in {@link 61 * #visitEnd()}). The element_value_pairs array is filled incrementally in the various visit() 62 * methods. 63 * 64 * <p>Note: as an exception to the above rules, for AnnotationDefault attributes (which contain a 65 * single element_value by definition), this ByteVector is initially empty when passed to the 66 * constructor, and {@link #numElementValuePairsOffset} is set to -1. 67 */ 68 private final ByteVector annotation; 69 70 /** 71 * The offset in {@link #annotation} where {@link #numElementValuePairs} must be stored (or -1 for 72 * the case of AnnotationDefault attributes). 73 */ 74 private final int numElementValuePairsOffset; 75 76 /** The number of element value pairs visited so far. */ 77 private int numElementValuePairs; 78 79 /** 80 * The previous AnnotationWriter. This field is used to store the list of annotations of a 81 * Runtime[In]Visible[Type]Annotations attribute. It is unused for nested or array annotations 82 * (annotation values of annotation type), or for AnnotationDefault attributes. 83 */ 84 private final AnnotationWriter previousAnnotation; 85 86 /** 87 * The next AnnotationWriter. This field is used to store the list of annotations of a 88 * Runtime[In]Visible[Type]Annotations attribute. It is unused for nested or array annotations 89 * (annotation values of annotation type), or for AnnotationDefault attributes. 90 */ 91 private AnnotationWriter nextAnnotation; 92 93 // ----------------------------------------------------------------------------------------------- 94 // Constructors and factories 95 // ----------------------------------------------------------------------------------------------- 96 97 /** 98 * Constructs a new {@link AnnotationWriter}. 99 * 100 * @param symbolTable where the constants used in this AnnotationWriter must be stored. 101 * @param useNamedValues whether values are named or not. AnnotationDefault and annotation arrays 102 * use unnamed values. 103 * @param annotation where the 'annotation' or 'type_annotation' JVMS structure corresponding to 104 * the visited content must be stored. This ByteVector must already contain all the fields of 105 * the structure except the last one (the element_value_pairs array). 106 * @param previousAnnotation the previously visited annotation of the 107 * Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or 108 * {@literal null} in other cases (e.g. nested or array annotations). 109 */ AnnotationWriter( final SymbolTable symbolTable, final boolean useNamedValues, final ByteVector annotation, final AnnotationWriter previousAnnotation)110 AnnotationWriter( 111 final SymbolTable symbolTable, 112 final boolean useNamedValues, 113 final ByteVector annotation, 114 final AnnotationWriter previousAnnotation) { 115 super(/* latest api = */ Opcodes.ASM9); 116 this.symbolTable = symbolTable; 117 this.useNamedValues = useNamedValues; 118 this.annotation = annotation; 119 // By hypothesis, num_element_value_pairs is stored in the last unsigned short of 'annotation'. 120 this.numElementValuePairsOffset = annotation.length == 0 ? -1 : annotation.length - 2; 121 this.previousAnnotation = previousAnnotation; 122 if (previousAnnotation != null) { 123 previousAnnotation.nextAnnotation = this; 124 } 125 } 126 127 /** 128 * Creates a new {@link AnnotationWriter} using named values. 129 * 130 * @param symbolTable where the constants used in this AnnotationWriter must be stored. 131 * @param descriptor the class descriptor of the annotation class. 132 * @param previousAnnotation the previously visited annotation of the 133 * Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or 134 * {@literal null} in other cases (e.g. nested or array annotations). 135 * @return a new {@link AnnotationWriter} for the given annotation descriptor. 136 */ create( final SymbolTable symbolTable, final String descriptor, final AnnotationWriter previousAnnotation)137 static AnnotationWriter create( 138 final SymbolTable symbolTable, 139 final String descriptor, 140 final AnnotationWriter previousAnnotation) { 141 // Create a ByteVector to hold an 'annotation' JVMS structure. 142 // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16. 143 ByteVector annotation = new ByteVector(); 144 // Write type_index and reserve space for num_element_value_pairs. 145 annotation.putShort(symbolTable.addConstantUtf8(descriptor)).putShort(0); 146 return new AnnotationWriter( 147 symbolTable, /* useNamedValues = */ true, annotation, previousAnnotation); 148 } 149 150 /** 151 * Creates a new {@link AnnotationWriter} using named values. 152 * 153 * @param symbolTable where the constants used in this AnnotationWriter must be stored. 154 * @param typeRef a reference to the annotated type. The sort of this type reference must be 155 * {@link TypeReference#CLASS_TYPE_PARAMETER}, {@link 156 * TypeReference#CLASS_TYPE_PARAMETER_BOUND} or {@link TypeReference#CLASS_EXTENDS}. See 157 * {@link TypeReference}. 158 * @param typePath the path to the annotated type argument, wildcard bound, array element type, or 159 * static inner type within 'typeRef'. May be {@literal null} if the annotation targets 160 * 'typeRef' as a whole. 161 * @param descriptor the class descriptor of the annotation class. 162 * @param previousAnnotation the previously visited annotation of the 163 * Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or 164 * {@literal null} in other cases (e.g. nested or array annotations). 165 * @return a new {@link AnnotationWriter} for the given type annotation reference and descriptor. 166 */ create( final SymbolTable symbolTable, final int typeRef, final TypePath typePath, final String descriptor, final AnnotationWriter previousAnnotation)167 static AnnotationWriter create( 168 final SymbolTable symbolTable, 169 final int typeRef, 170 final TypePath typePath, 171 final String descriptor, 172 final AnnotationWriter previousAnnotation) { 173 // Create a ByteVector to hold a 'type_annotation' JVMS structure. 174 // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20. 175 ByteVector typeAnnotation = new ByteVector(); 176 // Write target_type, target_info, and target_path. 177 TypeReference.putTarget(typeRef, typeAnnotation); 178 TypePath.put(typePath, typeAnnotation); 179 // Write type_index and reserve space for num_element_value_pairs. 180 typeAnnotation.putShort(symbolTable.addConstantUtf8(descriptor)).putShort(0); 181 return new AnnotationWriter( 182 symbolTable, /* useNamedValues = */ true, typeAnnotation, previousAnnotation); 183 } 184 185 // ----------------------------------------------------------------------------------------------- 186 // Implementation of the AnnotationVisitor abstract class 187 // ----------------------------------------------------------------------------------------------- 188 189 @Override visit(final String name, final Object value)190 public void visit(final String name, final Object value) { 191 // Case of an element_value with a const_value_index, class_info_index or array_index field. 192 // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1. 193 ++numElementValuePairs; 194 if (useNamedValues) { 195 annotation.putShort(symbolTable.addConstantUtf8(name)); 196 } 197 if (value instanceof String) { 198 annotation.put12('s', symbolTable.addConstantUtf8((String) value)); 199 } else if (value instanceof Byte) { 200 annotation.put12('B', symbolTable.addConstantInteger(((Byte) value).byteValue()).index); 201 } else if (value instanceof Boolean) { 202 int booleanValue = ((Boolean) value).booleanValue() ? 1 : 0; 203 annotation.put12('Z', symbolTable.addConstantInteger(booleanValue).index); 204 } else if (value instanceof Character) { 205 annotation.put12('C', symbolTable.addConstantInteger(((Character) value).charValue()).index); 206 } else if (value instanceof Short) { 207 annotation.put12('S', symbolTable.addConstantInteger(((Short) value).shortValue()).index); 208 } else if (value instanceof Type) { 209 annotation.put12('c', symbolTable.addConstantUtf8(((Type) value).getDescriptor())); 210 } else if (value instanceof byte[]) { 211 byte[] byteArray = (byte[]) value; 212 annotation.put12('[', byteArray.length); 213 for (byte byteValue : byteArray) { 214 annotation.put12('B', symbolTable.addConstantInteger(byteValue).index); 215 } 216 } else if (value instanceof boolean[]) { 217 boolean[] booleanArray = (boolean[]) value; 218 annotation.put12('[', booleanArray.length); 219 for (boolean booleanValue : booleanArray) { 220 annotation.put12('Z', symbolTable.addConstantInteger(booleanValue ? 1 : 0).index); 221 } 222 } else if (value instanceof short[]) { 223 short[] shortArray = (short[]) value; 224 annotation.put12('[', shortArray.length); 225 for (short shortValue : shortArray) { 226 annotation.put12('S', symbolTable.addConstantInteger(shortValue).index); 227 } 228 } else if (value instanceof char[]) { 229 char[] charArray = (char[]) value; 230 annotation.put12('[', charArray.length); 231 for (char charValue : charArray) { 232 annotation.put12('C', symbolTable.addConstantInteger(charValue).index); 233 } 234 } else if (value instanceof int[]) { 235 int[] intArray = (int[]) value; 236 annotation.put12('[', intArray.length); 237 for (int intValue : intArray) { 238 annotation.put12('I', symbolTable.addConstantInteger(intValue).index); 239 } 240 } else if (value instanceof long[]) { 241 long[] longArray = (long[]) value; 242 annotation.put12('[', longArray.length); 243 for (long longValue : longArray) { 244 annotation.put12('J', symbolTable.addConstantLong(longValue).index); 245 } 246 } else if (value instanceof float[]) { 247 float[] floatArray = (float[]) value; 248 annotation.put12('[', floatArray.length); 249 for (float floatValue : floatArray) { 250 annotation.put12('F', symbolTable.addConstantFloat(floatValue).index); 251 } 252 } else if (value instanceof double[]) { 253 double[] doubleArray = (double[]) value; 254 annotation.put12('[', doubleArray.length); 255 for (double doubleValue : doubleArray) { 256 annotation.put12('D', symbolTable.addConstantDouble(doubleValue).index); 257 } 258 } else { 259 Symbol symbol = symbolTable.addConstant(value); 260 annotation.put12(".s.IFJDCS".charAt(symbol.tag), symbol.index); 261 } 262 } 263 264 @Override visitEnum(final String name, final String descriptor, final String value)265 public void visitEnum(final String name, final String descriptor, final String value) { 266 // Case of an element_value with an enum_const_value field. 267 // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1. 268 ++numElementValuePairs; 269 if (useNamedValues) { 270 annotation.putShort(symbolTable.addConstantUtf8(name)); 271 } 272 annotation 273 .put12('e', symbolTable.addConstantUtf8(descriptor)) 274 .putShort(symbolTable.addConstantUtf8(value)); 275 } 276 277 @Override visitAnnotation(final String name, final String descriptor)278 public AnnotationVisitor visitAnnotation(final String name, final String descriptor) { 279 // Case of an element_value with an annotation_value field. 280 // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1. 281 ++numElementValuePairs; 282 if (useNamedValues) { 283 annotation.putShort(symbolTable.addConstantUtf8(name)); 284 } 285 // Write tag and type_index, and reserve 2 bytes for num_element_value_pairs. 286 annotation.put12('@', symbolTable.addConstantUtf8(descriptor)).putShort(0); 287 return new AnnotationWriter(symbolTable, /* useNamedValues = */ true, annotation, null); 288 } 289 290 @Override visitArray(final String name)291 public AnnotationVisitor visitArray(final String name) { 292 // Case of an element_value with an array_value field. 293 // https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1 294 ++numElementValuePairs; 295 if (useNamedValues) { 296 annotation.putShort(symbolTable.addConstantUtf8(name)); 297 } 298 // Write tag, and reserve 2 bytes for num_values. Here we take advantage of the fact that the 299 // end of an element_value of array type is similar to the end of an 'annotation' structure: an 300 // unsigned short num_values followed by num_values element_value, versus an unsigned short 301 // num_element_value_pairs, followed by num_element_value_pairs { element_name_index, 302 // element_value } tuples. This allows us to use an AnnotationWriter with unnamed values to 303 // visit the array elements. Its num_element_value_pairs will correspond to the number of array 304 // elements and will be stored in what is in fact num_values. 305 annotation.put12('[', 0); 306 return new AnnotationWriter(symbolTable, /* useNamedValues = */ false, annotation, null); 307 } 308 309 @Override visitEnd()310 public void visitEnd() { 311 if (numElementValuePairsOffset != -1) { 312 byte[] data = annotation.data; 313 data[numElementValuePairsOffset] = (byte) (numElementValuePairs >>> 8); 314 data[numElementValuePairsOffset + 1] = (byte) numElementValuePairs; 315 } 316 } 317 318 // ----------------------------------------------------------------------------------------------- 319 // Utility methods 320 // ----------------------------------------------------------------------------------------------- 321 322 /** 323 * Returns the size of a Runtime[In]Visible[Type]Annotations attribute containing this annotation 324 * and all its <i>predecessors</i> (see {@link #previousAnnotation}. Also adds the attribute name 325 * to the constant pool of the class (if not null). 326 * 327 * @param attributeName one of "Runtime[In]Visible[Type]Annotations", or {@literal null}. 328 * @return the size in bytes of a Runtime[In]Visible[Type]Annotations attribute containing this 329 * annotation and all its predecessors. This includes the size of the attribute_name_index and 330 * attribute_length fields. 331 */ computeAnnotationsSize(final String attributeName)332 int computeAnnotationsSize(final String attributeName) { 333 if (attributeName != null) { 334 symbolTable.addConstantUtf8(attributeName); 335 } 336 // The attribute_name_index, attribute_length and num_annotations fields use 8 bytes. 337 int attributeSize = 8; 338 AnnotationWriter annotationWriter = this; 339 while (annotationWriter != null) { 340 attributeSize += annotationWriter.annotation.length; 341 annotationWriter = annotationWriter.previousAnnotation; 342 } 343 return attributeSize; 344 } 345 346 /** 347 * Returns the size of the Runtime[In]Visible[Type]Annotations attributes containing the given 348 * annotations and all their <i>predecessors</i> (see {@link #previousAnnotation}. Also adds the 349 * attribute names to the constant pool of the class (if not null). 350 * 351 * @param lastRuntimeVisibleAnnotation The last runtime visible annotation of a field, method or 352 * class. The previous ones can be accessed with the {@link #previousAnnotation} field. May be 353 * {@literal null}. 354 * @param lastRuntimeInvisibleAnnotation The last runtime invisible annotation of this a field, 355 * method or class. The previous ones can be accessed with the {@link #previousAnnotation} 356 * field. May be {@literal null}. 357 * @param lastRuntimeVisibleTypeAnnotation The last runtime visible type annotation of this a 358 * field, method or class. The previous ones can be accessed with the {@link 359 * #previousAnnotation} field. May be {@literal null}. 360 * @param lastRuntimeInvisibleTypeAnnotation The last runtime invisible type annotation of a 361 * field, method or class field. The previous ones can be accessed with the {@link 362 * #previousAnnotation} field. May be {@literal null}. 363 * @return the size in bytes of a Runtime[In]Visible[Type]Annotations attribute containing the 364 * given annotations and all their predecessors. This includes the size of the 365 * attribute_name_index and attribute_length fields. 366 */ computeAnnotationsSize( final AnnotationWriter lastRuntimeVisibleAnnotation, final AnnotationWriter lastRuntimeInvisibleAnnotation, final AnnotationWriter lastRuntimeVisibleTypeAnnotation, final AnnotationWriter lastRuntimeInvisibleTypeAnnotation)367 static int computeAnnotationsSize( 368 final AnnotationWriter lastRuntimeVisibleAnnotation, 369 final AnnotationWriter lastRuntimeInvisibleAnnotation, 370 final AnnotationWriter lastRuntimeVisibleTypeAnnotation, 371 final AnnotationWriter lastRuntimeInvisibleTypeAnnotation) { 372 int size = 0; 373 if (lastRuntimeVisibleAnnotation != null) { 374 size += 375 lastRuntimeVisibleAnnotation.computeAnnotationsSize( 376 Constants.RUNTIME_VISIBLE_ANNOTATIONS); 377 } 378 if (lastRuntimeInvisibleAnnotation != null) { 379 size += 380 lastRuntimeInvisibleAnnotation.computeAnnotationsSize( 381 Constants.RUNTIME_INVISIBLE_ANNOTATIONS); 382 } 383 if (lastRuntimeVisibleTypeAnnotation != null) { 384 size += 385 lastRuntimeVisibleTypeAnnotation.computeAnnotationsSize( 386 Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS); 387 } 388 if (lastRuntimeInvisibleTypeAnnotation != null) { 389 size += 390 lastRuntimeInvisibleTypeAnnotation.computeAnnotationsSize( 391 Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS); 392 } 393 return size; 394 } 395 396 /** 397 * Puts a Runtime[In]Visible[Type]Annotations attribute containing this annotations and all its 398 * <i>predecessors</i> (see {@link #previousAnnotation} in the given ByteVector. Annotations are 399 * put in the same order they have been visited. 400 * 401 * @param attributeNameIndex the constant pool index of the attribute name (one of 402 * "Runtime[In]Visible[Type]Annotations"). 403 * @param output where the attribute must be put. 404 */ putAnnotations(final int attributeNameIndex, final ByteVector output)405 void putAnnotations(final int attributeNameIndex, final ByteVector output) { 406 int attributeLength = 2; // For num_annotations. 407 int numAnnotations = 0; 408 AnnotationWriter annotationWriter = this; 409 AnnotationWriter firstAnnotation = null; 410 while (annotationWriter != null) { 411 // In case the user forgot to call visitEnd(). 412 annotationWriter.visitEnd(); 413 attributeLength += annotationWriter.annotation.length; 414 numAnnotations++; 415 firstAnnotation = annotationWriter; 416 annotationWriter = annotationWriter.previousAnnotation; 417 } 418 output.putShort(attributeNameIndex); 419 output.putInt(attributeLength); 420 output.putShort(numAnnotations); 421 annotationWriter = firstAnnotation; 422 while (annotationWriter != null) { 423 output.putByteArray(annotationWriter.annotation.data, 0, annotationWriter.annotation.length); 424 annotationWriter = annotationWriter.nextAnnotation; 425 } 426 } 427 428 /** 429 * Puts the Runtime[In]Visible[Type]Annotations attributes containing the given annotations and 430 * all their <i>predecessors</i> (see {@link #previousAnnotation} in the given ByteVector. 431 * Annotations are put in the same order they have been visited. 432 * 433 * @param symbolTable where the constants used in the AnnotationWriter instances are stored. 434 * @param lastRuntimeVisibleAnnotation The last runtime visible annotation of a field, method or 435 * class. The previous ones can be accessed with the {@link #previousAnnotation} field. May be 436 * {@literal null}. 437 * @param lastRuntimeInvisibleAnnotation The last runtime invisible annotation of this a field, 438 * method or class. The previous ones can be accessed with the {@link #previousAnnotation} 439 * field. May be {@literal null}. 440 * @param lastRuntimeVisibleTypeAnnotation The last runtime visible type annotation of this a 441 * field, method or class. The previous ones can be accessed with the {@link 442 * #previousAnnotation} field. May be {@literal null}. 443 * @param lastRuntimeInvisibleTypeAnnotation The last runtime invisible type annotation of a 444 * field, method or class field. The previous ones can be accessed with the {@link 445 * #previousAnnotation} field. May be {@literal null}. 446 * @param output where the attributes must be put. 447 */ putAnnotations( final SymbolTable symbolTable, final AnnotationWriter lastRuntimeVisibleAnnotation, final AnnotationWriter lastRuntimeInvisibleAnnotation, final AnnotationWriter lastRuntimeVisibleTypeAnnotation, final AnnotationWriter lastRuntimeInvisibleTypeAnnotation, final ByteVector output)448 static void putAnnotations( 449 final SymbolTable symbolTable, 450 final AnnotationWriter lastRuntimeVisibleAnnotation, 451 final AnnotationWriter lastRuntimeInvisibleAnnotation, 452 final AnnotationWriter lastRuntimeVisibleTypeAnnotation, 453 final AnnotationWriter lastRuntimeInvisibleTypeAnnotation, 454 final ByteVector output) { 455 if (lastRuntimeVisibleAnnotation != null) { 456 lastRuntimeVisibleAnnotation.putAnnotations( 457 symbolTable.addConstantUtf8(Constants.RUNTIME_VISIBLE_ANNOTATIONS), output); 458 } 459 if (lastRuntimeInvisibleAnnotation != null) { 460 lastRuntimeInvisibleAnnotation.putAnnotations( 461 symbolTable.addConstantUtf8(Constants.RUNTIME_INVISIBLE_ANNOTATIONS), output); 462 } 463 if (lastRuntimeVisibleTypeAnnotation != null) { 464 lastRuntimeVisibleTypeAnnotation.putAnnotations( 465 symbolTable.addConstantUtf8(Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS), output); 466 } 467 if (lastRuntimeInvisibleTypeAnnotation != null) { 468 lastRuntimeInvisibleTypeAnnotation.putAnnotations( 469 symbolTable.addConstantUtf8(Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS), output); 470 } 471 } 472 473 /** 474 * Returns the size of a Runtime[In]VisibleParameterAnnotations attribute containing all the 475 * annotation lists from the given AnnotationWriter sub-array. Also adds the attribute name to the 476 * constant pool of the class. 477 * 478 * @param attributeName one of "Runtime[In]VisibleParameterAnnotations". 479 * @param annotationWriters an array of AnnotationWriter lists (designated by their <i>last</i> 480 * element). 481 * @param annotableParameterCount the number of elements in annotationWriters to take into account 482 * (elements [0..annotableParameterCount[ are taken into account). 483 * @return the size in bytes of a Runtime[In]VisibleParameterAnnotations attribute corresponding 484 * to the given sub-array of AnnotationWriter lists. This includes the size of the 485 * attribute_name_index and attribute_length fields. 486 */ computeParameterAnnotationsSize( final String attributeName, final AnnotationWriter[] annotationWriters, final int annotableParameterCount)487 static int computeParameterAnnotationsSize( 488 final String attributeName, 489 final AnnotationWriter[] annotationWriters, 490 final int annotableParameterCount) { 491 // Note: attributeName is added to the constant pool by the call to computeAnnotationsSize 492 // below. This assumes that there is at least one non-null element in the annotationWriters 493 // sub-array (which is ensured by the lazy instantiation of this array in MethodWriter). 494 // The attribute_name_index, attribute_length and num_parameters fields use 7 bytes, and each 495 // element of the parameter_annotations array uses 2 bytes for its num_annotations field. 496 int attributeSize = 7 + 2 * annotableParameterCount; 497 for (int i = 0; i < annotableParameterCount; ++i) { 498 AnnotationWriter annotationWriter = annotationWriters[i]; 499 attributeSize += 500 annotationWriter == null ? 0 : annotationWriter.computeAnnotationsSize(attributeName) - 8; 501 } 502 return attributeSize; 503 } 504 505 /** 506 * Puts a Runtime[In]VisibleParameterAnnotations attribute containing all the annotation lists 507 * from the given AnnotationWriter sub-array in the given ByteVector. 508 * 509 * @param attributeNameIndex constant pool index of the attribute name (one of 510 * Runtime[In]VisibleParameterAnnotations). 511 * @param annotationWriters an array of AnnotationWriter lists (designated by their <i>last</i> 512 * element). 513 * @param annotableParameterCount the number of elements in annotationWriters to put (elements 514 * [0..annotableParameterCount[ are put). 515 * @param output where the attribute must be put. 516 */ putParameterAnnotations( final int attributeNameIndex, final AnnotationWriter[] annotationWriters, final int annotableParameterCount, final ByteVector output)517 static void putParameterAnnotations( 518 final int attributeNameIndex, 519 final AnnotationWriter[] annotationWriters, 520 final int annotableParameterCount, 521 final ByteVector output) { 522 // The num_parameters field uses 1 byte, and each element of the parameter_annotations array 523 // uses 2 bytes for its num_annotations field. 524 int attributeLength = 1 + 2 * annotableParameterCount; 525 for (int i = 0; i < annotableParameterCount; ++i) { 526 AnnotationWriter annotationWriter = annotationWriters[i]; 527 attributeLength += 528 annotationWriter == null ? 0 : annotationWriter.computeAnnotationsSize(null) - 8; 529 } 530 output.putShort(attributeNameIndex); 531 output.putInt(attributeLength); 532 output.putByte(annotableParameterCount); 533 for (int i = 0; i < annotableParameterCount; ++i) { 534 AnnotationWriter annotationWriter = annotationWriters[i]; 535 AnnotationWriter firstAnnotation = null; 536 int numAnnotations = 0; 537 while (annotationWriter != null) { 538 // In case user the forgot to call visitEnd(). 539 annotationWriter.visitEnd(); 540 numAnnotations++; 541 firstAnnotation = annotationWriter; 542 annotationWriter = annotationWriter.previousAnnotation; 543 } 544 output.putShort(numAnnotations); 545 annotationWriter = firstAnnotation; 546 while (annotationWriter != null) { 547 output.putByteArray( 548 annotationWriter.annotation.data, 0, annotationWriter.annotation.length); 549 annotationWriter = annotationWriter.nextAnnotation; 550 } 551 } 552 } 553 } 554