/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * This file is available under and governed by the GNU General Public
 * License version 2 only, as published by the Free Software Foundation.
 * However, the following notice accompanied the original version of this
 * file:
 *
 * ASM: a very small and fast Java bytecode manipulation framework
 * Copyright (c) 2000-2011 INRIA, France Telecom
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holders nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */
package jdk.internal.org.objectweb.asm;

An AnnotationVisitor that generates a corresponding 'annotation' or 'type_annotation' structure, as defined in the Java Virtual Machine Specification (JVMS). AnnotationWriter instances can be chained in a doubly linked list, from which Runtime[In]Visible[Type]Annotations attributes can be generated with the putAnnotations method. Similarly, arrays of such lists can be used to generate Runtime[In]VisibleParameterAnnotations attributes.
Author:Eric Bruneton, Eugene Kuleshov
See Also:
/** * An {@link AnnotationVisitor} that generates a corresponding 'annotation' or 'type_annotation' * structure, as defined in the Java Virtual Machine Specification (JVMS). AnnotationWriter * instances can be chained in a doubly linked list, from which Runtime[In]Visible[Type]Annotations * attributes can be generated with the {@link #putAnnotations} method. Similarly, arrays of such * lists can be used to generate Runtime[In]VisibleParameterAnnotations attributes. * * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16">JVMS * 4.7.16</a> * @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20">JVMS * 4.7.20</a> * @author Eric Bruneton * @author Eugene Kuleshov */
final class AnnotationWriter extends AnnotationVisitor {
Where the constants used in this AnnotationWriter must be stored.
/** Where the constants used in this AnnotationWriter must be stored. */
private final SymbolTable symbolTable;
Whether values are named or not. AnnotationWriter instances used for annotation default and annotation arrays use unnamed values (i.e. they generate an 'element_value' structure for each value, instead of an element_name_index followed by an element_value).
/** * Whether values are named or not. AnnotationWriter instances used for annotation default and * annotation arrays use unnamed values (i.e. they generate an 'element_value' structure for each * value, instead of an element_name_index followed by an element_value). */
private final boolean useNamedValues;
The 'annotation' or 'type_annotation' JVMS structure corresponding to the annotation values visited so far. All the fields of these structures, except the last one - the element_value_pairs array, must be set before this ByteVector is passed to the constructor (num_element_value_pairs can be set to 0, it is reset to the correct value in visitEnd()). The element_value_pairs array is filled incrementally in the various visit() methods.

Note: as an exception to the above rules, for AnnotationDefault attributes (which contain a single element_value by definition), this ByteVector is initially empty when passed to the constructor, and numElementValuePairsOffset is set to -1.

/** * The 'annotation' or 'type_annotation' JVMS structure corresponding to the annotation values * visited so far. All the fields of these structures, except the last one - the * element_value_pairs array, must be set before this ByteVector is passed to the constructor * (num_element_value_pairs can be set to 0, it is reset to the correct value in {@link * #visitEnd()}). The element_value_pairs array is filled incrementally in the various visit() * methods. * * <p>Note: as an exception to the above rules, for AnnotationDefault attributes (which contain a * single element_value by definition), this ByteVector is initially empty when passed to the * constructor, and {@link #numElementValuePairsOffset} is set to -1. */
private final ByteVector annotation;
The offset in annotation where numElementValuePairs must be stored (or -1 for the case of AnnotationDefault attributes).
/** * The offset in {@link #annotation} where {@link #numElementValuePairs} must be stored (or -1 for * the case of AnnotationDefault attributes). */
private final int numElementValuePairsOffset;
The number of element value pairs visited so far.
/** The number of element value pairs visited so far. */
private int numElementValuePairs;
The previous AnnotationWriter. This field is used to store the list of annotations of a Runtime[In]Visible[Type]Annotations attribute. It is unused for nested or array annotations (annotation values of annotation type), or for AnnotationDefault attributes.
/** * The previous AnnotationWriter. This field is used to store the list of annotations of a * Runtime[In]Visible[Type]Annotations attribute. It is unused for nested or array annotations * (annotation values of annotation type), or for AnnotationDefault attributes. */
private final AnnotationWriter previousAnnotation;
The next AnnotationWriter. This field is used to store the list of annotations of a Runtime[In]Visible[Type]Annotations attribute. It is unused for nested or array annotations (annotation values of annotation type), or for AnnotationDefault attributes.
/** * The next AnnotationWriter. This field is used to store the list of annotations of a * Runtime[In]Visible[Type]Annotations attribute. It is unused for nested or array annotations * (annotation values of annotation type), or for AnnotationDefault attributes. */
private AnnotationWriter nextAnnotation; // ----------------------------------------------------------------------------------------------- // Constructors and factories // -----------------------------------------------------------------------------------------------
Constructs a new AnnotationWriter.
Params:
  • symbolTable – where the constants used in this AnnotationWriter must be stored.
  • useNamedValues – whether values are named or not. AnnotationDefault and annotation arrays use unnamed values.
  • annotation – where the 'annotation' or 'type_annotation' JVMS structure corresponding to the visited content must be stored. This ByteVector must already contain all the fields of the structure except the last one (the element_value_pairs array).
  • previousAnnotation – the previously visited annotation of the Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or null in other cases (e.g. nested or array annotations).
/** * Constructs a new {@link AnnotationWriter}. * * @param symbolTable where the constants used in this AnnotationWriter must be stored. * @param useNamedValues whether values are named or not. AnnotationDefault and annotation arrays * use unnamed values. * @param annotation where the 'annotation' or 'type_annotation' JVMS structure corresponding to * the visited content must be stored. This ByteVector must already contain all the fields of * the structure except the last one (the element_value_pairs array). * @param previousAnnotation the previously visited annotation of the * Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or * {@literal null} in other cases (e.g. nested or array annotations). */
AnnotationWriter( final SymbolTable symbolTable, final boolean useNamedValues, final ByteVector annotation, final AnnotationWriter previousAnnotation) { super(/* latest api = */ Opcodes.ASM8); this.symbolTable = symbolTable; this.useNamedValues = useNamedValues; this.annotation = annotation; // By hypothesis, num_element_value_pairs is stored in the last unsigned short of 'annotation'. this.numElementValuePairsOffset = annotation.length == 0 ? -1 : annotation.length - 2; this.previousAnnotation = previousAnnotation; if (previousAnnotation != null) { previousAnnotation.nextAnnotation = this; } }
Creates a new AnnotationWriter using named values.
Params:
  • symbolTable – where the constants used in this AnnotationWriter must be stored.
  • descriptor – the class descriptor of the annotation class.
  • previousAnnotation – the previously visited annotation of the Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or null in other cases (e.g. nested or array annotations).
Returns:a new AnnotationWriter for the given annotation descriptor.
/** * Creates a new {@link AnnotationWriter} using named values. * * @param symbolTable where the constants used in this AnnotationWriter must be stored. * @param descriptor the class descriptor of the annotation class. * @param previousAnnotation the previously visited annotation of the * Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or * {@literal null} in other cases (e.g. nested or array annotations). * @return a new {@link AnnotationWriter} for the given annotation descriptor. */
static AnnotationWriter create( final SymbolTable symbolTable, final String descriptor, final AnnotationWriter previousAnnotation) { // Create a ByteVector to hold an 'annotation' JVMS structure. // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16. ByteVector annotation = new ByteVector(); // Write type_index and reserve space for num_element_value_pairs. annotation.putShort(symbolTable.addConstantUtf8(descriptor)).putShort(0); return new AnnotationWriter( symbolTable, /* useNamedValues = */ true, annotation, previousAnnotation); }
Creates a new AnnotationWriter using named values.
Params:
  • symbolTable – where the constants used in this AnnotationWriter must be stored.
  • typeRef – a reference to the annotated type. The sort of this type reference must be TypeReference.CLASS_TYPE_PARAMETER, TypeReference.CLASS_TYPE_PARAMETER_BOUND or TypeReference.CLASS_EXTENDS. See TypeReference.
  • typePath – the path to the annotated type argument, wildcard bound, array element type, or static inner type within 'typeRef'. May be null if the annotation targets 'typeRef' as a whole.
  • descriptor – the class descriptor of the annotation class.
  • previousAnnotation – the previously visited annotation of the Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or null in other cases (e.g. nested or array annotations).
Returns:a new AnnotationWriter for the given type annotation reference and descriptor.
/** * Creates a new {@link AnnotationWriter} using named values. * * @param symbolTable where the constants used in this AnnotationWriter must be stored. * @param typeRef a reference to the annotated type. The sort of this type reference must be * {@link TypeReference#CLASS_TYPE_PARAMETER}, {@link * TypeReference#CLASS_TYPE_PARAMETER_BOUND} or {@link TypeReference#CLASS_EXTENDS}. See * {@link TypeReference}. * @param typePath the path to the annotated type argument, wildcard bound, array element type, or * static inner type within 'typeRef'. May be {@literal null} if the annotation targets * 'typeRef' as a whole. * @param descriptor the class descriptor of the annotation class. * @param previousAnnotation the previously visited annotation of the * Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or * {@literal null} in other cases (e.g. nested or array annotations). * @return a new {@link AnnotationWriter} for the given type annotation reference and descriptor. */
static AnnotationWriter create( final SymbolTable symbolTable, final int typeRef, final TypePath typePath, final String descriptor, final AnnotationWriter previousAnnotation) { // Create a ByteVector to hold a 'type_annotation' JVMS structure. // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20. ByteVector typeAnnotation = new ByteVector(); // Write target_type, target_info, and target_path. TypeReference.putTarget(typeRef, typeAnnotation); TypePath.put(typePath, typeAnnotation); // Write type_index and reserve space for num_element_value_pairs. typeAnnotation.putShort(symbolTable.addConstantUtf8(descriptor)).putShort(0); return new AnnotationWriter( symbolTable, /* useNamedValues = */ true, typeAnnotation, previousAnnotation); } // ----------------------------------------------------------------------------------------------- // Implementation of the AnnotationVisitor abstract class // ----------------------------------------------------------------------------------------------- @Override public void visit(final String name, final Object value) { // Case of an element_value with a const_value_index, class_info_index or array_index field. // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1. ++numElementValuePairs; if (useNamedValues) { annotation.putShort(symbolTable.addConstantUtf8(name)); } if (value instanceof String) { annotation.put12('s', symbolTable.addConstantUtf8((String) value)); } else if (value instanceof Byte) { annotation.put12('B', symbolTable.addConstantInteger(((Byte) value).byteValue()).index); } else if (value instanceof Boolean) { int booleanValue = ((Boolean) value).booleanValue() ? 1 : 0; annotation.put12('Z', symbolTable.addConstantInteger(booleanValue).index); } else if (value instanceof Character) { annotation.put12('C', symbolTable.addConstantInteger(((Character) value).charValue()).index); } else if (value instanceof Short) { annotation.put12('S', symbolTable.addConstantInteger(((Short) value).shortValue()).index); } else if (value instanceof Type) { annotation.put12('c', symbolTable.addConstantUtf8(((Type) value).getDescriptor())); } else if (value instanceof byte[]) { byte[] byteArray = (byte[]) value; annotation.put12('[', byteArray.length); for (byte byteValue : byteArray) { annotation.put12('B', symbolTable.addConstantInteger(byteValue).index); } } else if (value instanceof boolean[]) { boolean[] booleanArray = (boolean[]) value; annotation.put12('[', booleanArray.length); for (boolean booleanValue : booleanArray) { annotation.put12('Z', symbolTable.addConstantInteger(booleanValue ? 1 : 0).index); } } else if (value instanceof short[]) { short[] shortArray = (short[]) value; annotation.put12('[', shortArray.length); for (short shortValue : shortArray) { annotation.put12('S', symbolTable.addConstantInteger(shortValue).index); } } else if (value instanceof char[]) { char[] charArray = (char[]) value; annotation.put12('[', charArray.length); for (char charValue : charArray) { annotation.put12('C', symbolTable.addConstantInteger(charValue).index); } } else if (value instanceof int[]) { int[] intArray = (int[]) value; annotation.put12('[', intArray.length); for (int intValue : intArray) { annotation.put12('I', symbolTable.addConstantInteger(intValue).index); } } else if (value instanceof long[]) { long[] longArray = (long[]) value; annotation.put12('[', longArray.length); for (long longValue : longArray) { annotation.put12('J', symbolTable.addConstantLong(longValue).index); } } else if (value instanceof float[]) { float[] floatArray = (float[]) value; annotation.put12('[', floatArray.length); for (float floatValue : floatArray) { annotation.put12('F', symbolTable.addConstantFloat(floatValue).index); } } else if (value instanceof double[]) { double[] doubleArray = (double[]) value; annotation.put12('[', doubleArray.length); for (double doubleValue : doubleArray) { annotation.put12('D', symbolTable.addConstantDouble(doubleValue).index); } } else { Symbol symbol = symbolTable.addConstant(value); annotation.put12(".s.IFJDCS".charAt(symbol.tag), symbol.index); } } @Override public void visitEnum(final String name, final String descriptor, final String value) { // Case of an element_value with an enum_const_value field. // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1. ++numElementValuePairs; if (useNamedValues) { annotation.putShort(symbolTable.addConstantUtf8(name)); } annotation .put12('e', symbolTable.addConstantUtf8(descriptor)) .putShort(symbolTable.addConstantUtf8(value)); } @Override public AnnotationVisitor visitAnnotation(final String name, final String descriptor) { // Case of an element_value with an annotation_value field. // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1. ++numElementValuePairs; if (useNamedValues) { annotation.putShort(symbolTable.addConstantUtf8(name)); } // Write tag and type_index, and reserve 2 bytes for num_element_value_pairs. annotation.put12('@', symbolTable.addConstantUtf8(descriptor)).putShort(0); return new AnnotationWriter(symbolTable, /* useNamedValues = */ true, annotation, null); } @Override public AnnotationVisitor visitArray(final String name) { // Case of an element_value with an array_value field. // https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1 ++numElementValuePairs; if (useNamedValues) { annotation.putShort(symbolTable.addConstantUtf8(name)); } // Write tag, and reserve 2 bytes for num_values. Here we take advantage of the fact that the // end of an element_value of array type is similar to the end of an 'annotation' structure: an // unsigned short num_values followed by num_values element_value, versus an unsigned short // num_element_value_pairs, followed by num_element_value_pairs { element_name_index, // element_value } tuples. This allows us to use an AnnotationWriter with unnamed values to // visit the array elements. Its num_element_value_pairs will correspond to the number of array // elements and will be stored in what is in fact num_values. annotation.put12('[', 0); return new AnnotationWriter(symbolTable, /* useNamedValues = */ false, annotation, null); } @Override public void visitEnd() { if (numElementValuePairsOffset != -1) { byte[] data = annotation.data; data[numElementValuePairsOffset] = (byte) (numElementValuePairs >>> 8); data[numElementValuePairsOffset + 1] = (byte) numElementValuePairs; } } // ----------------------------------------------------------------------------------------------- // Utility methods // -----------------------------------------------------------------------------------------------
Returns the size of a Runtime[In]Visible[Type]Annotations attribute containing this annotation and all its predecessors (see previousAnnotation. Also adds the attribute name to the constant pool of the class (if not null).
Params:
  • attributeName – one of "Runtime[In]Visible[Type]Annotations", or null.
Returns:the size in bytes of a Runtime[In]Visible[Type]Annotations attribute containing this annotation and all its predecessors. This includes the size of the attribute_name_index and attribute_length fields.
/** * Returns the size of a Runtime[In]Visible[Type]Annotations attribute containing this annotation * and all its <i>predecessors</i> (see {@link #previousAnnotation}. Also adds the attribute name * to the constant pool of the class (if not null). * * @param attributeName one of "Runtime[In]Visible[Type]Annotations", or {@literal null}. * @return the size in bytes of a Runtime[In]Visible[Type]Annotations attribute containing this * annotation and all its predecessors. This includes the size of the attribute_name_index and * attribute_length fields. */
int computeAnnotationsSize(final String attributeName) { if (attributeName != null) { symbolTable.addConstantUtf8(attributeName); } // The attribute_name_index, attribute_length and num_annotations fields use 8 bytes. int attributeSize = 8; AnnotationWriter annotationWriter = this; while (annotationWriter != null) { attributeSize += annotationWriter.annotation.length; annotationWriter = annotationWriter.previousAnnotation; } return attributeSize; }
Returns the size of the Runtime[In]Visible[Type]Annotations attributes containing the given annotations and all their predecessors (see previousAnnotation. Also adds the attribute names to the constant pool of the class (if not null).
Params:
  • lastRuntimeVisibleAnnotation – The last runtime visible annotation of a field, method or class. The previous ones can be accessed with the previousAnnotation field. May be null.
  • lastRuntimeInvisibleAnnotation – The last runtime invisible annotation of this a field, method or class. The previous ones can be accessed with the previousAnnotation field. May be null.
  • lastRuntimeVisibleTypeAnnotation – The last runtime visible type annotation of this a field, method or class. The previous ones can be accessed with the previousAnnotation field. May be null.
  • lastRuntimeInvisibleTypeAnnotation – The last runtime invisible type annotation of a field, method or class field. The previous ones can be accessed with the previousAnnotation field. May be null.
Returns:the size in bytes of a Runtime[In]Visible[Type]Annotations attribute containing the given annotations and all their predecessors. This includes the size of the attribute_name_index and attribute_length fields.
/** * Returns the size of the Runtime[In]Visible[Type]Annotations attributes containing the given * annotations and all their <i>predecessors</i> (see {@link #previousAnnotation}. Also adds the * attribute names to the constant pool of the class (if not null). * * @param lastRuntimeVisibleAnnotation The last runtime visible annotation of a field, method or * class. The previous ones can be accessed with the {@link #previousAnnotation} field. May be * {@literal null}. * @param lastRuntimeInvisibleAnnotation The last runtime invisible annotation of this a field, * method or class. The previous ones can be accessed with the {@link #previousAnnotation} * field. May be {@literal null}. * @param lastRuntimeVisibleTypeAnnotation The last runtime visible type annotation of this a * field, method or class. The previous ones can be accessed with the {@link * #previousAnnotation} field. May be {@literal null}. * @param lastRuntimeInvisibleTypeAnnotation The last runtime invisible type annotation of a * field, method or class field. The previous ones can be accessed with the {@link * #previousAnnotation} field. May be {@literal null}. * @return the size in bytes of a Runtime[In]Visible[Type]Annotations attribute containing the * given annotations and all their predecessors. This includes the size of the * attribute_name_index and attribute_length fields. */
static int computeAnnotationsSize( final AnnotationWriter lastRuntimeVisibleAnnotation, final AnnotationWriter lastRuntimeInvisibleAnnotation, final AnnotationWriter lastRuntimeVisibleTypeAnnotation, final AnnotationWriter lastRuntimeInvisibleTypeAnnotation) { int size = 0; if (lastRuntimeVisibleAnnotation != null) { size += lastRuntimeVisibleAnnotation.computeAnnotationsSize( Constants.RUNTIME_VISIBLE_ANNOTATIONS); } if (lastRuntimeInvisibleAnnotation != null) { size += lastRuntimeInvisibleAnnotation.computeAnnotationsSize( Constants.RUNTIME_INVISIBLE_ANNOTATIONS); } if (lastRuntimeVisibleTypeAnnotation != null) { size += lastRuntimeVisibleTypeAnnotation.computeAnnotationsSize( Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS); } if (lastRuntimeInvisibleTypeAnnotation != null) { size += lastRuntimeInvisibleTypeAnnotation.computeAnnotationsSize( Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS); } return size; }
Puts a Runtime[In]Visible[Type]Annotations attribute containing this annotations and all its predecessors (see previousAnnotation in the given ByteVector. Annotations are put in the same order they have been visited.
Params:
  • attributeNameIndex – the constant pool index of the attribute name (one of "Runtime[In]Visible[Type]Annotations").
  • output – where the attribute must be put.
/** * Puts a Runtime[In]Visible[Type]Annotations attribute containing this annotations and all its * <i>predecessors</i> (see {@link #previousAnnotation} in the given ByteVector. Annotations are * put in the same order they have been visited. * * @param attributeNameIndex the constant pool index of the attribute name (one of * "Runtime[In]Visible[Type]Annotations"). * @param output where the attribute must be put. */
void putAnnotations(final int attributeNameIndex, final ByteVector output) { int attributeLength = 2; // For num_annotations. int numAnnotations = 0; AnnotationWriter annotationWriter = this; AnnotationWriter firstAnnotation = null; while (annotationWriter != null) { // In case the user forgot to call visitEnd(). annotationWriter.visitEnd(); attributeLength += annotationWriter.annotation.length; numAnnotations++; firstAnnotation = annotationWriter; annotationWriter = annotationWriter.previousAnnotation; } output.putShort(attributeNameIndex); output.putInt(attributeLength); output.putShort(numAnnotations); annotationWriter = firstAnnotation; while (annotationWriter != null) { output.putByteArray(annotationWriter.annotation.data, 0, annotationWriter.annotation.length); annotationWriter = annotationWriter.nextAnnotation; } }
Puts the Runtime[In]Visible[Type]Annotations attributes containing the given annotations and all their predecessors (see previousAnnotation in the given ByteVector. Annotations are put in the same order they have been visited.
Params:
  • symbolTable – where the constants used in the AnnotationWriter instances are stored.
  • lastRuntimeVisibleAnnotation – The last runtime visible annotation of a field, method or class. The previous ones can be accessed with the previousAnnotation field. May be null.
  • lastRuntimeInvisibleAnnotation – The last runtime invisible annotation of this a field, method or class. The previous ones can be accessed with the previousAnnotation field. May be null.
  • lastRuntimeVisibleTypeAnnotation – The last runtime visible type annotation of this a field, method or class. The previous ones can be accessed with the previousAnnotation field. May be null.
  • lastRuntimeInvisibleTypeAnnotation – The last runtime invisible type annotation of a field, method or class field. The previous ones can be accessed with the previousAnnotation field. May be null.
  • output – where the attributes must be put.
/** * Puts the Runtime[In]Visible[Type]Annotations attributes containing the given annotations and * all their <i>predecessors</i> (see {@link #previousAnnotation} in the given ByteVector. * Annotations are put in the same order they have been visited. * * @param symbolTable where the constants used in the AnnotationWriter instances are stored. * @param lastRuntimeVisibleAnnotation The last runtime visible annotation of a field, method or * class. The previous ones can be accessed with the {@link #previousAnnotation} field. May be * {@literal null}. * @param lastRuntimeInvisibleAnnotation The last runtime invisible annotation of this a field, * method or class. The previous ones can be accessed with the {@link #previousAnnotation} * field. May be {@literal null}. * @param lastRuntimeVisibleTypeAnnotation The last runtime visible type annotation of this a * field, method or class. The previous ones can be accessed with the {@link * #previousAnnotation} field. May be {@literal null}. * @param lastRuntimeInvisibleTypeAnnotation The last runtime invisible type annotation of a * field, method or class field. The previous ones can be accessed with the {@link * #previousAnnotation} field. May be {@literal null}. * @param output where the attributes must be put. */
static void putAnnotations( final SymbolTable symbolTable, final AnnotationWriter lastRuntimeVisibleAnnotation, final AnnotationWriter lastRuntimeInvisibleAnnotation, final AnnotationWriter lastRuntimeVisibleTypeAnnotation, final AnnotationWriter lastRuntimeInvisibleTypeAnnotation, final ByteVector output) { if (lastRuntimeVisibleAnnotation != null) { lastRuntimeVisibleAnnotation.putAnnotations( symbolTable.addConstantUtf8(Constants.RUNTIME_VISIBLE_ANNOTATIONS), output); } if (lastRuntimeInvisibleAnnotation != null) { lastRuntimeInvisibleAnnotation.putAnnotations( symbolTable.addConstantUtf8(Constants.RUNTIME_INVISIBLE_ANNOTATIONS), output); } if (lastRuntimeVisibleTypeAnnotation != null) { lastRuntimeVisibleTypeAnnotation.putAnnotations( symbolTable.addConstantUtf8(Constants.RUNTIME_VISIBLE_TYPE_ANNOTATIONS), output); } if (lastRuntimeInvisibleTypeAnnotation != null) { lastRuntimeInvisibleTypeAnnotation.putAnnotations( symbolTable.addConstantUtf8(Constants.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS), output); } }
Returns the size of a Runtime[In]VisibleParameterAnnotations attribute containing all the annotation lists from the given AnnotationWriter sub-array. Also adds the attribute name to the constant pool of the class.
Params:
  • attributeName – one of "Runtime[In]VisibleParameterAnnotations".
  • annotationWriters – an array of AnnotationWriter lists (designated by their last element).
  • annotableParameterCount – the number of elements in annotationWriters to take into account (elements [0..annotableParameterCount[ are taken into account).
Returns:the size in bytes of a Runtime[In]VisibleParameterAnnotations attribute corresponding to the given sub-array of AnnotationWriter lists. This includes the size of the attribute_name_index and attribute_length fields.
/** * Returns the size of a Runtime[In]VisibleParameterAnnotations attribute containing all the * annotation lists from the given AnnotationWriter sub-array. Also adds the attribute name to the * constant pool of the class. * * @param attributeName one of "Runtime[In]VisibleParameterAnnotations". * @param annotationWriters an array of AnnotationWriter lists (designated by their <i>last</i> * element). * @param annotableParameterCount the number of elements in annotationWriters to take into account * (elements [0..annotableParameterCount[ are taken into account). * @return the size in bytes of a Runtime[In]VisibleParameterAnnotations attribute corresponding * to the given sub-array of AnnotationWriter lists. This includes the size of the * attribute_name_index and attribute_length fields. */
static int computeParameterAnnotationsSize( final String attributeName, final AnnotationWriter[] annotationWriters, final int annotableParameterCount) { // Note: attributeName is added to the constant pool by the call to computeAnnotationsSize // below. This assumes that there is at least one non-null element in the annotationWriters // sub-array (which is ensured by the lazy instantiation of this array in MethodWriter). // The attribute_name_index, attribute_length and num_parameters fields use 7 bytes, and each // element of the parameter_annotations array uses 2 bytes for its num_annotations field. int attributeSize = 7 + 2 * annotableParameterCount; for (int i = 0; i < annotableParameterCount; ++i) { AnnotationWriter annotationWriter = annotationWriters[i]; attributeSize += annotationWriter == null ? 0 : annotationWriter.computeAnnotationsSize(attributeName) - 8; } return attributeSize; }
Puts a Runtime[In]VisibleParameterAnnotations attribute containing all the annotation lists from the given AnnotationWriter sub-array in the given ByteVector.
Params:
  • attributeNameIndex – constant pool index of the attribute name (one of Runtime[In]VisibleParameterAnnotations).
  • annotationWriters – an array of AnnotationWriter lists (designated by their last element).
  • annotableParameterCount – the number of elements in annotationWriters to put (elements [0..annotableParameterCount[ are put).
  • output – where the attribute must be put.
/** * Puts a Runtime[In]VisibleParameterAnnotations attribute containing all the annotation lists * from the given AnnotationWriter sub-array in the given ByteVector. * * @param attributeNameIndex constant pool index of the attribute name (one of * Runtime[In]VisibleParameterAnnotations). * @param annotationWriters an array of AnnotationWriter lists (designated by their <i>last</i> * element). * @param annotableParameterCount the number of elements in annotationWriters to put (elements * [0..annotableParameterCount[ are put). * @param output where the attribute must be put. */
static void putParameterAnnotations( final int attributeNameIndex, final AnnotationWriter[] annotationWriters, final int annotableParameterCount, final ByteVector output) { // The num_parameters field uses 1 byte, and each element of the parameter_annotations array // uses 2 bytes for its num_annotations field. int attributeLength = 1 + 2 * annotableParameterCount; for (int i = 0; i < annotableParameterCount; ++i) { AnnotationWriter annotationWriter = annotationWriters[i]; attributeLength += annotationWriter == null ? 0 : annotationWriter.computeAnnotationsSize(null) - 8; } output.putShort(attributeNameIndex); output.putInt(attributeLength); output.putByte(annotableParameterCount); for (int i = 0; i < annotableParameterCount; ++i) { AnnotationWriter annotationWriter = annotationWriters[i]; AnnotationWriter firstAnnotation = null; int numAnnotations = 0; while (annotationWriter != null) { // In case user the forgot to call visitEnd(). annotationWriter.visitEnd(); numAnnotations++; firstAnnotation = annotationWriter; annotationWriter = annotationWriter.previousAnnotation; } output.putShort(numAnnotations); annotationWriter = firstAnnotation; while (annotationWriter != null) { output.putByteArray( annotationWriter.annotation.data, 0, annotationWriter.annotation.length); annotationWriter = annotationWriter.nextAnnotation; } } } }