• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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