Upgrade to ASM master (6.2+) and CGLIB 3.2.7

Issue: SPR-16398
This commit is contained in:
Juergen Hoeller
2018-07-10 18:51:01 +02:00
parent aabc5d9766
commit a1d209726c
32 changed files with 15985 additions and 14583 deletions

View File

@@ -7,11 +7,11 @@ dependencyManagement {
} }
} }
// As of Spring 4.0.3, spring-core includes asm 5.x and repackages cglib 3.2, inlining // As of Spring 5.0.3, spring-core includes asm 6.x and repackages cglib 3.2.6+, inlining
// both into the spring-core jar. cglib 3.2 itself depends on asm 5.x and is therefore // both into the spring-core jar. cglib 3.2.6+ itself depends on asm 6.x and is therefore
// further transformed by the JarJar task to depend on org.springframework.asm; this // further transformed by the JarJar task to depend on org.springframework.asm; this
// avoids including two different copies of asm unnecessarily. // avoids including two different copies of asm unnecessarily.
def cglibVersion = "3.2.6" def cglibVersion = "3.2.7"
def objenesisVersion = "2.6" def objenesisVersion = "2.6"
configurations { configurations {

View File

@@ -1,169 +1,150 @@
/*** // ASM: a very small and fast Java bytecode manipulation framework
* ASM: a very small and fast Java bytecode manipulation framework // Copyright (c) 2000-2011 INRIA, France Telecom
* Copyright (c) 2000-2011 INRIA, France Telecom // All rights reserved.
* All rights reserved. //
* // Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions
* modification, are permitted provided that the following conditions // are met:
* are met: // 1. Redistributions of source code must retain the above copyright
* 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer.
* notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright
* 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the
* notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution.
* documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holders nor the names of its
* 3. Neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from
* contributors may be used to endorse or promote products derived from // this software without specific prior written permission.
* this software without specific prior written permission. //
* // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE.
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.springframework.asm; package org.springframework.asm;
/** /**
* A visitor to visit a Java annotation. The methods of this class must be * A visitor to visit a Java annotation. The methods of this class must be called in the following
* called in the following order: ( <tt>visit</tt> | <tt>visitEnum</tt> | * order: ( <tt>visit</tt> | <tt>visitEnum</tt> | <tt>visitAnnotation</tt> | <tt>visitArray</tt> )*
* <tt>visitAnnotation</tt> | <tt>visitArray</tt> )* <tt>visitEnd</tt>. * <tt>visitEnd</tt>.
* *
* @author Eric Bruneton * @author Eric Bruneton
* @author Eugene Kuleshov * @author Eugene Kuleshov
*/ */
public abstract class AnnotationVisitor { public abstract class AnnotationVisitor {
/** /**
* The ASM API version implemented by this visitor. The value of this field * The ASM API version implemented by this visitor. The value of this field must be one of {@link
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7_EXPERIMENTAL}.
*/ */
protected final int api; protected final int api;
/** /** The annotation visitor to which this visitor must delegate method calls. May be null. */
* The annotation visitor to which this visitor must delegate method calls. protected AnnotationVisitor av;
* May be null.
*/
protected AnnotationVisitor av;
/** /**
* Constructs a new {@link AnnotationVisitor}. * Constructs a new {@link AnnotationVisitor}.
* *
* @param api * @param api the ASM API version implemented by this visitor. Must be one of {@link
* the ASM API version implemented by this visitor. Must be one * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. * Opcodes#ASM7_EXPERIMENTAL}.
*/ */
public AnnotationVisitor(final int api) { public AnnotationVisitor(final int api) {
this(api, null); this(api, null);
}
/**
* Constructs a new {@link AnnotationVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be one of {@link
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link
* Opcodes#ASM7_EXPERIMENTAL}.
* @param annotationVisitor the annotation visitor to which this visitor must delegate method
* calls. May be null.
*/
public AnnotationVisitor(final int api, final AnnotationVisitor annotationVisitor) {
if (api != Opcodes.ASM6
&& api != Opcodes.ASM5
&& api != Opcodes.ASM4
&& api != Opcodes.ASM7_EXPERIMENTAL) {
throw new IllegalArgumentException();
} }
this.api = api;
this.av = annotationVisitor;
}
/** /**
* Constructs a new {@link AnnotationVisitor}. * Visits a primitive value of the annotation.
* *
* @param api * @param name the value name.
* the ASM API version implemented by this visitor. Must be one * @param value the actual value, whose type must be {@link Byte}, {@link Boolean}, {@link
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. * Character}, {@link Short}, {@link Integer} , {@link Long}, {@link Float}, {@link Double},
* @param av * {@link String} or {@link Type} of {@link Type#OBJECT} or {@link Type#ARRAY} sort. This
* the annotation visitor to which this visitor must delegate * value can also be an array of byte, boolean, short, char, int, long, float or double values
* method calls. May be null. * (this is equivalent to using {@link #visitArray} and visiting each array element in turn,
*/ * but is more convenient).
public AnnotationVisitor(final int api, final AnnotationVisitor av) { */
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) { public void visit(final String name, final Object value) {
throw new IllegalArgumentException(); if (av != null) {
} av.visit(name, value);
this.api = api;
this.av = av;
} }
}
/** /**
* Visits a primitive value of the annotation. * Visits an enumeration value of the annotation.
* *
* @param name * @param name the value name.
* the value name. * @param descriptor the class descriptor of the enumeration class.
* @param value * @param value the actual enumeration value.
* the actual value, whose type must be {@link Byte}, */
* {@link Boolean}, {@link Character}, {@link Short}, public void visitEnum(final String name, final String descriptor, final String value) {
* {@link Integer} , {@link Long}, {@link Float}, {@link Double}, if (av != null) {
* {@link String} or {@link Type} of OBJECT or ARRAY sort. This av.visitEnum(name, descriptor, value);
* value can also be an array of byte, boolean, short, char, int,
* long, float or double values (this is equivalent to using
* {@link #visitArray visitArray} and visiting each array element
* in turn, but is more convenient).
*/
public void visit(String name, Object value) {
if (av != null) {
av.visit(name, value);
}
} }
}
/** /**
* Visits an enumeration value of the annotation. * Visits a nested annotation value of the annotation.
* *
* @param name * @param name the value name.
* the value name. * @param descriptor the class descriptor of the nested annotation class.
* @param desc * @return a visitor to visit the actual nested annotation value, or <tt>null</tt> if this visitor
* the class descriptor of the enumeration class. * is not interested in visiting this nested annotation. <i>The nested annotation value must
* @param value * be fully visited before calling other methods on this annotation visitor</i>.
* the actual enumeration value. */
*/ public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
public void visitEnum(String name, String desc, String value) { if (av != null) {
if (av != null) { return av.visitAnnotation(name, descriptor);
av.visitEnum(name, desc, value);
}
} }
return null;
}
/** /**
* Visits a nested annotation value of the annotation. * Visits an array value of the annotation. Note that arrays of primitive types (such as byte,
* * boolean, short, char, int, long, float or double) can be passed as value to {@link #visit
* @param name * visit}. This is what {@link ClassReader} does.
* the value name. *
* @param desc * @param name the value name.
* the class descriptor of the nested annotation class. * @return a visitor to visit the actual array value elements, or <tt>null</tt> if this visitor is
* @return a visitor to visit the actual nested annotation value, or * not interested in visiting these values. The 'name' parameters passed to the methods of
* <tt>null</tt> if this visitor is not interested in visiting this * this visitor are ignored. <i>All the array values must be visited before calling other
* nested annotation. <i>The nested annotation value must be fully * methods on this annotation visitor</i>.
* visited before calling other methods on this annotation */
* visitor</i>. public AnnotationVisitor visitArray(final String name) {
*/ if (av != null) {
public AnnotationVisitor visitAnnotation(String name, String desc) { return av.visitArray(name);
if (av != null) {
return av.visitAnnotation(name, desc);
}
return null;
} }
return null;
}
/** /** Visits the end of the annotation. */
* Visits an array value of the annotation. Note that arrays of primitive public void visitEnd() {
* types (such as byte, boolean, short, char, int, long, float or double) if (av != null) {
* can be passed as value to {@link #visit visit}. This is what av.visitEnd();
* {@link ClassReader} does.
*
* @param name
* the value name.
* @return a visitor to visit the actual array value elements, or
* <tt>null</tt> if this visitor is not interested in visiting these
* values. The 'name' parameters passed to the methods of this
* visitor are ignored. <i>All the array values must be visited
* before calling other methods on this annotation visitor</i>.
*/
public AnnotationVisitor visitArray(String name) {
if (av != null) {
return av.visitArray(name);
}
return null;
}
/**
* Visits the end of the annotation.
*/
public void visitEnd() {
if (av != null) {
av.visitEnd();
}
} }
}
} }

View File

@@ -1,371 +1,418 @@
/*** // ASM: a very small and fast Java bytecode manipulation framework
* ASM: a very small and fast Java bytecode manipulation framework // Copyright (c) 2000-2011 INRIA, France Telecom
* Copyright (c) 2000-2011 INRIA, France Telecom // All rights reserved.
* All rights reserved. //
* // Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions
* modification, are permitted provided that the following conditions // are met:
* are met: // 1. Redistributions of source code must retain the above copyright
* 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer.
* notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright
* 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the
* notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution.
* documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holders nor the names of its
* 3. Neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from
* contributors may be used to endorse or promote products derived from // this software without specific prior written permission.
* this software without specific prior written permission. //
* // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE.
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.springframework.asm; package org.springframework.asm;
/** /**
* An {@link AnnotationVisitor} that generates annotations in bytecode form. * 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 Eric Bruneton
* @author Eugene Kuleshov * @author Eugene Kuleshov
*/ */
final class AnnotationWriter extends AnnotationVisitor { final class AnnotationWriter extends AnnotationVisitor {
/** /** Where the constants used in this AnnotationWriter must be stored. */
* The class writer to which this annotation must be added. private final SymbolTable symbolTable;
*/
private final ClassWriter cw;
/** /**
* The number of values in this annotation. * 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
private int size; * value, instead of an element_name_index followed by an element_value).
*/
private final boolean useNamedValues;
/** /**
* <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation * The 'annotation' or 'type_annotation' JVMS structure corresponding to the annotation values
* writers used for annotation default and annotation arrays use unnamed * visited so far. All the fields of these structures, except the last one - the
* values. * 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
private final boolean named; * #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 annotation values in bytecode form. This byte vector only contains * The offset in {@link #annotation} where {@link #numElementValuePairs} must be stored (or -1 for
* the values themselves, i.e. the number of values must be stored as a * the case of AnnotationDefault attributes).
* unsigned short just before these bytes. */
*/ private final int numElementValuePairsOffset;
private final ByteVector bv;
/** /** The number of element value pairs visited so far. */
* The byte vector to be used to store the number of values of this private int numElementValuePairs;
* annotation. See {@link #bv}.
*/
private final ByteVector parent;
/** /**
* Where the number of values of this annotation must be stored in * The previous AnnotationWriter. This field is used to store the list of annotations of a
* {@link #parent}. * 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 int offset; */
private final AnnotationWriter previousAnnotation;
/** /**
* Next annotation writer. This field is used to store annotation lists. * 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
AnnotationWriter next; * (annotation values of annotation type), or for AnnotationDefault attributes.
*/
private AnnotationWriter nextAnnotation;
/** // -----------------------------------------------------------------------------------------------
* Previous annotation writer. This field is used to store annotation lists. // Constructors
*/ // -----------------------------------------------------------------------------------------------
AnnotationWriter prev;
// ------------------------------------------------------------------------ /**
// Constructor * 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
* Constructs a new {@link AnnotationWriter}. * use unnamed values.
* * @param annotation where the 'annotation' or 'type_annotation' JVMS structure corresponding to
* @param cw * the visited content must be stored. This ByteVector must already contain all the fields of
* the class writer to which this annotation must be added. * the structure except the last one (the element_value_pairs array).
* @param named * @param previousAnnotation the previously visited annotation of the
* <tt>true<tt> if values are named, <tt>false</tt> otherwise. * Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or null in
* @param bv * other cases (e.g. nested or array annotations).
* where the annotation values must be stored. */
* @param parent AnnotationWriter(
* where the number of annotation values must be stored. final SymbolTable symbolTable,
* @param offset final boolean useNamedValues,
* where in <tt>parent</tt> the number of annotation values must final ByteVector annotation,
* be stored. final AnnotationWriter previousAnnotation) {
*/ super(Opcodes.ASM6);
AnnotationWriter(final ClassWriter cw, final boolean named, this.symbolTable = symbolTable;
final ByteVector bv, final ByteVector parent, final int offset) { this.useNamedValues = useNamedValues;
super(Opcodes.ASM6); this.annotation = annotation;
this.cw = cw; // By hypothesis, num_element_value_pairs is stored in the last unsigned short of 'annotation'.
this.named = named; this.numElementValuePairsOffset = annotation.length == 0 ? -1 : annotation.length - 2;
this.bv = bv; this.previousAnnotation = previousAnnotation;
this.parent = parent; if (previousAnnotation != null) {
this.offset = offset; previousAnnotation.nextAnnotation = this;
} }
}
// ------------------------------------------------------------------------ /**
// Implementation of the AnnotationVisitor abstract class * Constructs a new {@link AnnotationWriter} using named values.
// ------------------------------------------------------------------------ *
* @param symbolTable where the constants used in this AnnotationWriter must be stored.
* @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 null in
* other cases (e.g. nested or array annotations).
*/
AnnotationWriter(
final SymbolTable symbolTable,
final ByteVector annotation,
final AnnotationWriter previousAnnotation) {
this(symbolTable, /* useNamedValues = */ true, annotation, previousAnnotation);
}
@Override // -----------------------------------------------------------------------------------------------
public void visit(final String name, final Object value) { // Implementation of the AnnotationVisitor abstract class
++size; // -----------------------------------------------------------------------------------------------
if (named) {
bv.putShort(cw.newUTF8(name)); @Override
} public void visit(final String name, final Object value) {
if (value instanceof String) { // Case of an element_value with a const_value_index, class_info_index or array_index field.
bv.put12('s', cw.newUTF8((String) value)); // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1.
} else if (value instanceof Byte) { ++numElementValuePairs;
bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index); if (useNamedValues) {
} else if (value instanceof Boolean) { annotation.putShort(symbolTable.addConstantUtf8(name));
int v = ((Boolean) value).booleanValue() ? 1 : 0;
bv.put12('Z', cw.newInteger(v).index);
} else if (value instanceof Character) {
bv.put12('C', cw.newInteger(((Character) value).charValue()).index);
} else if (value instanceof Short) {
bv.put12('S', cw.newInteger(((Short) value).shortValue()).index);
} else if (value instanceof Type) {
bv.put12('c', cw.newUTF8(((Type) value).getDescriptor()));
} else if (value instanceof byte[]) {
byte[] v = (byte[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('B', cw.newInteger(v[i]).index);
}
} else if (value instanceof boolean[]) {
boolean[] v = (boolean[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index);
}
} else if (value instanceof short[]) {
short[] v = (short[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('S', cw.newInteger(v[i]).index);
}
} else if (value instanceof char[]) {
char[] v = (char[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('C', cw.newInteger(v[i]).index);
}
} else if (value instanceof int[]) {
int[] v = (int[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('I', cw.newInteger(v[i]).index);
}
} else if (value instanceof long[]) {
long[] v = (long[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('J', cw.newLong(v[i]).index);
}
} else if (value instanceof float[]) {
float[] v = (float[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('F', cw.newFloat(v[i]).index);
}
} else if (value instanceof double[]) {
double[] v = (double[]) value;
bv.put12('[', v.length);
for (int i = 0; i < v.length; i++) {
bv.put12('D', cw.newDouble(v[i]).index);
}
} else {
Item i = cw.newConstItem(value);
bv.put12(".s.IFJDCS".charAt(i.type), i.index);
}
} }
if (value instanceof String) {
@Override annotation.put12('s', symbolTable.addConstantUtf8((String) value));
public void visitEnum(final String name, final String desc, } else if (value instanceof Byte) {
final String value) { annotation.put12('B', symbolTable.addConstantInteger(((Byte) value).byteValue()).index);
++size; } else if (value instanceof Boolean) {
if (named) { int booleanValue = ((Boolean) value).booleanValue() ? 1 : 0;
bv.putShort(cw.newUTF8(name)); annotation.put12('Z', symbolTable.addConstantInteger(booleanValue).index);
} } else if (value instanceof Character) {
bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value)); 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 @Override
public AnnotationVisitor visitAnnotation(final String name, public void visitEnum(final String name, final String descriptor, final String value) {
final String desc) { // Case of an element_value with an enum_const_value field.
++size; // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1.
if (named) { ++numElementValuePairs;
bv.putShort(cw.newUTF8(name)); if (useNamedValues) {
} annotation.putShort(symbolTable.addConstantUtf8(name));
// write tag and type, and reserve space for values count
bv.put12('@', cw.newUTF8(desc)).putShort(0);
return new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
} }
annotation
.put12('e', symbolTable.addConstantUtf8(descriptor))
.putShort(symbolTable.addConstantUtf8(value));
}
@Override @Override
public AnnotationVisitor visitArray(final String name) { public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
++size; // Case of an element_value with an annotation_value field.
if (named) { // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1.
bv.putShort(cw.newUTF8(name)); ++numElementValuePairs;
} if (useNamedValues) {
// write tag, and reserve space for array size annotation.putShort(symbolTable.addConstantUtf8(name));
bv.put12('[', 0);
return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);
} }
// 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, annotation, null);
}
@Override @Override
public void visitEnd() { public AnnotationVisitor visitArray(final String name) {
if (parent != null) { // Case of an element_value with an array_value field.
byte[] data = parent.data; // https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1
data[offset] = (byte) (size >>> 8); ++numElementValuePairs;
data[offset + 1] = (byte) size; 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
// Utility methods public void visitEnd() {
// ------------------------------------------------------------------------ if (numElementValuePairsOffset != -1) {
byte[] data = annotation.data;
/** data[numElementValuePairsOffset] = (byte) (numElementValuePairs >>> 8);
* Returns the size of this annotation writer list. data[numElementValuePairsOffset + 1] = (byte) numElementValuePairs;
*
* @return the size of this annotation writer list.
*/
int getSize() {
int size = 0;
AnnotationWriter aw = this;
while (aw != null) {
size += aw.bv.length;
aw = aw.next;
}
return size;
} }
}
/** // -----------------------------------------------------------------------------------------------
* Puts the annotations of this annotation writer list into the given byte // Utility methods
* vector. // -----------------------------------------------------------------------------------------------
*
* @param out
* where the annotations must be put.
*/
void put(final ByteVector out) {
int n = 0;
int size = 2;
AnnotationWriter aw = this;
AnnotationWriter last = null;
while (aw != null) {
++n;
size += aw.bv.length;
aw.visitEnd(); // in case user forgot to call visitEnd
aw.prev = last;
last = aw;
aw = aw.next;
}
out.putInt(size);
out.putShort(n);
aw = last;
while (aw != null) {
out.putByteArray(aw.bv.data, 0, aw.bv.length);
aw = aw.prev;
}
}
/** /**
* Puts the given annotation lists into the given byte vector. * 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
* @param panns * to the constant pool of the class (if not null).
* an array of annotation writer lists. *
* @param off * @param attributeName one of "Runtime[In]Visible[Type]Annotations", or null.
* index of the first annotation to be written. * @return the size in bytes of a Runtime[In]Visible[Type]Annotations attribute containing this
* @param out * annotation and all its predecessors. This includes the size of the attribute_name_index and
* where the annotations must be put. * attribute_length fields.
*/ */
static void put(final AnnotationWriter[] panns, final int off, int computeAnnotationsSize(final String attributeName) {
final ByteVector out) { if (attributeName != null) {
int size = 1 + 2 * (panns.length - off); symbolTable.addConstantUtf8(attributeName);
for (int i = off; i < panns.length; ++i) {
size += panns[i] == null ? 0 : panns[i].getSize();
}
out.putInt(size).putByte(panns.length - off);
for (int i = off; i < panns.length; ++i) {
AnnotationWriter aw = panns[i];
AnnotationWriter last = null;
int n = 0;
while (aw != null) {
++n;
aw.visitEnd(); // in case user forgot to call visitEnd
aw.prev = last;
last = aw;
aw = aw.next;
}
out.putShort(n);
aw = last;
while (aw != null) {
out.putByteArray(aw.bv.data, 0, aw.bv.length);
aw = aw.prev;
}
}
} }
// 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;
}
/** /**
* Puts the given type reference and type path into the given bytevector. * Puts a Runtime[In]Visible[Type]Annotations attribute containing this annotations and all its
* LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported. * <i>predecessors</i> (see {@link #previousAnnotation} in the given ByteVector. Annotations are
* * put in the same order they have been visited.
* @param typeRef *
* a reference to the annotated type. See {@link TypeReference}. * @param attributeNameIndex the constant pool index of the attribute name (one of
* @param typePath * "Runtime[In]Visible[Type]Annotations").
* the path to the annotated type argument, wildcard bound, array * @param output where the attribute must be put.
* element type, or static inner type within 'typeRef'. May be */
* <tt>null</tt> if the annotation targets 'typeRef' as a whole. void putAnnotations(final int attributeNameIndex, final ByteVector output) {
* @param out int attributeLength = 2; // For num_annotations.
* where the type reference and type path must be put. int numAnnotations = 0;
*/ AnnotationWriter annotationWriter = this;
static void putTarget(int typeRef, TypePath typePath, ByteVector out) { AnnotationWriter firstAnnotation = null;
switch (typeRef >>> 24) { while (annotationWriter != null) {
case 0x00: // CLASS_TYPE_PARAMETER // In case the user forgot to call visitEnd().
case 0x01: // METHOD_TYPE_PARAMETER annotationWriter.visitEnd();
case 0x16: // METHOD_FORMAL_PARAMETER attributeLength += annotationWriter.annotation.length;
out.putShort(typeRef >>> 16); numAnnotations++;
break; firstAnnotation = annotationWriter;
case 0x13: // FIELD annotationWriter = annotationWriter.previousAnnotation;
case 0x14: // METHOD_RETURN
case 0x15: // METHOD_RECEIVER
out.putByte(typeRef >>> 24);
break;
case 0x47: // CAST
case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
out.putInt(typeRef);
break;
// case 0x10: // CLASS_EXTENDS
// case 0x11: // CLASS_TYPE_PARAMETER_BOUND
// case 0x12: // METHOD_TYPE_PARAMETER_BOUND
// case 0x17: // THROWS
// case 0x42: // EXCEPTION_PARAMETER
// case 0x43: // INSTANCEOF
// case 0x44: // NEW
// case 0x45: // CONSTRUCTOR_REFERENCE
// case 0x46: // METHOD_REFERENCE
default:
out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8);
break;
}
if (typePath == null) {
out.putByte(0);
} else {
int length = typePath.b[typePath.offset] * 2 + 1;
out.putByteArray(typePath.b, typePath.offset, length);
}
} }
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;
}
}
/**
* 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.
*
* @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;
}
}
}
} }

View File

@@ -1,255 +1,323 @@
/*** // ASM: a very small and fast Java bytecode manipulation framework
* ASM: a very small and fast Java bytecode manipulation framework // Copyright (c) 2000-2011 INRIA, France Telecom
* Copyright (c) 2000-2011 INRIA, France Telecom // All rights reserved.
* All rights reserved. //
* // Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions
* modification, are permitted provided that the following conditions // are met:
* are met: // 1. Redistributions of source code must retain the above copyright
* 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer.
* notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright
* 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the
* notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution.
* documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holders nor the names of its
* 3. Neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from
* contributors may be used to endorse or promote products derived from // this software without specific prior written permission.
* this software without specific prior written permission. //
* // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE.
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.springframework.asm; package org.springframework.asm;
/** /**
* A non standard class, field, method or code attribute. * A non standard class, field, method or code attribute, as defined in the Java Virtual Machine
* Specification (JVMS).
* *
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7">JVMS
* 4.7</a>
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.3">JVMS
* 4.7.3</a>
* @author Eric Bruneton * @author Eric Bruneton
* @author Eugene Kuleshov * @author Eugene Kuleshov
*/ */
public class Attribute { public class Attribute {
/** /** The type of this attribute, also called its name in the JVMS. */
* The type of this attribute. public final String type;
*/
public final String type;
/** /**
* The raw value of this attribute, used only for unknown attributes. * The raw content of this attribute, only used for unknown attributes (see {@link #isUnknown()}).
*/ * The 6 header bytes of the attribute (attribute_name_index and attribute_length) are <i>not</i>
byte[] value; * included.
*/
private byte[] content;
/** /**
* The next attribute in this attribute list. May be <tt>null</tt>. * The next attribute in this attribute list (Attribute instances can be linked via this field to
*/ * store a list of class, field, method or code attributes). May be <tt>null</tt>.
Attribute next; */
Attribute nextAttribute;
/** /**
* Constructs a new empty attribute. * Constructs a new empty attribute.
* *
* @param type * @param type the type of the attribute.
* the type of the attribute. */
*/ protected Attribute(final String type) {
protected Attribute(final String type) { this.type = type;
this.type = type; }
/**
* Returns <tt>true</tt> if this type of attribute is unknown. This means that the attribute
* content can't be parsed to extract constant pool references, labels, etc. Instead, the
* attribute content is read as an opaque byte array, and written back as is. This can lead to
* invalid attributes, if the content actually contains constant pool references, labels, or other
* symbolic references that need to be updated when there are changes to the constant pool, the
* method bytecode, etc. The default implementation of this method always returns <tt>true</tt>.
*
* @return <tt>true</tt> if this type of attribute is unknown.
*/
public boolean isUnknown() {
return true;
}
/**
* Returns <tt>true</tt> if this type of attribute is a code attribute.
*
* @return <tt>true</tt> if this type of attribute is a code attribute.
*/
public boolean isCodeAttribute() {
return false;
}
/**
* Returns the labels corresponding to this attribute.
*
* @return the labels corresponding to this attribute, or <tt>null</tt> if this attribute is not a
* code attribute that contains labels.
*/
protected Label[] getLabels() {
return new Label[0];
}
/**
* Reads a {@link #type} attribute. This method must return a <i>new</i> {@link Attribute} object,
* of type {@link #type}, corresponding to the 'length' bytes starting at 'offset', in the given
* ClassReader.
*
* @param classReader the class that contains the attribute to be read.
* @param offset index of the first byte of the attribute's content in {@link ClassReader#b}. The
* 6 attribute header bytes (attribute_name_index and attribute_length) are not taken into
* account here.
* @param length the length of the attribute's content (excluding the 6 attribute header bytes).
* @param charBuffer the buffer to be used to call the ClassReader methods requiring a
* 'charBuffer' parameter.
* @param codeAttributeOffset index of the first byte of content of the enclosing Code attribute
* in {@link ClassReader#b}, or -1 if the attribute to be read is not a code attribute. The 6
* attribute header bytes (attribute_name_index and attribute_length) are not taken into
* account here.
* @param labels the labels of the method's code, or <tt>null</tt> if the attribute to be read is
* not a code attribute.
* @return a <i>new</i> {@link Attribute} object corresponding to the specified bytes.
*/
protected Attribute read(
final ClassReader classReader,
final int offset,
final int length,
final char[] charBuffer,
final int codeAttributeOffset,
final Label[] labels) {
Attribute attribute = new Attribute(type);
attribute.content = new byte[length];
System.arraycopy(classReader.b, offset, attribute.content, 0, length);
return attribute;
}
/**
* Returns the byte array form of the content of this attribute. The 6 header bytes
* (attribute_name_index and attribute_length) must <i>not</i> be added in the returned
* ByteVector.
*
* @param classWriter the class to which this attribute must be added. This parameter can be used
* to add the items that corresponds to this attribute to the constant pool of this class.
* @param code the bytecode of the method corresponding to this code attribute, or <tt>null</tt>
* if this attribute is not a code attribute. Corresponds to the 'code' field of the Code
* attribute.
* @param codeLength the length of the bytecode of the method corresponding to this code
* attribute, or 0 if this attribute is not a code attribute. Corresponds to the 'code_length'
* field of the Code attribute.
* @param maxStack the maximum stack size of the method corresponding to this code attribute, or
* -1 if this attribute is not a code attribute.
* @param maxLocals the maximum number of local variables of the method corresponding to this code
* attribute, or -1 if this attribute is not a code attribute.
* @return the byte array form of this attribute.
*/
protected ByteVector write(
final ClassWriter classWriter,
final byte[] code,
final int codeLength,
final int maxStack,
final int maxLocals) {
return new ByteVector(content);
}
/**
* Returns the number of attributes of the attribute list that begins with this attribute.
*
* @return the number of attributes of the attribute list that begins with this attribute.
*/
final int getAttributeCount() {
int count = 0;
Attribute attribute = this;
while (attribute != null) {
count += 1;
attribute = attribute.nextAttribute;
} }
return count;
}
/** /**
* Returns <tt>true</tt> if this type of attribute is unknown. The default * Returns the total size in bytes of all the attributes in the attribute list that begins with
* implementation of this method always returns <tt>true</tt>. * this attribute. This size includes the 6 header bytes (attribute_name_index and
* * attribute_length) per attribute. Also adds the attribute type names to the constant pool.
* @return <tt>true</tt> if this type of attribute is unknown. *
*/ * @param symbolTable where the constants used in the attributes must be stored.
public boolean isUnknown() { * @return the size of all the attributes in this attribute list. This size includes the size of
return true; * the attribute headers.
*/
final int computeAttributesSize(final SymbolTable symbolTable) {
final byte[] code = null;
final int codeLength = 0;
final int maxStack = -1;
final int maxLocals = -1;
return computeAttributesSize(symbolTable, code, codeLength, maxStack, maxLocals);
}
/**
* Returns the total size in bytes of all the attributes in the attribute list that begins with
* this attribute. This size includes the 6 header bytes (attribute_name_index and
* attribute_length) per attribute. Also adds the attribute type names to the constant pool.
*
* @param symbolTable where the constants used in the attributes must be stored.
* @param code the bytecode of the method corresponding to these code attributes, or <tt>null</tt>
* if they are not code attributes. Corresponds to the 'code' field of the Code attribute.
* @param codeLength the length of the bytecode of the method corresponding to these code
* attributes, or 0 if they are not code attributes. Corresponds to the 'code_length' field of
* the Code attribute.
* @param maxStack the maximum stack size of the method corresponding to these code attributes, or
* -1 if they are not code attributes.
* @param maxLocals the maximum number of local variables of the method corresponding to these
* code attributes, or -1 if they are not code attribute.
* @return the size of all the attributes in this attribute list. This size includes the size of
* the attribute headers.
*/
final int computeAttributesSize(
final SymbolTable symbolTable,
final byte[] code,
final int codeLength,
final int maxStack,
final int maxLocals) {
final ClassWriter classWriter = symbolTable.classWriter;
int size = 0;
Attribute attribute = this;
while (attribute != null) {
symbolTable.addConstantUtf8(attribute.type);
size += 6 + attribute.write(classWriter, code, codeLength, maxStack, maxLocals).length;
attribute = attribute.nextAttribute;
} }
return size;
}
/** /**
* Returns <tt>true</tt> if this type of attribute is a code attribute. * Puts all the attributes of the attribute list that begins with this attribute, in the given
* * byte vector. This includes the 6 header bytes (attribute_name_index and attribute_length) per
* @return <tt>true</tt> if this type of attribute is a code attribute. * attribute.
*/ *
public boolean isCodeAttribute() { * @param symbolTable where the constants used in the attributes must be stored.
return false; * @param output where the attributes must be written.
*/
final void putAttributes(final SymbolTable symbolTable, final ByteVector output) {
final byte[] code = null;
final int codeLength = 0;
final int maxStack = -1;
final int maxLocals = -1;
putAttributes(symbolTable, code, codeLength, maxStack, maxLocals, output);
}
/**
* Puts all the attributes of the attribute list that begins with this attribute, in the given
* byte vector. This includes the 6 header bytes (attribute_name_index and attribute_length) per
* attribute.
*
* @param symbolTable where the constants used in the attributes must be stored.
* @param code the bytecode of the method corresponding to these code attributes, or <tt>null</tt>
* if they are not code attributes. Corresponds to the 'code' field of the Code attribute.
* @param codeLength the length of the bytecode of the method corresponding to these code
* attributes, or 0 if they are not code attributes. Corresponds to the 'code_length' field of
* the Code attribute.
* @param maxStack the maximum stack size of the method corresponding to these code attributes, or
* -1 if they are not code attributes.
* @param maxLocals the maximum number of local variables of the method corresponding to these
* code attributes, or -1 if they are not code attribute.
* @param output where the attributes must be written.
*/
final void putAttributes(
final SymbolTable symbolTable,
final byte[] code,
final int codeLength,
final int maxStack,
final int maxLocals,
final ByteVector output) {
final ClassWriter classWriter = symbolTable.classWriter;
Attribute attribute = this;
while (attribute != null) {
ByteVector attributeContent =
attribute.write(classWriter, code, codeLength, maxStack, maxLocals);
// Put attribute_name_index and attribute_length.
output.putShort(symbolTable.addConstantUtf8(attribute.type)).putInt(attributeContent.length);
output.putByteArray(attributeContent.data, 0, attributeContent.length);
attribute = attribute.nextAttribute;
} }
}
/** /** A set of attribute prototypes (attributes with the same type are considered equal). */
* Returns the labels corresponding to this attribute. static final class Set {
*
* @return the labels corresponding to this attribute, or <tt>null</tt> if
* this attribute is not a code attribute that contains labels.
*/
protected Label[] getLabels() {
return null;
}
/** private static final int SIZE_INCREMENT = 6;
* Reads a {@link #type type} attribute. This method must return a
* <i>new</i> {@link Attribute} object, of type {@link #type type},
* corresponding to the <tt>len</tt> bytes starting at the given offset, in
* the given class reader.
*
* @param cr
* the class that contains the attribute to be read.
* @param off
* index of the first byte of the attribute's content in
* {@link ClassReader#b cr.b}. The 6 attribute header bytes,
* containing the type and the length of the attribute, are not
* taken into account here.
* @param len
* the length of the attribute's content.
* @param buf
* buffer to be used to call {@link ClassReader#readUTF8
* readUTF8}, {@link ClassReader#readClass(int,char[]) readClass}
* or {@link ClassReader#readConst readConst}.
* @param codeOff
* index of the first byte of code's attribute content in
* {@link ClassReader#b cr.b}, or -1 if the attribute to be read
* is not a code attribute. The 6 attribute header bytes,
* containing the type and the length of the attribute, are not
* taken into account here.
* @param labels
* the labels of the method's code, or <tt>null</tt> if the
* attribute to be read is not a code attribute.
* @return a <i>new</i> {@link Attribute} object corresponding to the given
* bytes.
*/
protected Attribute read(final ClassReader cr, final int off,
final int len, final char[] buf, final int codeOff,
final Label[] labels) {
Attribute attr = new Attribute(type);
attr.value = new byte[len];
System.arraycopy(cr.b, off, attr.value, 0, len);
return attr;
}
/** private int size;
* Returns the byte array form of this attribute. private Attribute[] data = new Attribute[SIZE_INCREMENT];
*
* @param cw
* the class to which this attribute must be added. This
* parameter can be used to add to the constant pool of this
* class the items that corresponds to this attribute.
* @param code
* the bytecode of the method corresponding to this code
* attribute, or <tt>null</tt> if this attribute is not a code
* attributes.
* @param len
* the length of the bytecode of the method corresponding to this
* code attribute, or <tt>null</tt> if this attribute is not a
* code attribute.
* @param maxStack
* the maximum stack size of the method corresponding to this
* code attribute, or -1 if this attribute is not a code
* attribute.
* @param maxLocals
* the maximum number of local variables of the method
* corresponding to this code attribute, or -1 if this attribute
* is not a code attribute.
* @return the byte array form of this attribute.
*/
protected ByteVector write(final ClassWriter cw, final byte[] code,
final int len, final int maxStack, final int maxLocals) {
ByteVector v = new ByteVector();
v.data = value;
v.length = value.length;
return v;
}
/** void addAttributes(final Attribute attributeList) {
* Returns the length of the attribute list that begins with this attribute. Attribute attribute = attributeList;
* while (attribute != null) {
* @return the length of the attribute list that begins with this attribute. if (!contains(attribute)) {
*/ add(attribute);
final int getCount() {
int count = 0;
Attribute attr = this;
while (attr != null) {
count += 1;
attr = attr.next;
} }
return count; attribute = attribute.nextAttribute;
}
} }
/** Attribute[] toArray() {
* Returns the size of all the attributes in this attribute list. Attribute[] result = new Attribute[size];
* System.arraycopy(data, 0, result, 0, size);
* @param cw return result;
* the class writer to be used to convert the attributes into
* byte arrays, with the {@link #write write} method.
* @param code
* the bytecode of the method corresponding to these code
* attributes, or <tt>null</tt> if these attributes are not code
* attributes.
* @param len
* the length of the bytecode of the method corresponding to
* these code attributes, or <tt>null</tt> if these attributes
* are not code attributes.
* @param maxStack
* the maximum stack size of the method corresponding to these
* code attributes, or -1 if these attributes are not code
* attributes.
* @param maxLocals
* the maximum number of local variables of the method
* corresponding to these code attributes, or -1 if these
* attributes are not code attributes.
* @return the size of all the attributes in this attribute list. This size
* includes the size of the attribute headers.
*/
final int getSize(final ClassWriter cw, final byte[] code, final int len,
final int maxStack, final int maxLocals) {
Attribute attr = this;
int size = 0;
while (attr != null) {
cw.newUTF8(attr.type);
size += attr.write(cw, code, len, maxStack, maxLocals).length + 6;
attr = attr.next;
}
return size;
} }
/** private boolean contains(final Attribute attribute) {
* Writes all the attributes of this attribute list in the given byte for (int i = 0; i < size; ++i) {
* vector. if (data[i].type.equals(attribute.type)) {
* return true;
* @param cw
* the class writer to be used to convert the attributes into
* byte arrays, with the {@link #write write} method.
* @param code
* the bytecode of the method corresponding to these code
* attributes, or <tt>null</tt> if these attributes are not code
* attributes.
* @param len
* the length of the bytecode of the method corresponding to
* these code attributes, or <tt>null</tt> if these attributes
* are not code attributes.
* @param maxStack
* the maximum stack size of the method corresponding to these
* code attributes, or -1 if these attributes are not code
* attributes.
* @param maxLocals
* the maximum number of local variables of the method
* corresponding to these code attributes, or -1 if these
* attributes are not code attributes.
* @param out
* where the attributes must be written.
*/
final void put(final ClassWriter cw, final byte[] code, final int len,
final int maxStack, final int maxLocals, final ByteVector out) {
Attribute attr = this;
while (attr != null) {
ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
out.putShort(cw.newUTF8(attr.type)).putInt(b.length);
out.putByteArray(b.data, 0, b.length);
attr = attr.next;
} }
}
return false;
} }
private void add(final Attribute attribute) {
if (size >= data.length) {
Attribute[] newData = new Attribute[data.length + SIZE_INCREMENT];
System.arraycopy(data, 0, newData, 0, size);
data = newData;
}
data[size++] = attribute;
}
}
} }

View File

@@ -1,339 +1,360 @@
/*** // ASM: a very small and fast Java bytecode manipulation framework
* ASM: a very small and fast Java bytecode manipulation framework // Copyright (c) 2000-2011 INRIA, France Telecom
* Copyright (c) 2000-2011 INRIA, France Telecom // All rights reserved.
* All rights reserved. //
* // Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions
* modification, are permitted provided that the following conditions // are met:
* are met: // 1. Redistributions of source code must retain the above copyright
* 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer.
* notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright
* 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the
* notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution.
* documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holders nor the names of its
* 3. Neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from
* contributors may be used to endorse or promote products derived from // this software without specific prior written permission.
* this software without specific prior written permission. //
* // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE.
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.springframework.asm; package org.springframework.asm;
/** /**
* A dynamically extensible vector of bytes. This class is roughly equivalent to * A dynamically extensible vector of bytes. This class is roughly equivalent to a DataOutputStream
* a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient. * on top of a ByteArrayOutputStream, but is more efficient.
* *
* @author Eric Bruneton * @author Eric Bruneton
*/ */
public class ByteVector { public class ByteVector {
/** /** The content of this vector. Only the first {@link #length} bytes contain real data. */
* The content of this vector. byte[] data;
*/
byte[] data;
/** /** The actual number of bytes in this vector. */
* Actual number of bytes in this vector. int length;
*/
int length;
/** /** Constructs a new {@link ByteVector} with a default initial capacity. */
* Constructs a new {@link ByteVector ByteVector} with a default initial public ByteVector() {
* size. data = new byte[64];
*/ }
public ByteVector() {
data = new byte[64]; /**
* Constructs a new {@link ByteVector} with the given initial capacity.
*
* @param initialCapacity the initial capacity of the byte vector to be constructed.
*/
public ByteVector(final int initialCapacity) {
data = new byte[initialCapacity];
}
/**
* Constructs a new {@link ByteVector} from the given initial data.
*
* @param data the initial data of the new byte vector.
*/
ByteVector(final byte[] data) {
this.data = data;
this.length = data.length;
}
/**
* Puts a byte into this byte vector. The byte vector is automatically enlarged if necessary.
*
* @param byteValue a byte.
* @return this byte vector.
*/
public ByteVector putByte(final int byteValue) {
int currentLength = length;
if (currentLength + 1 > data.length) {
enlarge(1);
} }
data[currentLength++] = (byte) byteValue;
length = currentLength;
return this;
}
/** /**
* Constructs a new {@link ByteVector ByteVector} with the given initial * Puts two bytes into this byte vector. The byte vector is automatically enlarged if necessary.
* size. *
* * @param byteValue1 a byte.
* @param initialSize * @param byteValue2 another byte.
* the initial size of the byte vector to be constructed. * @return this byte vector.
*/ */
public ByteVector(final int initialSize) { final ByteVector put11(final int byteValue1, final int byteValue2) {
data = new byte[initialSize]; int currentLength = length;
if (currentLength + 2 > data.length) {
enlarge(2);
} }
byte[] currentData = data;
currentData[currentLength++] = (byte) byteValue1;
currentData[currentLength++] = (byte) byteValue2;
length = currentLength;
return this;
}
/** /**
* Puts a byte into this byte vector. The byte vector is automatically * Puts a short into this byte vector. The byte vector is automatically enlarged if necessary.
* enlarged if necessary. *
* * @param shortValue a short.
* @param b * @return this byte vector.
* a byte. */
* @return this byte vector. public ByteVector putShort(final int shortValue) {
*/ int currentLength = length;
public ByteVector putByte(final int b) { if (currentLength + 2 > data.length) {
int length = this.length; enlarge(2);
if (length + 1 > data.length) {
enlarge(1);
}
data[length++] = (byte) b;
this.length = length;
return this;
} }
byte[] currentData = data;
currentData[currentLength++] = (byte) (shortValue >>> 8);
currentData[currentLength++] = (byte) shortValue;
length = currentLength;
return this;
}
/** /**
* Puts two bytes into this byte vector. The byte vector is automatically * Puts a byte and a short into this byte vector. The byte vector is automatically enlarged if
* enlarged if necessary. * necessary.
* *
* @param b1 * @param byteValue a byte.
* a byte. * @param shortValue a short.
* @param b2 * @return this byte vector.
* another byte. */
* @return this byte vector. final ByteVector put12(final int byteValue, final int shortValue) {
*/ int currentLength = length;
ByteVector put11(final int b1, final int b2) { if (currentLength + 3 > data.length) {
int length = this.length; enlarge(3);
if (length + 2 > data.length) {
enlarge(2);
}
byte[] data = this.data;
data[length++] = (byte) b1;
data[length++] = (byte) b2;
this.length = length;
return this;
} }
byte[] currentData = data;
currentData[currentLength++] = (byte) byteValue;
currentData[currentLength++] = (byte) (shortValue >>> 8);
currentData[currentLength++] = (byte) shortValue;
length = currentLength;
return this;
}
/** /**
* Puts a short into this byte vector. The byte vector is automatically * Puts two bytes and a short into this byte vector. The byte vector is automatically enlarged if
* enlarged if necessary. * necessary.
* *
* @param s * @param byteValue1 a byte.
* a short. * @param byteValue2 another byte.
* @return this byte vector. * @param shortValue a short.
*/ * @return this byte vector.
public ByteVector putShort(final int s) { */
int length = this.length; final ByteVector put112(final int byteValue1, final int byteValue2, final int shortValue) {
if (length + 2 > data.length) { int currentLength = length;
enlarge(2); if (currentLength + 4 > data.length) {
} enlarge(4);
byte[] data = this.data;
data[length++] = (byte) (s >>> 8);
data[length++] = (byte) s;
this.length = length;
return this;
} }
byte[] currentData = data;
currentData[currentLength++] = (byte) byteValue1;
currentData[currentLength++] = (byte) byteValue2;
currentData[currentLength++] = (byte) (shortValue >>> 8);
currentData[currentLength++] = (byte) shortValue;
length = currentLength;
return this;
}
/** /**
* Puts a byte and a short into this byte vector. The byte vector is * Puts an int into this byte vector. The byte vector is automatically enlarged if necessary.
* automatically enlarged if necessary. *
* * @param intValue an int.
* @param b * @return this byte vector.
* a byte. */
* @param s public ByteVector putInt(final int intValue) {
* a short. int currentLength = length;
* @return this byte vector. if (currentLength + 4 > data.length) {
*/ enlarge(4);
ByteVector put12(final int b, final int s) {
int length = this.length;
if (length + 3 > data.length) {
enlarge(3);
}
byte[] data = this.data;
data[length++] = (byte) b;
data[length++] = (byte) (s >>> 8);
data[length++] = (byte) s;
this.length = length;
return this;
} }
byte[] currentData = data;
currentData[currentLength++] = (byte) (intValue >>> 24);
currentData[currentLength++] = (byte) (intValue >>> 16);
currentData[currentLength++] = (byte) (intValue >>> 8);
currentData[currentLength++] = (byte) intValue;
length = currentLength;
return this;
}
/** /**
* Puts an int into this byte vector. The byte vector is automatically * Puts one byte and two shorts into this byte vector. The byte vector is automatically enlarged
* enlarged if necessary. * if necessary.
* *
* @param i * @param byteValue a byte.
* an int. * @param shortValue1 a short.
* @return this byte vector. * @param shortValue2 another short.
*/ * @return this byte vector.
public ByteVector putInt(final int i) { */
int length = this.length; final ByteVector put122(final int byteValue, final int shortValue1, final int shortValue2) {
if (length + 4 > data.length) { int currentLength = length;
enlarge(4); if (currentLength + 5 > data.length) {
} enlarge(5);
byte[] data = this.data;
data[length++] = (byte) (i >>> 24);
data[length++] = (byte) (i >>> 16);
data[length++] = (byte) (i >>> 8);
data[length++] = (byte) i;
this.length = length;
return this;
} }
byte[] currentData = data;
currentData[currentLength++] = (byte) byteValue;
currentData[currentLength++] = (byte) (shortValue1 >>> 8);
currentData[currentLength++] = (byte) shortValue1;
currentData[currentLength++] = (byte) (shortValue2 >>> 8);
currentData[currentLength++] = (byte) shortValue2;
length = currentLength;
return this;
}
/** /**
* Puts a long into this byte vector. The byte vector is automatically * Puts a long into this byte vector. The byte vector is automatically enlarged if necessary.
* enlarged if necessary. *
* * @param longValue a long.
* @param l * @return this byte vector.
* a long. */
* @return this byte vector. public ByteVector putLong(final long longValue) {
*/ int currentLength = length;
public ByteVector putLong(final long l) { if (currentLength + 8 > data.length) {
int length = this.length; enlarge(8);
if (length + 8 > data.length) {
enlarge(8);
}
byte[] data = this.data;
int i = (int) (l >>> 32);
data[length++] = (byte) (i >>> 24);
data[length++] = (byte) (i >>> 16);
data[length++] = (byte) (i >>> 8);
data[length++] = (byte) i;
i = (int) l;
data[length++] = (byte) (i >>> 24);
data[length++] = (byte) (i >>> 16);
data[length++] = (byte) (i >>> 8);
data[length++] = (byte) i;
this.length = length;
return this;
} }
byte[] currentData = data;
int intValue = (int) (longValue >>> 32);
currentData[currentLength++] = (byte) (intValue >>> 24);
currentData[currentLength++] = (byte) (intValue >>> 16);
currentData[currentLength++] = (byte) (intValue >>> 8);
currentData[currentLength++] = (byte) intValue;
intValue = (int) longValue;
currentData[currentLength++] = (byte) (intValue >>> 24);
currentData[currentLength++] = (byte) (intValue >>> 16);
currentData[currentLength++] = (byte) (intValue >>> 8);
currentData[currentLength++] = (byte) intValue;
length = currentLength;
return this;
}
/** /**
* Puts an UTF8 string into this byte vector. The byte vector is * Puts an UTF8 string into this byte vector. The byte vector is automatically enlarged if
* automatically enlarged if necessary. * necessary.
* *
* @param s * @param stringValue a String whose UTF8 encoded length must be less than 65536.
* a String whose UTF8 encoded length must be less than 65536. * @return this byte vector.
* @return this byte vector. */
*/ public ByteVector putUTF8(final String stringValue) {
public ByteVector putUTF8(final String s) { int charLength = stringValue.length();
int charLength = s.length(); if (charLength > 65535) {
if (charLength > 65535) { throw new IllegalArgumentException("UTF8 string too large");
throw new IllegalArgumentException();
}
int len = length;
if (len + 2 + charLength > data.length) {
enlarge(2 + charLength);
}
byte[] data = this.data;
// optimistic algorithm: instead of computing the byte length and then
// serializing the string (which requires two loops), we assume the byte
// length is equal to char length (which is the most frequent case), and
// we start serializing the string right away. During the serialization,
// if we find that this assumption is wrong, we continue with the
// general method.
data[len++] = (byte) (charLength >>> 8);
data[len++] = (byte) charLength;
for (int i = 0; i < charLength; ++i) {
char c = s.charAt(i);
if (c >= '\001' && c <= '\177') {
data[len++] = (byte) c;
} else {
length = len;
return encodeUTF8(s, i, 65535);
}
}
length = len;
return this;
} }
int currentLength = length;
if (currentLength + 2 + charLength > data.length) {
enlarge(2 + charLength);
}
byte[] currentData = data;
// Optimistic algorithm: instead of computing the byte length and then serializing the string
// (which requires two loops), we assume the byte length is equal to char length (which is the
// most frequent case), and we start serializing the string right away. During the
// serialization, if we find that this assumption is wrong, we continue with the general method.
currentData[currentLength++] = (byte) (charLength >>> 8);
currentData[currentLength++] = (byte) charLength;
for (int i = 0; i < charLength; ++i) {
char charValue = stringValue.charAt(i);
if (charValue >= '\u0001' && charValue <= '\u007F') {
currentData[currentLength++] = (byte) charValue;
} else {
length = currentLength;
return encodeUTF8(stringValue, i, 65535);
}
}
length = currentLength;
return this;
}
/** /**
* Puts an UTF8 string into this byte vector. The byte vector is * Puts an UTF8 string into this byte vector. The byte vector is automatically enlarged if
* automatically enlarged if necessary. The string length is encoded in two * necessary. The string length is encoded in two bytes before the encoded characters, if there is
* bytes before the encoded characters, if there is space for that (i.e. if * space for that (i.e. if this.length - offset - 2 &gt;= 0).
* this.length - i - 2 >= 0). *
* * @param stringValue the String to encode.
* @param s * @param offset the index of the first character to encode. The previous characters are supposed
* the String to encode. * to have already been encoded, using only one byte per character.
* @param i * @param maxByteLength the maximum byte length of the encoded string, including the already
* the index of the first character to encode. The previous * encoded characters.
* characters are supposed to have already been encoded, using * @return this byte vector.
* only one byte per character. */
* @param maxByteLength final ByteVector encodeUTF8(final String stringValue, final int offset, final int maxByteLength) {
* the maximum byte length of the encoded string, including the int charLength = stringValue.length();
* already encoded characters. int byteLength = offset;
* @return this byte vector. for (int i = offset; i < charLength; ++i) {
*/ char charValue = stringValue.charAt(i);
ByteVector encodeUTF8(final String s, int i, int maxByteLength) { if (charValue >= '\u0001' && charValue <= '\u007F') {
int charLength = s.length(); byteLength++;
int byteLength = i; } else if (charValue <= '\u07FF') {
char c; byteLength += 2;
for (int j = i; j < charLength; ++j) { } else {
c = s.charAt(j); byteLength += 3;
if (c >= '\001' && c <= '\177') { }
byteLength++;
} else if (c > '\u07FF') {
byteLength += 3;
} else {
byteLength += 2;
}
}
if (byteLength > maxByteLength) {
throw new IllegalArgumentException();
}
int start = length - i - 2;
if (start >= 0) {
data[start] = (byte) (byteLength >>> 8);
data[start + 1] = (byte) byteLength;
}
if (length + byteLength - i > data.length) {
enlarge(byteLength - i);
}
int len = length;
for (int j = i; j < charLength; ++j) {
c = s.charAt(j);
if (c >= '\001' && c <= '\177') {
data[len++] = (byte) c;
} else if (c > '\u07FF') {
data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
data[len++] = (byte) (0x80 | c & 0x3F);
} else {
data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
data[len++] = (byte) (0x80 | c & 0x3F);
}
}
length = len;
return this;
} }
if (byteLength > maxByteLength) {
throw new IllegalArgumentException("UTF8 string too large");
}
// Compute where 'byteLength' must be stored in 'data', and store it at this location.
int byteLengthOffset = length - offset - 2;
if (byteLengthOffset >= 0) {
data[byteLengthOffset] = (byte) (byteLength >>> 8);
data[byteLengthOffset + 1] = (byte) byteLength;
}
if (length + byteLength - offset > data.length) {
enlarge(byteLength - offset);
}
int currentLength = length;
for (int i = offset; i < charLength; ++i) {
char charValue = stringValue.charAt(i);
if (charValue >= '\u0001' && charValue <= '\u007F') {
data[currentLength++] = (byte) charValue;
} else if (charValue <= '\u07FF') {
data[currentLength++] = (byte) (0xC0 | charValue >> 6 & 0x1F);
data[currentLength++] = (byte) (0x80 | charValue & 0x3F);
} else {
data[currentLength++] = (byte) (0xE0 | charValue >> 12 & 0xF);
data[currentLength++] = (byte) (0x80 | charValue >> 6 & 0x3F);
data[currentLength++] = (byte) (0x80 | charValue & 0x3F);
}
}
length = currentLength;
return this;
}
/** /**
* Puts an array of bytes into this byte vector. The byte vector is * Puts an array of bytes into this byte vector. The byte vector is automatically enlarged if
* automatically enlarged if necessary. * necessary.
* *
* @param b * @param byteArrayValue an array of bytes. May be <tt>null</tt> to put <tt>byteLength</tt> null
* an array of bytes. May be <tt>null</tt> to put <tt>len</tt> * bytes into this byte vector.
* null bytes into this byte vector. * @param byteOffset index of the first byte of byteArrayValue that must be copied.
* @param off * @param byteLength number of bytes of byteArrayValue that must be copied.
* index of the fist byte of b that must be copied. * @return this byte vector.
* @param len */
* number of bytes of b that must be copied. public ByteVector putByteArray(
* @return this byte vector. final byte[] byteArrayValue, final int byteOffset, final int byteLength) {
*/ if (length + byteLength > data.length) {
public ByteVector putByteArray(final byte[] b, final int off, final int len) { enlarge(byteLength);
if (length + len > data.length) {
enlarge(len);
}
if (b != null) {
System.arraycopy(b, off, data, length, len);
}
length += len;
return this;
} }
if (byteArrayValue != null) {
System.arraycopy(byteArrayValue, byteOffset, data, length, byteLength);
}
length += byteLength;
return this;
}
/** /**
* Enlarge this byte vector so that it can receive n more bytes. * Enlarges this byte vector so that it can receive 'size' more bytes.
* *
* @param size * @param size number of additional bytes that this byte vector should be able to receive.
* number of additional bytes that this byte vector should be */
* able to receive. private void enlarge(final int size) {
*/ int doubleCapacity = 2 * data.length;
private void enlarge(final int size) { int minimalCapacity = length + size;
int length1 = 2 * data.length; byte[] newData = new byte[doubleCapacity > minimalCapacity ? doubleCapacity : minimalCapacity];
int length2 = length + size; System.arraycopy(data, 0, newData, 0, length);
byte[] newData = new byte[length1 > length2 ? length1 : length2]; data = newData;
System.arraycopy(data, 0, newData, 0, length); }
data = newData;
}
} }

View File

@@ -1,344 +1,337 @@
/*** // ASM: a very small and fast Java bytecode manipulation framework
* ASM: a very small and fast Java bytecode manipulation framework // Copyright (c) 2000-2011 INRIA, France Telecom
* Copyright (c) 2000-2011 INRIA, France Telecom // All rights reserved.
* All rights reserved. //
* // Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions
* modification, are permitted provided that the following conditions // are met:
* are met: // 1. Redistributions of source code must retain the above copyright
* 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer.
* notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright
* 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the
* notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution.
* documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holders nor the names of its
* 3. Neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from
* contributors may be used to endorse or promote products derived from // this software without specific prior written permission.
* this software without specific prior written permission. //
* // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE.
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.springframework.asm; package org.springframework.asm;
/** /**
* A visitor to visit a Java class. The methods of this class must be called in * A visitor to visit a Java class. The methods of this class must be called in the following order:
* the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [ * <tt>visit</tt> [ <tt>visitSource</tt> ] [ <tt>visitModule</tt> ][ <tt>visitNestHost</tt> ][
* <tt>visitModule</tt> ][ <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> | * <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> | <tt>visitTypeAnnotation</tt> |
* <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* ( * <tt>visitAttribute</tt> )* ( <tt>visitNestMember</tt> | <tt>visitInnerClass</tt> |
* <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )* * <tt>visitField</tt> | <tt>visitMethod</tt> )* <tt>visitEnd</tt>.
* <tt>visitEnd</tt>.
* *
* @author Eric Bruneton * @author Eric Bruneton
*/ */
public abstract class ClassVisitor { public abstract class ClassVisitor {
/** /**
* The ASM API version implemented by this visitor. The value of this field * The ASM API version implemented by this visitor. The value of this field must be one of {@link
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7_EXPERIMENTAL}.
*/ */
protected final int api; protected final int api;
/** /** The class visitor to which this visitor must delegate method calls. May be null. */
* The class visitor to which this visitor must delegate method calls. May protected ClassVisitor cv;
* be null.
*/
protected ClassVisitor cv;
/** /**
* Constructs a new {@link ClassVisitor}. * Constructs a new {@link ClassVisitor}.
* *
* @param api * @param api the ASM API version implemented by this visitor. Must be one of {@link
* the ASM API version implemented by this visitor. Must be one * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. * Opcodes#ASM7_EXPERIMENTAL}.
*/ */
public ClassVisitor(final int api) { public ClassVisitor(final int api) {
this(api, null); this(api, null);
}
/**
* Constructs a new {@link ClassVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be one of {@link
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link
* Opcodes#ASM7_EXPERIMENTAL}.
* @param classVisitor the class visitor to which this visitor must delegate method calls. May be
* null.
*/
public ClassVisitor(final int api, final ClassVisitor classVisitor) {
if (api != Opcodes.ASM6
&& api != Opcodes.ASM5
&& api != Opcodes.ASM4
&& api != Opcodes.ASM7_EXPERIMENTAL) {
throw new IllegalArgumentException();
} }
this.api = api;
this.cv = classVisitor;
}
/** /**
* Constructs a new {@link ClassVisitor}. * Visits the header of the class.
* *
* @param api * @param version the class version. The minor version is stored in the 16 most significant bits,
* the ASM API version implemented by this visitor. Must be one * and the major version in the 16 least significant bits.
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. * @param access the class's access flags (see {@link Opcodes}). This parameter also indicates if
* @param cv * the class is deprecated.
* the class visitor to which this visitor must delegate method * @param name the internal name of the class (see {@link Type#getInternalName()}).
* calls. May be null. * @param signature the signature of this class. May be <tt>null</tt> if the class is not a
*/ * generic one, and does not extend or implement generic classes or interfaces.
public ClassVisitor(final int api, final ClassVisitor cv) { * @param superName the internal of name of the super class (see {@link Type#getInternalName()}).
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) { * For interfaces, the super class is {@link Object}. May be <tt>null</tt>, but only for the
throw new IllegalArgumentException(); * {@link Object} class.
} * @param interfaces the internal names of the class's interfaces (see {@link
this.api = api; * Type#getInternalName()}). May be <tt>null</tt>.
this.cv = cv; */
public void visit(
final int version,
final int access,
final String name,
final String signature,
final String superName,
final String[] interfaces) {
if (cv != null) {
cv.visit(version, access, name, signature, superName, interfaces);
} }
}
/** /**
* Visits the header of the class. * Visits the source of the class.
* *
* @param version * @param source the name of the source file from which the class was compiled. May be
* the class version. * <tt>null</tt>.
* @param access * @param debug additional debug information to compute the correspondence between source and
* the class's access flags (see {@link Opcodes}). This parameter * compiled elements of the class. May be <tt>null</tt>.
* also indicates if the class is deprecated. */
* @param name public void visitSource(final String source, final String debug) {
* the internal name of the class (see if (cv != null) {
* {@link Type#getInternalName() getInternalName}). cv.visitSource(source, debug);
* @param signature
* the signature of this class. May be <tt>null</tt> if the class
* is not a generic one, and does not extend or implement generic
* classes or interfaces.
* @param superName
* the internal of name of the super class (see
* {@link Type#getInternalName() getInternalName}). For
* interfaces, the super class is {@link Object}. May be
* <tt>null</tt>, but only for the {@link Object} class.
* @param interfaces
* the internal names of the class's interfaces (see
* {@link Type#getInternalName() getInternalName}). May be
* <tt>null</tt>.
*/
public void visit(int version, int access, String name, String signature,
String superName, String[] interfaces) {
if (cv != null) {
cv.visit(version, access, name, signature, superName, interfaces);
}
} }
}
/** /**
* Visits the source of the class. * Visit the module corresponding to the class.
* *
* @param source * @param name the fully qualified name (using dots) of the module.
* the name of the source file from which the class was compiled. * @param access the module access flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC} and {@code
* May be <tt>null</tt>. * ACC_MANDATED}.
* @param debug * @param version the module version, or <tt>null</tt>.
* additional debug information to compute the correspondance * @return a visitor to visit the module values, or <tt>null</tt> if this visitor is not
* between source and compiled elements of the class. May be * interested in visiting this module.
* <tt>null</tt>. */
*/ public ModuleVisitor visitModule(final String name, final int access, final String version) {
public void visitSource(String source, String debug) { if (api < Opcodes.ASM6) {
if (cv != null) { throw new UnsupportedOperationException();
cv.visitSource(source, debug);
}
} }
if (cv != null) {
return cv.visitModule(name, access, version);
}
return null;
}
/** /**
* Visit the module corresponding to the class. * <b>Experimental, use at your own risk. This method will be renamed when it becomes stable, this
* @param name * will break existing code using it</b>. Visits the nest host class of the class. A nest is a set
* module name * of classes of the same package that share access to their private members. One of these
* @param access * classes, called the host, lists the other members of the nest, which in turn should link to the
* module flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC} * host of their nest. This method must be called only once and only if the visited class is a
* and {@code ACC_MANDATED}. * non-host member of a nest. A class is implicitly its own nest, so it's invalid to call this
* @param version * method with the visited class name as argument.
* module version or null. *
* @return a visitor to visit the module values, or <tt>null</tt> if * @param nestHost the internal name of the host class of the nest.
* this visitor is not interested in visiting this module. */
*/ public void visitNestHostExperimental(final String nestHost) {
public ModuleVisitor visitModule(String name, int access, String version) { if (api < Opcodes.ASM7_EXPERIMENTAL) {
if (api < Opcodes.ASM6) { throw new UnsupportedOperationException();
throw new RuntimeException();
}
if (cv != null) {
return cv.visitModule(name, access, version);
}
return null;
} }
if (cv != null) {
cv.visitNestHostExperimental(nestHost);
}
}
/** /**
* Visits the enclosing class of the class. This method must be called only * Visits the enclosing class of the class. This method must be called only if the class has an
* if the class has an enclosing class. * enclosing class.
* *
* @param owner * @param owner internal name of the enclosing class of the class.
* internal name of the enclosing class of the class. * @param name the name of the method that contains the class, or <tt>null</tt> if the class is
* @param name * not enclosed in a method of its enclosing class.
* the name of the method that contains the class, or * @param descriptor the descriptor of the method that contains the class, or <tt>null</tt> if the
* <tt>null</tt> if the class is not enclosed in a method of its * class is not enclosed in a method of its enclosing class.
* enclosing class. */
* @param desc public void visitOuterClass(final String owner, final String name, final String descriptor) {
* the descriptor of the method that contains the class, or if (cv != null) {
* <tt>null</tt> if the class is not enclosed in a method of its cv.visitOuterClass(owner, name, descriptor);
* enclosing class.
*/
public void visitOuterClass(String owner, String name, String desc) {
if (cv != null) {
cv.visitOuterClass(owner, name, desc);
}
} }
}
/** /**
* Visits an annotation of the class. * Visits an annotation of the class.
* *
* @param desc * @param descriptor the class descriptor of the annotation class.
* the class descriptor of the annotation class. * @param visible <tt>true</tt> if the annotation is visible at runtime.
* @param visible * @return a visitor to visit the annotation values, or <tt>null</tt> if this visitor is not
* <tt>true</tt> if the annotation is visible at runtime. * interested in visiting this annotation.
* @return a visitor to visit the annotation values, or <tt>null</tt> if */
* this visitor is not interested in visiting this annotation. public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
*/ if (cv != null) {
public AnnotationVisitor visitAnnotation(String desc, boolean visible) { return cv.visitAnnotation(descriptor, visible);
if (cv != null) {
return cv.visitAnnotation(desc, visible);
}
return null;
} }
return null;
}
/** /**
* Visits an annotation on a type in the class signature. * Visits an annotation on a type in the class signature.
* *
* @param typeRef * @param typeRef a reference to the annotated type. The sort of this type reference must be
* a reference to the annotated type. The sort of this type * {@link TypeReference#CLASS_TYPE_PARAMETER}, {@link
* reference must be {@link TypeReference#CLASS_TYPE_PARAMETER * TypeReference#CLASS_TYPE_PARAMETER_BOUND} or {@link TypeReference#CLASS_EXTENDS}. See
* CLASS_TYPE_PARAMETER}, * {@link TypeReference}.
* {@link TypeReference#CLASS_TYPE_PARAMETER_BOUND * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
* CLASS_TYPE_PARAMETER_BOUND} or * static inner type within 'typeRef'. May be <tt>null</tt> if the annotation targets
* {@link TypeReference#CLASS_EXTENDS CLASS_EXTENDS}. See * 'typeRef' as a whole.
* {@link TypeReference}. * @param descriptor the class descriptor of the annotation class.
* @param typePath * @param visible <tt>true</tt> if the annotation is visible at runtime.
* the path to the annotated type argument, wildcard bound, array * @return a visitor to visit the annotation values, or <tt>null</tt> if this visitor is not
* element type, or static inner type within 'typeRef'. May be * interested in visiting this annotation.
* <tt>null</tt> if the annotation targets 'typeRef' as a whole. */
* @param desc public AnnotationVisitor visitTypeAnnotation(
* the class descriptor of the annotation class. final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
* @param visible if (api < Opcodes.ASM5) {
* <tt>true</tt> if the annotation is visible at runtime. throw new UnsupportedOperationException();
* @return a visitor to visit the annotation values, or <tt>null</tt> if
* this visitor is not interested in visiting this annotation.
*/
public AnnotationVisitor visitTypeAnnotation(int typeRef,
TypePath typePath, String desc, boolean visible) {
/* SPRING PATCH: REMOVED FOR COMPATIBILITY WITH CGLIB 3.1
if (api < Opcodes.ASM5) {
throw new RuntimeException();
}
*/
if (cv != null) {
return cv.visitTypeAnnotation(typeRef, typePath, desc, visible);
}
return null;
} }
if (cv != null) {
return cv.visitTypeAnnotation(typeRef, typePath, descriptor, visible);
}
return null;
}
/** /**
* Visits a non standard attribute of the class. * Visits a non standard attribute of the class.
* *
* @param attr * @param attribute an attribute.
* an attribute. */
*/ public void visitAttribute(final Attribute attribute) {
public void visitAttribute(Attribute attr) { if (cv != null) {
if (cv != null) { cv.visitAttribute(attribute);
cv.visitAttribute(attr);
}
} }
}
/** /**
* Visits information about an inner class. This inner class is not * <b>Experimental, use at your own risk. This method will be renamed when it becomes stable, this
* necessarily a member of the class being visited. * will break existing code using it</b>. Visits a member of the nest. A nest is a set of classes
* * of the same package that share access to their private members. One of these classes, called
* @param name * the host, lists the other members of the nest, which in turn should link to the host of their
* the internal name of an inner class (see * nest. This method must be called only if the visited class is the host of a nest. A nest host
* {@link Type#getInternalName() getInternalName}). * is implicitly a member of its own nest, so it's invalid to call this method with the visited
* @param outerName * class name as argument.
* the internal name of the class to which the inner class *
* belongs (see {@link Type#getInternalName() getInternalName}). * @param nestMember the internal name of a nest member.
* May be <tt>null</tt> for not member classes. */
* @param innerName public void visitNestMemberExperimental(final String nestMember) {
* the (simple) name of the inner class inside its enclosing if (api < Opcodes.ASM7_EXPERIMENTAL) {
* class. May be <tt>null</tt> for anonymous inner classes. throw new UnsupportedOperationException();
* @param access
* the access flags of the inner class as originally declared in
* the enclosing class.
*/
public void visitInnerClass(String name, String outerName,
String innerName, int access) {
if (cv != null) {
cv.visitInnerClass(name, outerName, innerName, access);
}
} }
if (cv != null) {
cv.visitNestMemberExperimental(nestMember);
}
}
/** /**
* Visits a field of the class. * Visits information about an inner class. This inner class is not necessarily a member of the
* * class being visited.
* @param access *
* the field's access flags (see {@link Opcodes}). This parameter * @param name the internal name of an inner class (see {@link Type#getInternalName()}).
* also indicates if the field is synthetic and/or deprecated. * @param outerName the internal name of the class to which the inner class belongs (see {@link
* @param name * Type#getInternalName()}). May be <tt>null</tt> for not member classes.
* the field's name. * @param innerName the (simple) name of the inner class inside its enclosing class. May be
* @param desc * <tt>null</tt> for anonymous inner classes.
* the field's descriptor (see {@link Type Type}). * @param access the access flags of the inner class as originally declared in the enclosing
* @param signature * class.
* the field's signature. May be <tt>null</tt> if the field's */
* type does not use generic types. public void visitInnerClass(
* @param value final String name, final String outerName, final String innerName, final int access) {
* the field's initial value. This parameter, which may be if (cv != null) {
* <tt>null</tt> if the field does not have an initial value, cv.visitInnerClass(name, outerName, innerName, access);
* must be an {@link Integer}, a {@link Float}, a {@link Long}, a
* {@link Double} or a {@link String} (for <tt>int</tt>,
* <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields
* respectively). <i>This parameter is only used for static
* fields</i>. Its value is ignored for non static fields, which
* must be initialized through bytecode instructions in
* constructors or methods.
* @return a visitor to visit field annotations and attributes, or
* <tt>null</tt> if this class visitor is not interested in visiting
* these annotations and attributes.
*/
public FieldVisitor visitField(int access, String name, String desc,
String signature, Object value) {
if (cv != null) {
return cv.visitField(access, name, desc, signature, value);
}
return null;
} }
}
/** /**
* Visits a method of the class. This method <i>must</i> return a new * Visits a field of the class.
* {@link MethodVisitor} instance (or <tt>null</tt>) each time it is called, *
* i.e., it should not return a previously returned visitor. * @param access the field's access flags (see {@link Opcodes}). This parameter also indicates if
* * the field is synthetic and/or deprecated.
* @param access * @param name the field's name.
* the method's access flags (see {@link Opcodes}). This * @param descriptor the field's descriptor (see {@link Type}).
* parameter also indicates if the method is synthetic and/or * @param signature the field's signature. May be <tt>null</tt> if the field's type does not use
* deprecated. * generic types.
* @param name * @param value the field's initial value. This parameter, which may be <tt>null</tt> if the field
* the method's name. * does not have an initial value, must be an {@link Integer}, a {@link Float}, a {@link
* @param desc * Long}, a {@link Double} or a {@link String} (for <tt>int</tt>, <tt>float</tt>,
* the method's descriptor (see {@link Type Type}). * <tt>long</tt> or <tt>String</tt> fields respectively). <i>This parameter is only used for
* @param signature * static fields</i>. Its value is ignored for non static fields, which must be initialized
* the method's signature. May be <tt>null</tt> if the method * through bytecode instructions in constructors or methods.
* parameters, return type and exceptions do not use generic * @return a visitor to visit field annotations and attributes, or <tt>null</tt> if this class
* types. * visitor is not interested in visiting these annotations and attributes.
* @param exceptions */
* the internal names of the method's exception classes (see public FieldVisitor visitField(
* {@link Type#getInternalName() getInternalName}). May be final int access,
* <tt>null</tt>. final String name,
* @return an object to visit the byte code of the method, or <tt>null</tt> final String descriptor,
* if this class visitor is not interested in visiting the code of final String signature,
* this method. final Object value) {
*/ if (cv != null) {
public MethodVisitor visitMethod(int access, String name, String desc, return cv.visitField(access, name, descriptor, signature, value);
String signature, String[] exceptions) {
if (cv != null) {
return cv.visitMethod(access, name, desc, signature, exceptions);
}
return null;
} }
return null;
}
/** /**
* Visits the end of the class. This method, which is the last one to be * Visits a method of the class. This method <i>must</i> return a new {@link MethodVisitor}
* called, is used to inform the visitor that all the fields and methods of * instance (or <tt>null</tt>) each time it is called, i.e., it should not return a previously
* the class have been visited. * returned visitor.
*/ *
public void visitEnd() { * @param access the method's access flags (see {@link Opcodes}). This parameter also indicates if
if (cv != null) { * the method is synthetic and/or deprecated.
cv.visitEnd(); * @param name the method's name.
} * @param descriptor the method's descriptor (see {@link Type}).
* @param signature the method's signature. May be <tt>null</tt> if the method parameters, return
* type and exceptions do not use generic types.
* @param exceptions the internal names of the method's exception classes (see {@link
* Type#getInternalName()}). May be <tt>null</tt>.
* @return an object to visit the byte code of the method, or <tt>null</tt> if this class visitor
* is not interested in visiting the code of this method.
*/
public MethodVisitor visitMethod(
final int access,
final String name,
final String descriptor,
final String signature,
final String[] exceptions) {
if (cv != null) {
return cv.visitMethod(access, name, descriptor, signature, exceptions);
} }
return null;
}
/**
* Visits the end of the class. This method, which is the last one to be called, is used to inform
* the visitor that all the fields and methods of the class have been visited.
*/
public void visitEnd() {
if (cv != null) {
cv.visitEnd();
}
}
} }

View File

@@ -0,0 +1,145 @@
// 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 org.springframework.asm;
import java.util.Arrays;
/**
* A constant whose value is computed at runtime, with a bootstrap method.
*
* @author Remi Forax
*/
public final class ConstantDynamic {
/** The constant name (can be arbitrary). */
private final String name;
/** The constant type (must be a field descriptor). */
private final String descriptor;
/** The bootstrap method to use to compute the constant value at runtime. */
private final Handle bootstrapMethod;
/**
* The arguments to pass to the bootstrap method, in order to compute the constant value at
* runtime.
*/
private final Object[] bootstrapMethodArguments;
/**
* Constructs a new {@link ConstantDynamic}.
*
* @param name the constant name (can be arbitrary).
* @param descriptor the constant type (must be a field descriptor).
* @param bootstrapMethod the bootstrap method to use to compute the constant value at runtime.
* @param bootstrapMethodArguments the arguments to pass to the bootstrap method, in order to
* compute the constant value at runtime.
*/
public ConstantDynamic(
final String name,
final String descriptor,
final Handle bootstrapMethod,
final Object... bootstrapMethodArguments) {
this.name = name;
this.descriptor = descriptor;
this.bootstrapMethod = bootstrapMethod;
this.bootstrapMethodArguments = bootstrapMethodArguments;
}
/**
* Returns the name of this constant.
*
* @return the name of this constant.
*/
public String getName() {
return name;
}
/**
* Returns the type of this constant.
*
* @return the type of this constant, as a field descriptor.
*/
public String getDescriptor() {
return descriptor;
}
/**
* Returns the bootstrap method used to compute the value of this constant.
*
* @return the bootstrap method used to compute the value of this constant.
*/
public Handle getBootstrapMethod() {
return bootstrapMethod;
}
/**
* Returns the arguments to pass to the bootstrap method, in order to compute the value of this
* constant.
*
* @return the arguments to pass to the bootstrap method, in order to compute the value of this
* constant.
*/
public Object[] getBootstrapMethodArguments() {
return bootstrapMethodArguments;
}
@Override
public boolean equals(final Object object) {
if (object == this) {
return true;
}
if (!(object instanceof ConstantDynamic)) {
return false;
}
ConstantDynamic constantDynamic = (ConstantDynamic) object;
return name.equals(constantDynamic.name)
&& descriptor.equals(constantDynamic.descriptor)
&& bootstrapMethod.equals(constantDynamic.bootstrapMethod)
&& Arrays.equals(bootstrapMethodArguments, constantDynamic.bootstrapMethodArguments);
}
@Override
public int hashCode() {
return name.hashCode()
^ Integer.rotateLeft(descriptor.hashCode(), 8)
^ Integer.rotateLeft(bootstrapMethod.hashCode(), 16)
^ Integer.rotateLeft(Arrays.hashCode(bootstrapMethodArguments), 24);
}
@Override
public String toString() {
return name
+ " : "
+ descriptor
+ ' '
+ bootstrapMethod
+ ' '
+ Arrays.toString(bootstrapMethodArguments);
}
}

View File

@@ -0,0 +1,176 @@
// 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 org.springframework.asm;
/**
* Defines additional JVM opcodes, access flags and constants which are not part of the ASM public
* API.
*
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-6.html">JVMS 6</a>
* @author Eric Bruneton
*/
final class Constants implements Opcodes {
private Constants() {}
// The ClassFile attribute names, in the order they are defined in
// https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.7-300.
static final String CONSTANT_VALUE = "ConstantValue";
static final String CODE = "Code";
static final String STACK_MAP_TABLE = "StackMapTable";
static final String EXCEPTIONS = "Exceptions";
static final String INNER_CLASSES = "InnerClasses";
static final String ENCLOSING_METHOD = "EnclosingMethod";
static final String SYNTHETIC = "Synthetic";
static final String SIGNATURE = "Signature";
static final String SOURCE_FILE = "SourceFile";
static final String SOURCE_DEBUG_EXTENSION = "SourceDebugExtension";
static final String LINE_NUMBER_TABLE = "LineNumberTable";
static final String LOCAL_VARIABLE_TABLE = "LocalVariableTable";
static final String LOCAL_VARIABLE_TYPE_TABLE = "LocalVariableTypeTable";
static final String DEPRECATED = "Deprecated";
static final String RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations";
static final String RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations";
static final String RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations";
static final String RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = "RuntimeInvisibleParameterAnnotations";
static final String RUNTIME_VISIBLE_TYPE_ANNOTATIONS = "RuntimeVisibleTypeAnnotations";
static final String RUNTIME_INVISIBLE_TYPE_ANNOTATIONS = "RuntimeInvisibleTypeAnnotations";
static final String ANNOTATION_DEFAULT = "AnnotationDefault";
static final String BOOTSTRAP_METHODS = "BootstrapMethods";
static final String METHOD_PARAMETERS = "MethodParameters";
static final String MODULE = "Module";
static final String MODULE_PACKAGES = "ModulePackages";
static final String MODULE_MAIN_CLASS = "ModuleMainClass";
static final String NEST_HOST = "NestHost";
static final String NEST_MEMBERS = "NestMembers";
// ASM specific access flags.
// WARNING: the 16 least significant bits must NOT be used, to avoid conflicts with standard
// access flags, and also to make sure that these flags are automatically filtered out when
// written in class files (because access flags are stored using 16 bits only).
static final int ACC_CONSTRUCTOR = 0x40000; // method access flag.
// ASM specific stack map frame types, used in {@link ClassVisitor#visitFrame}.
/**
* A frame inserted between already existing frames. This internal stack map frame type (in
* addition to the ones declared in {@link Opcodes}) can only be used if the frame content can be
* computed from the previous existing frame and from the instructions between this existing frame
* and the inserted one, without any knowledge of the type hierarchy. This kind of frame is only
* used when an unconditional jump is inserted in a method while expanding an ASM specific
* instruction. Keep in sync with Opcodes.java.
*/
static final int F_INSERT = 256;
// The JVM opcode values which are not part of the ASM public API.
// See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html.
static final int LDC_W = 19;
static final int LDC2_W = 20;
static final int ILOAD_0 = 26;
static final int ILOAD_1 = 27;
static final int ILOAD_2 = 28;
static final int ILOAD_3 = 29;
static final int LLOAD_0 = 30;
static final int LLOAD_1 = 31;
static final int LLOAD_2 = 32;
static final int LLOAD_3 = 33;
static final int FLOAD_0 = 34;
static final int FLOAD_1 = 35;
static final int FLOAD_2 = 36;
static final int FLOAD_3 = 37;
static final int DLOAD_0 = 38;
static final int DLOAD_1 = 39;
static final int DLOAD_2 = 40;
static final int DLOAD_3 = 41;
static final int ALOAD_0 = 42;
static final int ALOAD_1 = 43;
static final int ALOAD_2 = 44;
static final int ALOAD_3 = 45;
static final int ISTORE_0 = 59;
static final int ISTORE_1 = 60;
static final int ISTORE_2 = 61;
static final int ISTORE_3 = 62;
static final int LSTORE_0 = 63;
static final int LSTORE_1 = 64;
static final int LSTORE_2 = 65;
static final int LSTORE_3 = 66;
static final int FSTORE_0 = 67;
static final int FSTORE_1 = 68;
static final int FSTORE_2 = 69;
static final int FSTORE_3 = 70;
static final int DSTORE_0 = 71;
static final int DSTORE_1 = 72;
static final int DSTORE_2 = 73;
static final int DSTORE_3 = 74;
static final int ASTORE_0 = 75;
static final int ASTORE_1 = 76;
static final int ASTORE_2 = 77;
static final int ASTORE_3 = 78;
static final int WIDE = 196;
static final int GOTO_W = 200;
static final int JSR_W = 201;
// Constants to convert between normal and wide jump instructions.
// The delta between the GOTO_W and JSR_W opcodes and GOTO and JUMP.
static final int WIDE_JUMP_OPCODE_DELTA = GOTO_W - GOTO;
// Constants to convert JVM opcodes to the equivalent ASM specific opcodes, and vice versa.
// The delta between the ASM_IFEQ, ..., ASM_IF_ACMPNE, ASM_GOTO and ASM_JSR opcodes
// and IFEQ, ..., IF_ACMPNE, GOTO and JSR.
static final int ASM_OPCODE_DELTA = 49;
// The delta between the ASM_IFNULL and ASM_IFNONNULL opcodes and IFNULL and IFNONNULL.
static final int ASM_IFNULL_OPCODE_DELTA = 20;
// ASM specific opcodes, used for long forward jump instructions.
static final int ASM_IFEQ = IFEQ + ASM_OPCODE_DELTA;
static final int ASM_IFNE = IFNE + ASM_OPCODE_DELTA;
static final int ASM_IFLT = IFLT + ASM_OPCODE_DELTA;
static final int ASM_IFGE = IFGE + ASM_OPCODE_DELTA;
static final int ASM_IFGT = IFGT + ASM_OPCODE_DELTA;
static final int ASM_IFLE = IFLE + ASM_OPCODE_DELTA;
static final int ASM_IF_ICMPEQ = IF_ICMPEQ + ASM_OPCODE_DELTA;
static final int ASM_IF_ICMPNE = IF_ICMPNE + ASM_OPCODE_DELTA;
static final int ASM_IF_ICMPLT = IF_ICMPLT + ASM_OPCODE_DELTA;
static final int ASM_IF_ICMPGE = IF_ICMPGE + ASM_OPCODE_DELTA;
static final int ASM_IF_ICMPGT = IF_ICMPGT + ASM_OPCODE_DELTA;
static final int ASM_IF_ICMPLE = IF_ICMPLE + ASM_OPCODE_DELTA;
static final int ASM_IF_ACMPEQ = IF_ACMPEQ + ASM_OPCODE_DELTA;
static final int ASM_IF_ACMPNE = IF_ACMPNE + ASM_OPCODE_DELTA;
static final int ASM_GOTO = GOTO + ASM_OPCODE_DELTA;
static final int ASM_JSR = JSR + ASM_OPCODE_DELTA;
static final int ASM_IFNULL = IFNULL + ASM_IFNULL_OPCODE_DELTA;
static final int ASM_IFNONNULL = IFNONNULL + ASM_IFNULL_OPCODE_DELTA;
static final int ASM_GOTO_W = 220;
}

View File

@@ -1,32 +1,30 @@
/*** // ASM: a very small and fast Java bytecode manipulation framework
* ASM: a very small and fast Java bytecode manipulation framework // Copyright (c) 2000-2011 INRIA, France Telecom
* Copyright (c) 2000-2011 INRIA, France Telecom // All rights reserved.
* All rights reserved. //
* // Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions
* modification, are permitted provided that the following conditions // are met:
* are met: // 1. Redistributions of source code must retain the above copyright
* 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer.
* notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright
* 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the
* notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution.
* documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holders nor the names of its
* 3. Neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from
* contributors may be used to endorse or promote products derived from // this software without specific prior written permission.
* this software without specific prior written permission. //
* // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE.
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.springframework.asm; package org.springframework.asm;
@@ -35,111 +33,105 @@ package org.springframework.asm;
* *
* @author Eric Bruneton * @author Eric Bruneton
*/ */
class Context { final class Context {
/** /** The prototypes of the attributes that must be parsed in this class. */
* Prototypes of the attributes that must be parsed for this class. Attribute[] attributePrototypes;
*/
Attribute[] attrs;
/** /**
* The {@link ClassReader} option flags for the parsing of this class. * The options used to parse this class. One or more of {@link ClassReader#SKIP_CODE}, {@link
*/ * ClassReader#SKIP_DEBUG}, {@link ClassReader#SKIP_FRAMES}, {@link ClassReader#EXPAND_FRAMES} or
int flags; * {@link ClassReader#EXPAND_ASM_INSNS}.
*/
int parsingOptions;
/** /** The buffer used to read strings in the constant pool. */
* The buffer used to read strings. char[] charBuffer;
*/
char[] buffer;
/** // Information about the current method, i.e. the one read in the current (or latest) call
* The start index of each bootstrap method. // to {@link ClassReader#readMethod()}.
*/
int[] bootstrapMethods;
/** /** The access flags of the current method. */
* The access flags of the method currently being parsed. int currentMethodAccessFlags;
*/
int access;
/** /** The name of the current method. */
* The name of the method currently being parsed. String currentMethodName;
*/
String name;
/** /** The descriptor of the current method. */
* The descriptor of the method currently being parsed. String currentMethodDescriptor;
*/
String desc;
/** /**
* The label objects, indexed by bytecode offset, of the method currently * The labels of the current method, indexed by bytecode offset (only bytecode offsets for which a
* being parsed (only bytecode offsets for which a label is needed have a * label is needed have a non null associated Label).
* non null associated Label object). */
*/ Label[] currentMethodLabels;
Label[] labels;
/** // Information about the current type annotation target, i.e. the one read in the current
* The target of the type annotation currently being parsed. // (or latest) call to {@link ClassReader#readAnnotationTarget()}.
*/
int typeRef;
/** /**
* The path of the type annotation currently being parsed. * The target_type and target_info of the current type annotation target, encoded as described in
*/ * {@link TypeReference}.
TypePath typePath; */
int currentTypeAnnotationTarget;
/** /** The target_path of the current type annotation target. */
* The offset of the latest stack map frame that has been parsed. TypePath currentTypeAnnotationTargetPath;
*/
int offset;
/** /** The start of each local variable range in the current local variable annotation. */
* The labels corresponding to the start of the local variable ranges in the Label[] currentLocalVariableAnnotationRangeStarts;
* local variable type annotation currently being parsed.
*/
Label[] start;
/** /** The end of each local variable range in the current local variable annotation. */
* The labels corresponding to the end of the local variable ranges in the Label[] currentLocalVariableAnnotationRangeEnds;
* local variable type annotation currently being parsed.
*/
Label[] end;
/** /**
* The local variable indices for each local variable range in the local * The local variable index of each local variable range in the current local variable annotation.
* variable type annotation currently being parsed. */
*/ int[] currentLocalVariableAnnotationRangeIndices;
int[] index;
/** // Information about the current stack map frame, i.e. the one read in the current (or latest)
* The encoding of the latest stack map frame that has been parsed. // call to {@link ClassReader#readFrame()}.
*/
int mode;
/** /** The bytecode offset of the current stack map frame. */
* The number of locals in the latest stack map frame that has been parsed. int currentFrameOffset;
*/
int localCount;
/** /**
* The number locals in the latest stack map frame that has been parsed, * The type of the current stack map frame. One of {@link Opcodes#F_FULL}, {@link
* minus the number of locals in the previous frame. * Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or {@link Opcodes#F_SAME1}.
*/ */
int localDiff; int currentFrameType;
/** /**
* The local values of the latest stack map frame that has been parsed. * The number of local variable types in the current stack map frame. Each type is represented
*/ * with a single array element (even long and double).
Object[] local; */
int currentFrameLocalCount;
/** /**
* The stack size of the latest stack map frame that has been parsed. * The delta number of local variable types in the current stack map frame (each type is
*/ * represented with a single array element - even long and double). This is the number of local
int stackCount; * variable types in this frame, minus the number of local variable types in the previous frame.
*/
int currentFrameLocalCountDelta;
/** /**
* The stack values of the latest stack map frame that has been parsed. * The types of the local variables in the current stack map frame. Each type is represented with
*/ * a single array element (even long and double), using the format described in {@link
Object[] stack; * MethodVisitor#visitFrame}. Depending on {@link #currentFrameType}, this contains the types of
* all the local variables, or only those of the additional ones (compared to the previous frame).
*/
Object[] currentFrameLocalTypes;
/**
* The number stack element types in the current stack map frame. Each type is represented with a
* single array element (even long and double).
*/
int currentFrameStackCount;
/**
* The types of the stack elements in the current stack map frame. Each type is represented with a
* single array element (even long and double), using the format described in {@link
* MethodVisitor#visitFrame}.
*/
Object[] currentFrameStackTypes;
} }

View File

@@ -1,56 +1,56 @@
/*** // ASM: a very small and fast Java bytecode manipulation framework
* ASM: a very small and fast Java bytecode manipulation framework // Copyright (c) 2000-2011 INRIA, France Telecom
* Copyright (c) 2000-2011 INRIA, France Telecom // All rights reserved.
* All rights reserved. //
* // Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions
* modification, are permitted provided that the following conditions // are met:
* are met: // 1. Redistributions of source code must retain the above copyright
* 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer.
* notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright
* 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the
* notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution.
* documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holders nor the names of its
* 3. Neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from
* contributors may be used to endorse or promote products derived from // this software without specific prior written permission.
* this software without specific prior written permission. //
* // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE.
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.springframework.asm; package org.springframework.asm;
/** /**
* Information about the input stack map frame at the "current" instruction of a * Information about the input stack map frame at the "current" instruction of a method. This is
* method. This is implemented as a Frame subclass for a "basic block" * implemented as a Frame subclass for a "basic block" containing only one instruction.
* containing only one instruction.
* *
* @author Eric Bruneton * @author Eric Bruneton
*/ */
class CurrentFrame extends Frame { final class CurrentFrame extends Frame {
/** CurrentFrame(final Label owner) {
* Sets this CurrentFrame to the input stack map frame of the next "current" super(owner);
* instruction, i.e. the instruction just after the given one. It is assumed }
* that the value of this object when this method is called is the stack map
* frame status just before the given instruction is executed. /**
*/ * Sets this CurrentFrame to the input stack map frame of the next "current" instruction, i.e. the
@Override * instruction just after the given one. It is assumed that the value of this object when this
void execute(int opcode, int arg, ClassWriter cw, Item item) { * method is called is the stack map frame status just before the given instruction is executed.
super.execute(opcode, arg, cw, item); */
Frame successor = new Frame(); @Override
merge(cw, successor, 0); void execute(
set(successor); final int opcode, final int arg, final Symbol symbolArg, final SymbolTable symbolTable) {
owner.inputStackTop = 0; super.execute(opcode, arg, symbolArg, symbolTable);
} Frame successor = new Frame(null);
merge(symbolTable, successor, 0);
copyFrom(successor);
}
} }

View File

@@ -1,75 +1,91 @@
/*** // ASM: a very small and fast Java bytecode manipulation framework
* ASM: a very small and fast Java bytecode manipulation framework // Copyright (c) 2000-2011 INRIA, France Telecom
* Copyright (c) 2000-2011 INRIA, France Telecom // All rights reserved.
* All rights reserved. //
* // Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions
* modification, are permitted provided that the following conditions // are met:
* are met: // 1. Redistributions of source code must retain the above copyright
* 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer.
* notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright
* 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the
* notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution.
* documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holders nor the names of its
* 3. Neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from
* contributors may be used to endorse or promote products derived from // this software without specific prior written permission.
* this software without specific prior written permission. //
* // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE.
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.springframework.asm; package org.springframework.asm;
/** /**
* An edge in the control flow graph of a method body. See {@link Label Label}. * An edge in the control flow graph of a method. Each node of this graph is a basic block,
* represented with the Label corresponding to its first instruction. Each edge goes from one node
* to another, i.e. from one basic block to another (called the predecessor and successor blocks,
* respectively). An edge corresponds either to a jump or ret instruction or to an exception
* handler.
* *
* @see Label
* @author Eric Bruneton * @author Eric Bruneton
*/ */
class Edge { final class Edge {
/** /**
* Denotes a normal control flow graph edge. * A control flow graph edge corresponding to a jump or ret instruction. Only used with {@link
*/ * ClassWriter#COMPUTE_FRAMES}.
static final int NORMAL = 0; */
static final int JUMP = 0;
/** /**
* Denotes a control flow graph edge corresponding to an exception handler. * A control flow graph edge corresponding to an exception handler. Only used with {@link
* More precisely any {@link Edge} whose {@link #info} is strictly positive * ClassWriter#COMPUTE_MAXS}.
* corresponds to an exception handler. The actual value of {@link #info} is */
* the index, in the {@link ClassWriter} type table, of the exception that static final int EXCEPTION = 0x7FFFFFFF;
* is catched.
*/
static final int EXCEPTION = 0x7FFFFFFF;
/** /**
* Information about this control flow graph edge. If * Information about this control flow graph edge.
* {@link ClassWriter#COMPUTE_MAXS} is used this field is the (relative) *
* stack size in the basic block from which this edge originates. This size * <ul>
* is equal to the stack size at the "jump" instruction to which this edge * <li>If {@link ClassWriter#COMPUTE_MAXS} is used, this field contains either a stack size
* corresponds, relatively to the stack size at the beginning of the * delta (for an edge corresponding to a jump instruction), or the value EXCEPTION (for an
* originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used, * edge corresponding to an exception handler). The stack size delta is the stack size just
* this field is the kind of this control flow graph edge (i.e. NORMAL or * after the jump instruction, minus the stack size at the beginning of the predecessor
* EXCEPTION). * basic block, i.e. the one containing the jump instruction.
*/ * <li>If {@link ClassWriter#COMPUTE_FRAMES} is used, this field contains either the value JUMP
int info; * (for an edge corresponding to a jump instruction), or the index, in the {@link
* ClassWriter} type table, of the exception type that is handled (for an edge corresponding
* to an exception handler).
* </ul>
*/
final int info;
/** /** The successor block of this control flow graph edge. */
* The successor block of the basic block from which this edge originates. final Label successor;
*/
Label successor;
/** /**
* The next edge in the list of successors of the originating basic block. * The next edge in the list of outgoing edges of a basic block. See {@link Label#outgoingEdges}.
* See {@link Label#successors successors}. */
*/ Edge nextEdge;
Edge next;
/**
* Constructs a new Edge.
*
* @param info see {@link #info}.
* @param successor see {@link #successor}.
* @param nextEdge see {@link #nextEdge}.
*/
Edge(final int info, final Label successor, final Edge nextEdge) {
this.info = info;
this.successor = successor;
this.nextEdge = nextEdge;
}
} }

View File

@@ -1,152 +1,138 @@
/*** // ASM: a very small and fast Java bytecode manipulation framework
* ASM: a very small and fast Java bytecode manipulation framework // Copyright (c) 2000-2011 INRIA, France Telecom
* Copyright (c) 2000-2011 INRIA, France Telecom // All rights reserved.
* All rights reserved. //
* // Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions
* modification, are permitted provided that the following conditions // are met:
* are met: // 1. Redistributions of source code must retain the above copyright
* 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer.
* notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright
* 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the
* notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution.
* documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holders nor the names of its
* 3. Neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from
* contributors may be used to endorse or promote products derived from // this software without specific prior written permission.
* this software without specific prior written permission. //
* // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE.
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.springframework.asm; package org.springframework.asm;
/** /**
* A visitor to visit a Java field. The methods of this class must be called in * A visitor to visit a Java field. The methods of this class must be called in the following order:
* the following order: ( <tt>visitAnnotation</tt> | * ( <tt>visitAnnotation</tt> | <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )*
* <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* <tt>visitEnd</tt>. * <tt>visitEnd</tt>.
* *
* @author Eric Bruneton * @author Eric Bruneton
*/ */
public abstract class FieldVisitor { public abstract class FieldVisitor {
/** /**
* The ASM API version implemented by this visitor. The value of this field * The ASM API version implemented by this visitor. The value of this field must be one of {@link
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7_EXPERIMENTAL}.
*/ */
protected final int api; protected final int api;
/** /** The field visitor to which this visitor must delegate method calls. May be null. */
* The field visitor to which this visitor must delegate method calls. May protected FieldVisitor fv;
* be null.
*/
protected FieldVisitor fv;
/** /**
* Constructs a new {@link FieldVisitor}. * Constructs a new {@link FieldVisitor}.
* *
* @param api * @param api the ASM API version implemented by this visitor. Must be one of {@link
* the ASM API version implemented by this visitor. Must be one * Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. * Opcodes#ASM7_EXPERIMENTAL}.
*/ */
public FieldVisitor(final int api) { public FieldVisitor(final int api) {
this(api, null); this(api, null);
}
/**
* Constructs a new {@link FieldVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be one of {@link
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link
* Opcodes#ASM7_EXPERIMENTAL}.
* @param fieldVisitor the field visitor to which this visitor must delegate method calls. May be
* null.
*/
public FieldVisitor(final int api, final FieldVisitor fieldVisitor) {
if (api != Opcodes.ASM6
&& api != Opcodes.ASM5
&& api != Opcodes.ASM4
&& api != Opcodes.ASM7_EXPERIMENTAL) {
throw new IllegalArgumentException();
} }
this.api = api;
this.fv = fieldVisitor;
}
/** /**
* Constructs a new {@link FieldVisitor}. * Visits an annotation of the field.
* *
* @param api * @param descriptor the class descriptor of the annotation class.
* the ASM API version implemented by this visitor. Must be one * @param visible <tt>true</tt> if the annotation is visible at runtime.
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}. * @return a visitor to visit the annotation values, or <tt>null</tt> if this visitor is not
* @param fv * interested in visiting this annotation.
* the field visitor to which this visitor must delegate method */
* calls. May be null. public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
*/ if (fv != null) {
public FieldVisitor(final int api, final FieldVisitor fv) { return fv.visitAnnotation(descriptor, visible);
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
throw new IllegalArgumentException();
}
this.api = api;
this.fv = fv;
} }
return null;
}
/** /**
* Visits an annotation of the field. * Visits an annotation on the type of the field.
* *
* @param desc * @param typeRef a reference to the annotated type. The sort of this type reference must be
* the class descriptor of the annotation class. * {@link TypeReference#FIELD}. See {@link TypeReference}.
* @param visible * @param typePath the path to the annotated type argument, wildcard bound, array element type, or
* <tt>true</tt> if the annotation is visible at runtime. * static inner type within 'typeRef'. May be <tt>null</tt> if the annotation targets
* @return a visitor to visit the annotation values, or <tt>null</tt> if * 'typeRef' as a whole.
* this visitor is not interested in visiting this annotation. * @param descriptor the class descriptor of the annotation class.
*/ * @param visible <tt>true</tt> if the annotation is visible at runtime.
public AnnotationVisitor visitAnnotation(String desc, boolean visible) { * @return a visitor to visit the annotation values, or <tt>null</tt> if this visitor is not
if (fv != null) { * interested in visiting this annotation.
return fv.visitAnnotation(desc, visible); */
} public AnnotationVisitor visitTypeAnnotation(
return null; final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
if (api < Opcodes.ASM5) {
throw new UnsupportedOperationException();
} }
if (fv != null) {
return fv.visitTypeAnnotation(typeRef, typePath, descriptor, visible);
}
return null;
}
/** /**
* Visits an annotation on the type of the field. * Visits a non standard attribute of the field.
* *
* @param typeRef * @param attribute an attribute.
* a reference to the annotated type. The sort of this type */
* reference must be {@link TypeReference#FIELD FIELD}. See public void visitAttribute(final Attribute attribute) {
* {@link TypeReference}. if (fv != null) {
* @param typePath fv.visitAttribute(attribute);
* the path to the annotated type argument, wildcard bound, array
* element type, or static inner type within 'typeRef'. May be
* <tt>null</tt> if the annotation targets 'typeRef' as a whole.
* @param desc
* the class descriptor of the annotation class.
* @param visible
* <tt>true</tt> if the annotation is visible at runtime.
* @return a visitor to visit the annotation values, or <tt>null</tt> if
* this visitor is not interested in visiting this annotation.
*/
public AnnotationVisitor visitTypeAnnotation(int typeRef,
TypePath typePath, String desc, boolean visible) {
/* SPRING PATCH: REMOVED FOR COMPATIBILITY WITH CGLIB 3.1
if (api < Opcodes.ASM5) {
throw new RuntimeException();
}
*/
if (fv != null) {
return fv.visitTypeAnnotation(typeRef, typePath, desc, visible);
}
return null;
} }
}
/** /**
* Visits a non standard attribute of the field. * Visits the end of the field. This method, which is the last one to be called, is used to inform
* * the visitor that all the annotations and attributes of the field have been visited.
* @param attr */
* an attribute. public void visitEnd() {
*/ if (fv != null) {
public void visitAttribute(Attribute attr) { fv.visitEnd();
if (fv != null) {
fv.visitAttribute(attr);
}
}
/**
* Visits the end of the field. This method, which is the last one to be
* called, is used to inform the visitor that all the annotations and
* attributes of the field have been visited.
*/
public void visitEnd() {
if (fv != null) {
fv.visitEnd();
}
} }
}
} }

View File

@@ -1,329 +1,346 @@
/*** // ASM: a very small and fast Java bytecode manipulation framework
* ASM: a very small and fast Java bytecode manipulation framework // Copyright (c) 2000-2011 INRIA, France Telecom
* Copyright (c) 2000-2011 INRIA, France Telecom // All rights reserved.
* All rights reserved. //
* // Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions
* modification, are permitted provided that the following conditions // are met:
* are met: // 1. Redistributions of source code must retain the above copyright
* 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer.
* notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright
* 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the
* notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution.
* documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holders nor the names of its
* 3. Neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from
* contributors may be used to endorse or promote products derived from // this software without specific prior written permission.
* this software without specific prior written permission. //
* // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE.
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.springframework.asm; package org.springframework.asm;
/** /**
* An {@link FieldVisitor} that generates Java fields in bytecode form. * A {@link FieldVisitor} that generates a corresponding 'field_info' structure, as defined in the
* Java Virtual Machine Specification (JVMS).
* *
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.5">JVMS
* 4.5</a>
* @author Eric Bruneton * @author Eric Bruneton
*/ */
final class FieldWriter extends FieldVisitor { final class FieldWriter extends FieldVisitor {
/** /** Where the constants used in this FieldWriter must be stored. */
* The class writer to which this field must be added. private final SymbolTable symbolTable;
*/
private final ClassWriter cw;
/** // Note: fields are ordered as in the field_info structure, and those related to attributes are
* Access flags of this field. // ordered as in Section 4.7 of the JVMS.
*/
private final int access;
/** /**
* The index of the constant pool item that contains the name of this * The access_flags field of the field_info JVMS structure. This field can contain ASM specific
* method. * access flags, such as {@link Opcodes#ACC_DEPRECATED}, which are removed when generating the
*/ * ClassFile structure.
private final int name; */
private final int accessFlags;
/** /** The name_index field of the field_info JVMS structure. */
* The index of the constant pool item that contains the descriptor of this private final int nameIndex;
* field.
*/
private final int desc;
/** /** The descriptor_index field of the field_info JVMS structure. */
* The index of the constant pool item that contains the signature of this private final int descriptorIndex;
* field.
*/
private int signature;
/** /**
* The index of the constant pool item that contains the constant value of * The signature_index field of the Signature attribute of this field_info, or 0 if there is no
* this field. * Signature attribute.
*/ */
private int value; private int signatureIndex;
/** /**
* The runtime visible annotations of this field. May be <tt>null</tt>. * The constantvalue_index field of the ConstantValue attribute of this field_info, or 0 if there
*/ * is no ConstantValue attribute.
private AnnotationWriter anns; */
private int constantValueIndex;
/** /**
* The runtime invisible annotations of this field. May be <tt>null</tt>. * The last runtime visible annotation of this field. The previous ones can be accessed with the
*/ * {@link AnnotationWriter#previousAnnotation} field. May be <tt>null</tt>.
private AnnotationWriter ianns; */
private AnnotationWriter lastRuntimeVisibleAnnotation;
/** /**
* The runtime visible type annotations of this field. May be <tt>null</tt>. * The last runtime invisible annotation of this field. The previous ones can be accessed with the
*/ * {@link AnnotationWriter#previousAnnotation} field. May be <tt>null</tt>.
private AnnotationWriter tanns; */
private AnnotationWriter lastRuntimeInvisibleAnnotation;
/** /**
* The runtime invisible type annotations of this field. May be * The last runtime visible type annotation of this field. The previous ones can be accessed with
* <tt>null</tt>. * the {@link AnnotationWriter#previousAnnotation} field. May be <tt>null</tt>.
*/ */
private AnnotationWriter itanns; private AnnotationWriter lastRuntimeVisibleTypeAnnotation;
/** /**
* The non standard attributes of this field. May be <tt>null</tt>. * The last runtime invisible type annotation of this field. The previous ones can be accessed
*/ * with the {@link AnnotationWriter#previousAnnotation} field. May be <tt>null</tt>.
private Attribute attrs; */
private AnnotationWriter lastRuntimeInvisibleTypeAnnotation;
// ------------------------------------------------------------------------ /**
// Constructor * The first non standard attribute of this field. The next ones can be accessed with the {@link
// ------------------------------------------------------------------------ * Attribute#nextAttribute} field. May be <tt>null</tt>.
*
* <p><b>WARNING</b>: this list stores the attributes in the <i>reverse</i> order of their visit.
* firstAttribute is actually the last attribute visited in {@link #visitAttribute}. The {@link
* #putFieldInfo} method writes the attributes in the order defined by this list, i.e. in the
* reverse order specified by the user.
*/
private Attribute firstAttribute;
/** // -----------------------------------------------------------------------------------------------
* Constructs a new {@link FieldWriter}. // Constructor
* // -----------------------------------------------------------------------------------------------
* @param cw
* the class writer to which this field must be added. /**
* @param access * Constructs a new {@link FieldWriter}.
* the field's access flags (see {@link Opcodes}). *
* @param name * @param symbolTable where the constants used in this FieldWriter must be stored.
* the field's name. * @param access the field's access flags (see {@link Opcodes}).
* @param desc * @param name the field's name.
* the field's descriptor (see {@link Type}). * @param descriptor the field's descriptor (see {@link Type}).
* @param signature * @param signature the field's signature. May be <tt>null</tt>.
* the field's signature. May be <tt>null</tt>. * @param constantValue the field's constant value. May be <tt>null</tt>.
* @param value */
* the field's constant value. May be <tt>null</tt>. FieldWriter(
*/ final SymbolTable symbolTable,
FieldWriter(final ClassWriter cw, final int access, final String name, final int access,
final String desc, final String signature, final Object value) { final String name,
super(Opcodes.ASM6); final String descriptor,
if (cw.firstField == null) { final String signature,
cw.firstField = this; final Object constantValue) {
} else { super(Opcodes.ASM6);
cw.lastField.fv = this; this.symbolTable = symbolTable;
} this.accessFlags = access;
cw.lastField = this; this.nameIndex = symbolTable.addConstantUtf8(name);
this.cw = cw; this.descriptorIndex = symbolTable.addConstantUtf8(descriptor);
this.access = access; if (signature != null) {
this.name = cw.newUTF8(name); this.signatureIndex = symbolTable.addConstantUtf8(signature);
this.desc = cw.newUTF8(desc);
if (ClassReader.SIGNATURES && signature != null) {
this.signature = cw.newUTF8(signature);
}
if (value != null) {
this.value = cw.newConstItem(value).index;
}
} }
if (constantValue != null) {
// ------------------------------------------------------------------------ this.constantValueIndex = symbolTable.addConstant(constantValue).index;
// Implementation of the FieldVisitor abstract class
// ------------------------------------------------------------------------
@Override
public AnnotationVisitor visitAnnotation(final String desc,
final boolean visible) {
if (!ClassReader.ANNOTATIONS) {
return null;
}
ByteVector bv = new ByteVector();
// write type, and reserve space for values count
bv.putShort(cw.newUTF8(desc)).putShort(0);
AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
if (visible) {
aw.next = anns;
anns = aw;
} else {
aw.next = ianns;
ianns = aw;
}
return aw;
} }
}
@Override // -----------------------------------------------------------------------------------------------
public AnnotationVisitor visitTypeAnnotation(final int typeRef, // Implementation of the FieldVisitor abstract class
final TypePath typePath, final String desc, final boolean visible) { // -----------------------------------------------------------------------------------------------
if (!ClassReader.ANNOTATIONS) {
return null; @Override
} public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
ByteVector bv = new ByteVector(); // Create a ByteVector to hold an 'annotation' JVMS structure.
// write target_type and target_info // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.
AnnotationWriter.putTarget(typeRef, typePath, bv); ByteVector annotation = new ByteVector();
// write type, and reserve space for values count // Write type_index and reserve space for num_element_value_pairs.
bv.putShort(cw.newUTF8(desc)).putShort(0); annotation.putShort(symbolTable.addConstantUtf8(descriptor)).putShort(0);
AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, if (visible) {
bv.length - 2); return lastRuntimeVisibleAnnotation =
if (visible) { new AnnotationWriter(symbolTable, annotation, lastRuntimeVisibleAnnotation);
aw.next = tanns; } else {
tanns = aw; return lastRuntimeInvisibleAnnotation =
} else { new AnnotationWriter(symbolTable, annotation, lastRuntimeInvisibleAnnotation);
aw.next = itanns;
itanns = aw;
}
return aw;
} }
}
@Override @Override
public void visitAttribute(final Attribute attr) { public AnnotationVisitor visitTypeAnnotation(
attr.next = attrs; final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
attrs = attr; // 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);
if (visible) {
return lastRuntimeVisibleTypeAnnotation =
new AnnotationWriter(symbolTable, typeAnnotation, lastRuntimeVisibleTypeAnnotation);
} else {
return lastRuntimeInvisibleTypeAnnotation =
new AnnotationWriter(symbolTable, typeAnnotation, lastRuntimeInvisibleTypeAnnotation);
} }
}
@Override @Override
public void visitEnd() { public void visitAttribute(final Attribute attribute) {
// Store the attributes in the <i>reverse</i> order of their visit by this method.
attribute.nextAttribute = firstAttribute;
firstAttribute = attribute;
}
@Override
public void visitEnd() {
// Nothing to do.
}
// -----------------------------------------------------------------------------------------------
// Utility methods
// -----------------------------------------------------------------------------------------------
/**
* Returns the size of the field_info JVMS structure generated by this FieldWriter. Also adds the
* names of the attributes of this field in the constant pool.
*
* @return the size in bytes of the field_info JVMS structure.
*/
int computeFieldInfoSize() {
// The access_flags, name_index, descriptor_index and attributes_count fields use 8 bytes.
int size = 8;
// For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
if (constantValueIndex != 0) {
// ConstantValue attributes always use 8 bytes.
symbolTable.addConstantUtf8(Constants.CONSTANT_VALUE);
size += 8;
} }
// Before Java 1.5, synthetic fields are represented with a Synthetic attribute.
// ------------------------------------------------------------------------ if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0
// Utility methods && symbolTable.getMajorVersion() < Opcodes.V1_5) {
// ------------------------------------------------------------------------ // Synthetic attributes always use 6 bytes.
symbolTable.addConstantUtf8(Constants.SYNTHETIC);
/** size += 6;
* Returns the size of this field.
*
* @return the size of this field.
*/
int getSize() {
int size = 8;
if (value != 0) {
cw.newUTF8("ConstantValue");
size += 8;
}
if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
if ((cw.version & 0xFFFF) < Opcodes.V1_5
|| (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
cw.newUTF8("Synthetic");
size += 6;
}
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
cw.newUTF8("Deprecated");
size += 6;
}
if (ClassReader.SIGNATURES && signature != 0) {
cw.newUTF8("Signature");
size += 8;
}
if (ClassReader.ANNOTATIONS && anns != null) {
cw.newUTF8("RuntimeVisibleAnnotations");
size += 8 + anns.getSize();
}
if (ClassReader.ANNOTATIONS && ianns != null) {
cw.newUTF8("RuntimeInvisibleAnnotations");
size += 8 + ianns.getSize();
}
if (ClassReader.ANNOTATIONS && tanns != null) {
cw.newUTF8("RuntimeVisibleTypeAnnotations");
size += 8 + tanns.getSize();
}
if (ClassReader.ANNOTATIONS && itanns != null) {
cw.newUTF8("RuntimeInvisibleTypeAnnotations");
size += 8 + itanns.getSize();
}
if (attrs != null) {
size += attrs.getSize(cw, null, 0, -1, -1);
}
return size;
} }
if (signatureIndex != 0) {
/** // Signature attributes always use 8 bytes.
* Puts the content of this field into the given byte vector. symbolTable.addConstantUtf8(Constants.SIGNATURE);
* size += 8;
* @param out
* where the content of this field must be put.
*/
void put(final ByteVector out) {
final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
| ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
out.putShort(access & ~mask).putShort(name).putShort(desc);
int attributeCount = 0;
if (value != 0) {
++attributeCount;
}
if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
if ((cw.version & 0xFFFF) < Opcodes.V1_5
|| (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
++attributeCount;
}
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
++attributeCount;
}
if (ClassReader.SIGNATURES && signature != 0) {
++attributeCount;
}
if (ClassReader.ANNOTATIONS && anns != null) {
++attributeCount;
}
if (ClassReader.ANNOTATIONS && ianns != null) {
++attributeCount;
}
if (ClassReader.ANNOTATIONS && tanns != null) {
++attributeCount;
}
if (ClassReader.ANNOTATIONS && itanns != null) {
++attributeCount;
}
if (attrs != null) {
attributeCount += attrs.getCount();
}
out.putShort(attributeCount);
if (value != 0) {
out.putShort(cw.newUTF8("ConstantValue"));
out.putInt(2).putShort(value);
}
if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
if ((cw.version & 0xFFFF) < Opcodes.V1_5
|| (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
out.putShort(cw.newUTF8("Synthetic")).putInt(0);
}
}
if ((access & Opcodes.ACC_DEPRECATED) != 0) {
out.putShort(cw.newUTF8("Deprecated")).putInt(0);
}
if (ClassReader.SIGNATURES && signature != 0) {
out.putShort(cw.newUTF8("Signature"));
out.putInt(2).putShort(signature);
}
if (ClassReader.ANNOTATIONS && anns != null) {
out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
anns.put(out);
}
if (ClassReader.ANNOTATIONS && ianns != null) {
out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
ianns.put(out);
}
if (ClassReader.ANNOTATIONS && tanns != null) {
out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
tanns.put(out);
}
if (ClassReader.ANNOTATIONS && itanns != null) {
out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
itanns.put(out);
}
if (attrs != null) {
attrs.put(cw, null, 0, -1, -1, out);
}
} }
// ACC_DEPRECATED is ASM specific, the ClassFile format uses a Deprecated attribute instead.
if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) {
// Deprecated attributes always use 6 bytes.
symbolTable.addConstantUtf8(Constants.DEPRECATED);
size += 6;
}
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);
}
if (firstAttribute != null) {
size += firstAttribute.computeAttributesSize(symbolTable);
}
return size;
}
/**
* Puts the content of the field_info JVMS structure generated by this FieldWriter into the given
* ByteVector.
*
* @param output where the field_info structure must be put.
*/
void putFieldInfo(final ByteVector output) {
boolean useSyntheticAttribute = symbolTable.getMajorVersion() < Opcodes.V1_5;
// Put the access_flags, name_index and descriptor_index fields.
int mask = useSyntheticAttribute ? Opcodes.ACC_SYNTHETIC : 0;
output.putShort(accessFlags & ~mask).putShort(nameIndex).putShort(descriptorIndex);
// Compute and put the attributes_count field.
// For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
int attributesCount = 0;
if (constantValueIndex != 0) {
++attributesCount;
}
if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && useSyntheticAttribute) {
++attributesCount;
}
if (signatureIndex != 0) {
++attributesCount;
}
if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) {
++attributesCount;
}
if (lastRuntimeVisibleAnnotation != null) {
++attributesCount;
}
if (lastRuntimeInvisibleAnnotation != null) {
++attributesCount;
}
if (lastRuntimeVisibleTypeAnnotation != null) {
++attributesCount;
}
if (lastRuntimeInvisibleTypeAnnotation != null) {
++attributesCount;
}
if (firstAttribute != null) {
attributesCount += firstAttribute.getAttributeCount();
}
output.putShort(attributesCount);
// Put the field_info attributes.
// For ease of reference, we use here the same attribute order as in Section 4.7 of the JVMS.
if (constantValueIndex != 0) {
output
.putShort(symbolTable.addConstantUtf8(Constants.CONSTANT_VALUE))
.putInt(2)
.putShort(constantValueIndex);
}
if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0 && useSyntheticAttribute) {
output.putShort(symbolTable.addConstantUtf8(Constants.SYNTHETIC)).putInt(0);
}
if (signatureIndex != 0) {
output
.putShort(symbolTable.addConstantUtf8(Constants.SIGNATURE))
.putInt(2)
.putShort(signatureIndex);
}
if ((accessFlags & Opcodes.ACC_DEPRECATED) != 0) {
output.putShort(symbolTable.addConstantUtf8(Constants.DEPRECATED)).putInt(0);
}
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);
}
if (firstAttribute != null) {
firstAttribute.putAttributes(symbolTable, output);
}
}
/**
* Collects the attributes of this field into the given set of attribute prototypes.
*
* @param attributePrototypes a set of attribute prototypes.
*/
final void collectAttributePrototypes(final Attribute.Set attributePrototypes) {
attributePrototypes.addAttributes(firstAttribute);
}
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,32 +1,30 @@
/*** // ASM: a very small and fast Java bytecode manipulation framework
* ASM: a very small and fast Java bytecode manipulation framework // Copyright (c) 2000-2011 INRIA, France Telecom
* Copyright (c) 2000-2011 INRIA, France Telecom // All rights reserved.
* All rights reserved. //
* // Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions
* modification, are permitted provided that the following conditions // are met:
* are met: // 1. Redistributions of source code must retain the above copyright
* 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer.
* notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright
* 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the
* notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution.
* documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holders nor the names of its
* 3. Neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from
* contributors may be used to endorse or promote products derived from // this software without specific prior written permission.
* this software without specific prior written permission. //
* // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE.
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.springframework.asm; package org.springframework.asm;
@@ -38,185 +36,154 @@ package org.springframework.asm;
*/ */
public final class Handle { public final class Handle {
/** /**
* The kind of field or method designated by this Handle. Should be * The kind of field or method designated by this Handle. Should be {@link Opcodes#H_GETFIELD},
* {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, {@link
* {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, * Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
* {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, * {@link Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
* {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or */
* {@link Opcodes#H_INVOKEINTERFACE}. private final int tag;
*/
final int tag;
/** /** The internal name of the class that owns the field or method designated by this handle. */
* The internal name of the class that owns the field or method designated private final String owner;
* by this handle.
*/
final String owner;
/** /** The name of the field or method designated by this handle. */
* The name of the field or method designated by this handle. private final String name;
*/
final String name;
/** /** The descriptor of the field or method designated by this handle. */
* The descriptor of the field or method designated by this handle. private final String descriptor;
*/
final String desc;
/** Whether the owner is an interface or not. */
private final boolean isInterface;
/** /**
* Indicate if the owner is an interface or not. * Constructs a new field or method handle.
*/ *
final boolean itf; * @param tag the kind of field or method designated by this Handle. Must be {@link
* Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link
* Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
* {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or {@link
* Opcodes#H_INVOKEINTERFACE}.
* @param owner the internal name of the class that owns the field or method designated by this
* handle.
* @param name the name of the field or method designated by this handle.
* @param descriptor the descriptor of the field or method designated by this handle.
* @deprecated this constructor has been superseded by {@link #Handle(int, String, String, String,
* boolean)}.
*/
@Deprecated
public Handle(final int tag, final String owner, final String name, final String descriptor) {
this(tag, owner, name, descriptor, tag == Opcodes.H_INVOKEINTERFACE);
}
/** /**
* Constructs a new field or method handle. * Constructs a new field or method handle.
* *
* @param tag * @param tag the kind of field or method designated by this Handle. Must be {@link
* the kind of field or method designated by this Handle. Must be * Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD}, {@link
* {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, * Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
* {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, * {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or {@link
* {@link Opcodes#H_INVOKEVIRTUAL}, * Opcodes#H_INVOKEINTERFACE}.
* {@link Opcodes#H_INVOKESTATIC}, * @param owner the internal name of the class that owns the field or method designated by this
* {@link Opcodes#H_INVOKESPECIAL}, * handle.
* {@link Opcodes#H_NEWINVOKESPECIAL} or * @param name the name of the field or method designated by this handle.
* {@link Opcodes#H_INVOKEINTERFACE}. * @param descriptor the descriptor of the field or method designated by this handle.
* @param owner * @param isInterface whether the owner is an interface or not.
* the internal name of the class that owns the field or method */
* designated by this handle. public Handle(
* @param name final int tag,
* the name of the field or method designated by this handle. final String owner,
* @param desc final String name,
* the descriptor of the field or method designated by this final String descriptor,
* handle. final boolean isInterface) {
* this.tag = tag;
* @deprecated this constructor has been superseded this.owner = owner;
* by {@link #Handle(int, String, String, String, boolean)}. this.name = name;
*/ this.descriptor = descriptor;
@Deprecated this.isInterface = isInterface;
public Handle(int tag, String owner, String name, String desc) { }
this(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE);
/**
* Returns the kind of field or method designated by this handle.
*
* @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
* {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL}, {@link
* Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL}, {@link
* Opcodes#H_NEWINVOKESPECIAL} or {@link Opcodes#H_INVOKEINTERFACE}.
*/
public int getTag() {
return tag;
}
/**
* Returns the internal name of the class that owns the field or method designated by this handle.
*
* @return the internal name of the class that owns the field or method designated by this handle.
*/
public String getOwner() {
return owner;
}
/**
* Returns the name of the field or method designated by this handle.
*
* @return the name of the field or method designated by this handle.
*/
public String getName() {
return name;
}
/**
* Returns the descriptor of the field or method designated by this handle.
*
* @return the descriptor of the field or method designated by this handle.
*/
public String getDesc() {
return descriptor;
}
/**
* Returns true if the owner of the field or method designated by this handle is an interface.
*
* @return true if the owner of the field or method designated by this handle is an interface.
*/
public boolean isInterface() {
return isInterface;
}
@Override
public boolean equals(final Object object) {
if (object == this) {
return true;
} }
if (!(object instanceof Handle)) {
/** return false;
* Constructs a new field or method handle.
*
* @param tag
* the kind of field or method designated by this Handle. Must be
* {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
* {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
* {@link Opcodes#H_INVOKEVIRTUAL},
* {@link Opcodes#H_INVOKESTATIC},
* {@link Opcodes#H_INVOKESPECIAL},
* {@link Opcodes#H_NEWINVOKESPECIAL} or
* {@link Opcodes#H_INVOKEINTERFACE}.
* @param owner
* the internal name of the class that owns the field or method
* designated by this handle.
* @param name
* the name of the field or method designated by this handle.
* @param desc
* the descriptor of the field or method designated by this
* handle.
* @param itf
* true if the owner is an interface.
*/
public Handle(int tag, String owner, String name, String desc, boolean itf) {
this.tag = tag;
this.owner = owner;
this.name = name;
this.desc = desc;
this.itf = itf;
} }
Handle handle = (Handle) object;
return tag == handle.tag
&& isInterface == handle.isInterface
&& owner.equals(handle.owner)
&& name.equals(handle.name)
&& descriptor.equals(handle.descriptor);
}
/** @Override
* Returns the kind of field or method designated by this handle. public int hashCode() {
* return tag
* @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC}, + (isInterface ? 64 : 0)
* {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC}, + owner.hashCode() * name.hashCode() * descriptor.hashCode();
* {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC}, }
* {@link Opcodes#H_INVOKESPECIAL},
* {@link Opcodes#H_NEWINVOKESPECIAL} or
* {@link Opcodes#H_INVOKEINTERFACE}.
*/
public int getTag() {
return tag;
}
/** /**
* Returns the internal name of the class that owns the field or method * Returns the textual representation of this handle. The textual representation is:
* designated by this handle. *
* * <ul>
* @return the internal name of the class that owns the field or method * <li>for a reference to a class: owner "." name descriptor " (" tag ")",
* designated by this handle. * <li>for a reference to an interface: owner "." name descriptor " (" tag " itf)".
*/ * </ul>
public String getOwner() { */
return owner; @Override
} public String toString() {
return owner + '.' + name + descriptor + " (" + tag + (isInterface ? " itf" : "") + ')';
/** }
* Returns the name of the field or method designated by this handle.
*
* @return the name of the field or method designated by this handle.
*/
public String getName() {
return name;
}
/**
* Returns the descriptor of the field or method designated by this handle.
*
* @return the descriptor of the field or method designated by this handle.
*/
public String getDesc() {
return desc;
}
/**
* Returns true if the owner of the field or method designated
* by this handle is an interface.
*
* @return true if the owner of the field or method designated
* by this handle is an interface.
*/
public boolean isInterface() {
return itf;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Handle)) {
return false;
}
Handle h = (Handle) obj;
return tag == h.tag && itf == h.itf && owner.equals(h.owner)
&& name.equals(h.name) && desc.equals(h.desc);
}
@Override
public int hashCode() {
return tag + (itf? 64: 0) + owner.hashCode() * name.hashCode() * desc.hashCode();
}
/**
* Returns the textual representation of this handle. The textual
* representation is:
*
* <pre>
* for a reference to a class:
* owner '.' name desc ' ' '(' tag ')'
* for a reference to an interface:
* owner '.' name desc ' ' '(' tag ' ' itf ')'
* </pre>
*
* . As this format is unambiguous, it can be parsed if necessary.
*/
@Override
public String toString() {
return owner + '.' + name + desc + " (" + tag + (itf? " itf": "") + ')';
}
} }

View File

@@ -1,121 +1,198 @@
/*** // ASM: a very small and fast Java bytecode manipulation framework
* ASM: a very small and fast Java bytecode manipulation framework // Copyright (c) 2000-2011 INRIA, France Telecom
* Copyright (c) 2000-2011 INRIA, France Telecom // All rights reserved.
* All rights reserved. //
* // Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions
* modification, are permitted provided that the following conditions // are met:
* are met: // 1. Redistributions of source code must retain the above copyright
* 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer.
* notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright
* 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the
* notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution.
* documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holders nor the names of its
* 3. Neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from
* contributors may be used to endorse or promote products derived from // this software without specific prior written permission.
* this software without specific prior written permission. //
* // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE.
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.springframework.asm; package org.springframework.asm;
/** /**
* Information about an exception handler block. * Information about an exception handler. Corresponds to an element of the exception_table array of
* a Code attribute, as defined in the Java Virtual Machine Specification (JVMS). Handler instances
* can be chained together, with their {@link #nextHandler} field, to describe a full JVMS
* exception_table array.
* *
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.3">JVMS
* 4.7.3</a>
* @author Eric Bruneton * @author Eric Bruneton
*/ */
class Handler { final class Handler {
/** /**
* Beginning of the exception handler's scope (inclusive). * The start_pc field of this JVMS exception_table entry. Corresponds to the beginning of the
*/ * exception handler's scope (inclusive).
Label start; */
final Label startPc;
/** /**
* End of the exception handler's scope (exclusive). * The end_pc field of this JVMS exception_table entry. Corresponds to the end of the exception
*/ * handler's scope (exclusive).
Label end; */
final Label endPc;
/** /**
* Beginning of the exception handler's code. * The handler_pc field of this JVMS exception_table entry. Corresponding to the beginning of the
*/ * exception handler's code.
Label handler; */
final Label handlerPc;
/** /**
* Internal name of the type of exceptions handled by this handler, or * The catch_type field of this JVMS exception_table entry. This is the constant pool index of the
* <tt>null</tt> to catch any exceptions. * internal name of the type of exceptions handled by this handler, or 0 to catch any exceptions.
*/ */
String desc; final int catchType;
/** /**
* Constant pool index of the internal name of the type of exceptions * The internal name of the type of exceptions handled by this handler, or <tt>null</tt> to catch
* handled by this handler, or 0 to catch any exceptions. * any exceptions.
*/ */
int type; final String catchTypeDescriptor;
/** /** The next exception handler. */
* Next exception handler block info. Handler nextHandler;
*/
Handler next;
/** /**
* Removes the range between start and end from the given exception * Constructs a new Handler.
* handlers. *
* * @param startPc the start_pc field of this JVMS exception_table entry.
* @param h * @param endPc the end_pc field of this JVMS exception_table entry.
* an exception handler list. * @param handlerPc the handler_pc field of this JVMS exception_table entry.
* @param start * @param catchType The catch_type field of this JVMS exception_table entry.
* the start of the range to be removed. * @param catchTypeDescriptor The internal name of the type of exceptions handled by this handler,
* @param end * or <tt>null</tt> to catch any exceptions.
* the end of the range to be removed. Maybe null. */
* @return the exception handler list with the start-end range removed. Handler(
*/ final Label startPc,
static Handler remove(Handler h, Label start, Label end) { final Label endPc,
if (h == null) { final Label handlerPc,
return null; final int catchType,
} else { final String catchTypeDescriptor) {
h.next = remove(h.next, start, end); this.startPc = startPc;
} this.endPc = endPc;
int hstart = h.start.position; this.handlerPc = handlerPc;
int hend = h.end.position; this.catchType = catchType;
int s = start.position; this.catchTypeDescriptor = catchTypeDescriptor;
int e = end == null ? Integer.MAX_VALUE : end.position; }
// if [hstart,hend[ and [s,e[ intervals intersect...
if (s < hend && e > hstart) { /**
if (s <= hstart) { * Constructs a new Handler from the given one, with a different scope.
if (e >= hend) { *
// [hstart,hend[ fully included in [s,e[, h removed * @param handler an existing Handler.
h = h.next; * @param startPc the start_pc field of this JVMS exception_table entry.
} else { * @param endPc the end_pc field of this JVMS exception_table entry.
// [hstart,hend[ minus [s,e[ = [e,hend[ */
h.start = end; Handler(final Handler handler, final Label startPc, final Label endPc) {
} this(startPc, endPc, handler.handlerPc, handler.catchType, handler.catchTypeDescriptor);
} else if (e >= hend) { this.nextHandler = handler.nextHandler;
// [hstart,hend[ minus [s,e[ = [hstart,s[ }
h.end = start;
} else { /**
// [hstart,hend[ minus [s,e[ = [hstart,s[ + [e,hend[ * Removes the range between start and end from the Handler list that begins with the given
Handler g = new Handler(); * element.
g.start = end; *
g.end = h.end; * @param firstHandler the beginning of a Handler list. May be <tt>null</tt>.
g.handler = h.handler; * @param start the start of the range to be removed.
g.desc = h.desc; * @param end the end of the range to be removed. Maybe <tt>null</tt>.
g.type = h.type; * @return the exception handler list with the start-end range removed.
g.next = h.next; */
h.end = start; static Handler removeRange(final Handler firstHandler, final Label start, final Label end) {
h.next = g; if (firstHandler == null) {
} return null;
} } else {
return h; firstHandler.nextHandler = removeRange(firstHandler.nextHandler, start, end);
} }
int handlerStart = firstHandler.startPc.bytecodeOffset;
int handlerEnd = firstHandler.endPc.bytecodeOffset;
int rangeStart = start.bytecodeOffset;
int rangeEnd = end == null ? Integer.MAX_VALUE : end.bytecodeOffset;
// Return early if [handlerStart,handlerEnd[ and [rangeStart,rangeEnd[ don't intersect.
if (rangeStart >= handlerEnd || rangeEnd <= handlerStart) {
return firstHandler;
}
if (rangeStart <= handlerStart) {
if (rangeEnd >= handlerEnd) {
// If [handlerStart,handlerEnd[ is included in [rangeStart,rangeEnd[, remove firstHandler.
return firstHandler.nextHandler;
} else {
// [handlerStart,handlerEnd[ - [rangeStart,rangeEnd[ = [rangeEnd,handlerEnd[
return new Handler(firstHandler, end, firstHandler.endPc);
}
} else if (rangeEnd >= handlerEnd) {
// [handlerStart,handlerEnd[ - [rangeStart,rangeEnd[ = [handlerStart,rangeStart[
return new Handler(firstHandler, firstHandler.startPc, start);
} else {
// [handlerStart,handlerEnd[ - [rangeStart,rangeEnd[ =
// [handlerStart,rangeStart[ + [rangeEnd,handerEnd[
firstHandler.nextHandler = new Handler(firstHandler, end, firstHandler.endPc);
return new Handler(firstHandler, firstHandler.startPc, start);
}
}
/**
* Returns the number of elements of the Handler list that begins with the given element.
*
* @param firstHandler the beginning of a Handler list. May be <tt>null</tt>.
* @return the number of elements of the Handler list that begins with 'handler'.
*/
static int getExceptionTableLength(final Handler firstHandler) {
int length = 0;
Handler handler = firstHandler;
while (handler != null) {
length++;
handler = handler.nextHandler;
}
return length;
}
/**
* Returns the size in bytes of the JVMS exception_table corresponding to the Handler list that
* begins with the given element. <i>This includes the exception_table_length field.</i>
*
* @param firstHandler the beginning of a Handler list. May be <tt>null</tt>.
* @return the size in bytes of the exception_table_length and exception_table structures.
*/
static int getExceptionTableSize(final Handler firstHandler) {
return 2 + 8 * getExceptionTableLength(firstHandler);
}
/**
* Puts the JVMS exception_table corresponding to the Handler list that begins with the given
* element. <i>This includes the exception_table_length field.</i>
*
* @param firstHandler the beginning of a Handler list. May be <tt>null</tt>.
* @param output where the exception_table_length and exception_table structures must be put.
*/
static void putExceptionTable(final Handler firstHandler, final ByteVector output) {
output.putShort(getExceptionTableLength(firstHandler));
Handler handler = firstHandler;
while (handler != null) {
output
.putShort(handler.startPc.bytecodeOffset)
.putShort(handler.endPc.bytecodeOffset)
.putShort(handler.handlerPc.bytecodeOffset)
.putShort(handler.catchType);
handler = handler.nextHandler;
}
}
} }

View File

@@ -1,318 +0,0 @@
/***
* 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 org.springframework.asm;
/**
* A constant pool item. Constant pool items can be created with the 'newXXX'
* methods in the {@link ClassWriter} class.
*
* @author Eric Bruneton
*/
final class Item {
/**
* Index of this item in the constant pool.
*/
int index;
/**
* Type of this constant pool item. A single class is used to represent all
* constant pool item types, in order to minimize the bytecode size of this
* package. The value of this field is one of {@link ClassWriter#INT},
* {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT},
* {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8},
* {@link ClassWriter#STR}, {@link ClassWriter#CLASS},
* {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
* {@link ClassWriter#METH}, {@link ClassWriter#IMETH},
* {@link ClassWriter#MODULE}, {@link ClassWriter#PACKAGE},
* {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
*
* MethodHandle constant 9 variations are stored using a range of 9 values
* from {@link ClassWriter#HANDLE_BASE} + 1 to
* {@link ClassWriter#HANDLE_BASE} + 9.
*
* Special Item types are used for Items that are stored in the ClassWriter
* {@link ClassWriter#typeTable}, instead of the constant pool, in order to
* avoid clashes with normal constant pool items in the ClassWriter constant
* pool's hash table. These special item types are
* {@link ClassWriter#TYPE_NORMAL}, {@link ClassWriter#TYPE_UNINIT} and
* {@link ClassWriter#TYPE_MERGED}.
*/
int type;
/**
* Value of this item, for an integer item.
*/
int intVal;
/**
* Value of this item, for a long item.
*/
long longVal;
/**
* First part of the value of this item, for items that do not hold a
* primitive value.
*/
String strVal1;
/**
* Second part of the value of this item, for items that do not hold a
* primitive value.
*/
String strVal2;
/**
* Third part of the value of this item, for items that do not hold a
* primitive value.
*/
String strVal3;
/**
* The hash code value of this constant pool item.
*/
int hashCode;
/**
* Link to another constant pool item, used for collision lists in the
* constant pool's hash table.
*/
Item next;
/**
* Constructs an uninitialized {@link Item}.
*/
Item() {
}
/**
* Constructs an uninitialized {@link Item} for constant pool element at
* given position.
*
* @param index
* index of the item to be constructed.
*/
Item(final int index) {
this.index = index;
}
/**
* Constructs a copy of the given item.
*
* @param index
* index of the item to be constructed.
* @param i
* the item that must be copied into the item to be constructed.
*/
Item(final int index, final Item i) {
this.index = index;
type = i.type;
intVal = i.intVal;
longVal = i.longVal;
strVal1 = i.strVal1;
strVal2 = i.strVal2;
strVal3 = i.strVal3;
hashCode = i.hashCode;
}
/**
* Sets this item to an integer item.
*
* @param intVal
* the value of this item.
*/
void set(final int intVal) {
this.type = ClassWriter.INT;
this.intVal = intVal;
this.hashCode = 0x7FFFFFFF & (type + intVal);
}
/**
* Sets this item to a long item.
*
* @param longVal
* the value of this item.
*/
void set(final long longVal) {
this.type = ClassWriter.LONG;
this.longVal = longVal;
this.hashCode = 0x7FFFFFFF & (type + (int) longVal);
}
/**
* Sets this item to a float item.
*
* @param floatVal
* the value of this item.
*/
void set(final float floatVal) {
this.type = ClassWriter.FLOAT;
this.intVal = Float.floatToRawIntBits(floatVal);
this.hashCode = 0x7FFFFFFF & (type + (int) floatVal);
}
/**
* Sets this item to a double item.
*
* @param doubleVal
* the value of this item.
*/
void set(final double doubleVal) {
this.type = ClassWriter.DOUBLE;
this.longVal = Double.doubleToRawLongBits(doubleVal);
this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal);
}
/**
* Sets this item to an item that do not hold a primitive value.
*
* @param type
* the type of this item.
* @param strVal1
* first part of the value of this item.
* @param strVal2
* second part of the value of this item.
* @param strVal3
* third part of the value of this item.
*/
@SuppressWarnings("fallthrough")
void set(final int type, final String strVal1, final String strVal2,
final String strVal3) {
this.type = type;
this.strVal1 = strVal1;
this.strVal2 = strVal2;
this.strVal3 = strVal3;
switch (type) {
case ClassWriter.CLASS:
this.intVal = 0; // intVal of a class must be zero, see visitInnerClass
case ClassWriter.UTF8:
case ClassWriter.STR:
case ClassWriter.MTYPE:
case ClassWriter.MODULE:
case ClassWriter.PACKAGE:
case ClassWriter.TYPE_NORMAL:
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
return;
case ClassWriter.NAME_TYPE: {
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
* strVal2.hashCode());
return;
}
// ClassWriter.FIELD:
// ClassWriter.METH:
// ClassWriter.IMETH:
// ClassWriter.HANDLE_BASE + 1..9
default:
hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
* strVal2.hashCode() * strVal3.hashCode());
}
}
/**
* Sets the item to an InvokeDynamic item.
*
* @param name
* invokedynamic's name.
* @param desc
* invokedynamic's desc.
* @param bsmIndex
* zero based index into the class attribute BootrapMethods.
*/
void set(String name, String desc, int bsmIndex) {
this.type = ClassWriter.INDY;
this.longVal = bsmIndex;
this.strVal1 = name;
this.strVal2 = desc;
this.hashCode = 0x7FFFFFFF & (ClassWriter.INDY + bsmIndex
* strVal1.hashCode() * strVal2.hashCode());
}
/**
* Sets the item to a BootstrapMethod item.
*
* @param position
* position in byte in the class attribute BootrapMethods.
* @param hashCode
* hashcode of the item. This hashcode is processed from the
* hashcode of the bootstrap method and the hashcode of all
* bootstrap arguments.
*/
void set(int position, int hashCode) {
this.type = ClassWriter.BSM;
this.intVal = position;
this.hashCode = hashCode;
}
/**
* Indicates if the given item is equal to this one. <i>This method assumes
* that the two items have the same {@link #type}</i>.
*
* @param i
* the item to be compared to this one. Both items must have the
* same {@link #type}.
* @return <tt>true</tt> if the given item if equal to this one,
* <tt>false</tt> otherwise.
*/
boolean isEqualTo(final Item i) {
switch (type) {
case ClassWriter.UTF8:
case ClassWriter.STR:
case ClassWriter.CLASS:
case ClassWriter.MODULE:
case ClassWriter.PACKAGE:
case ClassWriter.MTYPE:
case ClassWriter.TYPE_NORMAL:
return i.strVal1.equals(strVal1);
case ClassWriter.TYPE_MERGED:
case ClassWriter.LONG:
case ClassWriter.DOUBLE:
return i.longVal == longVal;
case ClassWriter.INT:
case ClassWriter.FLOAT:
return i.intVal == intVal;
case ClassWriter.TYPE_UNINIT:
return i.intVal == intVal && i.strVal1.equals(strVal1);
case ClassWriter.NAME_TYPE:
return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
case ClassWriter.INDY: {
return i.longVal == longVal && i.strVal1.equals(strVal1)
&& i.strVal2.equals(strVal2);
}
// case ClassWriter.FIELD:
// case ClassWriter.METH:
// case ClassWriter.IMETH:
// case ClassWriter.HANDLE_BASE + 1..9
default:
return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2)
&& i.strVal3.equals(strVal3);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,178 +1,175 @@
/*** // ASM: a very small and fast Java bytecode manipulation framework
* ASM: a very small and fast Java bytecode manipulation framework // Copyright (c) 2000-2011 INRIA, France Telecom
* Copyright (c) 2000-2011 INRIA, France Telecom // All rights reserved.
* All rights reserved. //
* // Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions
* modification, are permitted provided that the following conditions // are met:
* are met: // 1. Redistributions of source code must retain the above copyright
* 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer.
* notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright
* 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the
* notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution.
* documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holders nor the names of its
* 3. Neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from
* contributors may be used to endorse or promote products derived from // this software without specific prior written permission.
* this software without specific prior written permission. //
* // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE.
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.springframework.asm; package org.springframework.asm;
/** /**
* A visitor to visit a Java module. The methods of this class must be called in * A visitor to visit a Java module. The methods of this class must be called in the following
* the following order: <tt>visitVersion</tt> | <tt>visitMainClass</tt> | * order: <tt>visitMainClass</tt> | ( <tt>visitPackage</tt> | <tt>visitRequire</tt> |
* <tt>visitTargetPlatform</tt> | ( <tt>visitConcealedPackage</tt> | <tt>visitRequire</tt> | * <tt>visitExport</tt> | <tt>visitOpen</tt> | <tt>visitUse</tt> | <tt>visitProvide</tt> )*
* <tt>visitExport</tt> | <tt>visitUse</tt> | <tt>visitProvide</tt> )* <tt>visitEnd</tt>. * <tt>visitEnd</tt>.
* *
* @author Remi Forax * @author Remi Forax
* @author Eric Bruneton
*/ */
public abstract class ModuleVisitor { public abstract class ModuleVisitor {
/** /**
* The ASM API version implemented by this visitor. The value of this field * The ASM API version implemented by this visitor. The value of this field must be one of {@link
* must be {@link Opcodes#ASM6}. * Opcodes#ASM6} or {@link Opcodes#ASM7_EXPERIMENTAL}.
*/ */
protected final int api; protected final int api;
/** /** The module visitor to which this visitor must delegate method calls. May be null. */
* The module visitor to which this visitor must delegate method calls. May protected ModuleVisitor mv;
* be null.
*/
protected ModuleVisitor mv;
/**
* Constructs a new {@link ModuleVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM6}
* or {@link Opcodes#ASM7_EXPERIMENTAL}.
*/
public ModuleVisitor(final int api) {
this(api, null);
}
public ModuleVisitor(final int api) { /**
this(api, null); * Constructs a new {@link ModuleVisitor}.
*
* @param api the ASM API version implemented by this visitor. Must be one of {@link Opcodes#ASM6}
* or {@link Opcodes#ASM7_EXPERIMENTAL}.
* @param moduleVisitor the module visitor to which this visitor must delegate method calls. May
* be null.
*/
public ModuleVisitor(final int api, final ModuleVisitor moduleVisitor) {
if (api != Opcodes.ASM6 && api != Opcodes.ASM7_EXPERIMENTAL) {
throw new IllegalArgumentException();
} }
this.api = api;
this.mv = moduleVisitor;
}
/** /**
* Constructs a new {@link MethodVisitor}. * Visit the main class of the current module.
* *
* @param api * @param mainClass the internal name of the main class of the current module.
* the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}. */
* @param mv public void visitMainClass(final String mainClass) {
* the method visitor to which this visitor must delegate method if (mv != null) {
* calls. May be null. mv.visitMainClass(mainClass);
*/
public ModuleVisitor(final int api, final ModuleVisitor mv) {
if (api != Opcodes.ASM6) {
throw new IllegalArgumentException();
}
this.api = api;
this.mv = mv;
} }
}
/** /**
* Visit the main class of the current module. * Visit a package of the current module.
* *
* @param mainClass the main class of the current module. * @param packaze the internal name of a package.
*/ */
public void visitMainClass(String mainClass) { public void visitPackage(final String packaze) {
if (mv != null) { if (mv != null) {
mv.visitMainClass(mainClass); mv.visitPackage(packaze);
}
} }
}
/** /**
* Visit a concealed package of the current module. * Visits a dependence of the current module.
* *
* @param packaze name of a concealed package * @param module the fully qualified name (using dots) of the dependence.
*/ * @param access the access flag of the dependence among {@code ACC_TRANSITIVE}, {@code
public void visitPackage(String packaze) { * ACC_STATIC_PHASE}, {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
if (mv != null) { * @param version the module version at compile time, or <tt>null</tt>.
mv.visitPackage(packaze); */
} public void visitRequire(final String module, final int access, final String version) {
if (mv != null) {
mv.visitRequire(module, access, version);
} }
}
/** /**
* Visits a dependence of the current module. * Visit an exported package of the current module.
* *
* @param module the module name of the dependence * @param packaze the internal name of the exported package.
* @param access the access flag of the dependence among * @param access the access flag of the exported package, valid values are among {@code
* ACC_TRANSITIVE, ACC_STATIC_PHASE, ACC_SYNTHETIC * ACC_SYNTHETIC} and {@code ACC_MANDATED}.
* and ACC_MANDATED. * @param modules the fully qualified names (using dots) of the modules that can access the public
* @param version the module version at compile time or null. * classes of the exported package, or <tt>null</tt>.
*/ */
public void visitRequire(String module, int access, String version) { public void visitExport(final String packaze, final int access, final String... modules) {
if (mv != null) { if (mv != null) {
mv.visitRequire(module, access, version); mv.visitExport(packaze, access, modules);
}
} }
}
/** /**
* Visit an exported package of the current module. * Visit an open package of the current module.
* *
* @param packaze the name of the exported package. * @param packaze the internal name of the opened package.
* @param access the access flag of the exported package, * @param access the access flag of the opened package, valid values are among {@code
* valid values are among {@code ACC_SYNTHETIC} and * ACC_SYNTHETIC} and {@code ACC_MANDATED}.
* {@code ACC_MANDATED}. * @param modules the fully qualified names (using dots) of the modules that can use deep
* @param modules names of the modules that can access to * reflection to the classes of the open package, or <tt>null</tt>.
* the public classes of the exported package or */
* <tt>null</tt>. public void visitOpen(final String packaze, final int access, final String... modules) {
*/ if (mv != null) {
public void visitExport(String packaze, int access, String... modules) { mv.visitOpen(packaze, access, modules);
if (mv != null) {
mv.visitExport(packaze, access, modules);
}
} }
}
/** /**
* Visit an open package of the current module. * Visit a service used by the current module. The name must be the internal name of an interface
* * or a class.
* @param packaze the name of the opened package. *
* @param access the access flag of the opened package, * @param service the internal name of the service.
* valid values are among {@code ACC_SYNTHETIC} and */
* {@code ACC_MANDATED}. public void visitUse(final String service) {
* @param modules names of the modules that can use deep if (mv != null) {
* reflection to the classes of the open package or mv.visitUse(service);
* <tt>null</tt>.
*/
public void visitOpen(String packaze, int access, String... modules) {
if (mv != null) {
mv.visitOpen(packaze, access, modules);
}
} }
}
/** /**
* Visit a service used by the current module. * Visit an implementation of a service.
* The name must be the name of an interface or an *
* abstract class. * @param service the internal name of the service.
* * @param providers the internal names of the implementations of the service (there is at least
* @param service the internal name of the service. * one provider).
*/ */
public void visitUse(String service) { public void visitProvide(final String service, final String... providers) {
if (mv != null) { if (mv != null) {
mv.visitUse(service); mv.visitProvide(service, providers);
}
} }
}
/** /**
* Visit an implementation of a service. * Visits the end of the module. This method, which is the last one to be called, is used to
* * inform the visitor that everything have been visited.
* @param service the internal name of the service */
* @param providers the internal names of the implementations public void visitEnd() {
* of the service (there is at least one provider). if (mv != null) {
*/ mv.visitEnd();
public void visitProvide(String service, String... providers) {
if (mv != null) {
mv.visitProvide(service, providers);
}
}
public void visitEnd() {
if (mv != null) {
mv.visitEnd();
}
} }
}
} }

View File

@@ -1,293 +1,253 @@
/*** // ASM: a very small and fast Java bytecode manipulation framework
* ASM: a very small and fast Java bytecode manipulation framework // Copyright (c) 2000-2011 INRIA, France Telecom
* Copyright (c) 2000-2011 INRIA, France Telecom // All rights reserved.
* All rights reserved. //
* // Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions
* modification, are permitted provided that the following conditions // are met:
* are met: // 1. Redistributions of source code must retain the above copyright
* 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer.
* notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright
* 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the
* notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution.
* documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holders nor the names of its
* 3. Neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from
* contributors may be used to endorse or promote products derived from // this software without specific prior written permission.
* this software without specific prior written permission. //
* // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE.
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.springframework.asm; package org.springframework.asm;
/** /**
* A {@link ModuleVisitor} that generates the corresponding Module, ModulePackages and
* ModuleMainClass attributes, as defined in the Java Virtual Machine Specification (JVMS).
*
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.25">JVMS
* 4.7.25</a>
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.26">JVMS
* 4.7.26</a>
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.27">JVMS
* 4.7.27</a>
* @author Remi Forax * @author Remi Forax
* @author Eric Bruneton
*/ */
final class ModuleWriter extends ModuleVisitor { final class ModuleWriter extends ModuleVisitor {
/**
* The class writer to which this Module attribute must be added.
*/
private final ClassWriter cw;
/** /** Where the constants used in this AnnotationWriter must be stored. */
* size in byte of the Module attribute. private final SymbolTable symbolTable;
*/
int size;
/** /** The module_name_index field of the JVMS Module attribute. */
* Number of attributes associated with the current module private final int moduleNameIndex;
* (Version, ConcealPackages, etc)
*/
int attributeCount;
/** /** The module_flags field of the JVMS Module attribute. */
* Size in bytes of the attributes associated with the current module private final int moduleFlags;
*/
int attributesSize;
/** /** The module_version_index field of the JVMS Module attribute. */
* module name index in the constant pool private final int moduleVersionIndex;
*/
private final int name;
/** /** The requires_count field of the JVMS Module attribute. */
* module access flags private int requiresCount;
*/
private final int access;
/** /** The binary content of the 'requires' array of the JVMS Module attribute. */
* module version index in the constant pool or 0 private final ByteVector requires;
*/
private final int version;
/** /** The exports_count field of the JVMS Module attribute. */
* module main class index in the constant pool or 0 private int exportsCount;
*/
private int mainClass;
/** /** The binary content of the 'exports' array of the JVMS Module attribute. */
* number of packages private final ByteVector exports;
*/
private int packageCount;
/** /** The opens_count field of the JVMS Module attribute. */
* The packages in bytecode form. This byte vector only contains private int opensCount;
* the items themselves, the number of items is store in packageCount
*/
private ByteVector packages;
/** /** The binary content of the 'opens' array of the JVMS Module attribute. */
* number of requires items private final ByteVector opens;
*/
private int requireCount;
/** /** The uses_count field of the JVMS Module attribute. */
* The requires items in bytecode form. This byte vector only contains private int usesCount;
* the items themselves, the number of items is store in requireCount
*/
private ByteVector requires;
/** /** The binary content of the 'uses_index' array of the JVMS Module attribute. */
* number of exports items private final ByteVector usesIndex;
*/
private int exportCount;
/** /** The provides_count field of the JVMS Module attribute. */
* The exports items in bytecode form. This byte vector only contains private int providesCount;
* the items themselves, the number of items is store in exportCount
*/
private ByteVector exports;
/** /** The binary content of the 'provides' array of the JVMS Module attribute. */
* number of opens items private final ByteVector provides;
*/
private int openCount;
/** /** The provides_count field of the JVMS ModulePackages attribute. */
* The opens items in bytecode form. This byte vector only contains private int packageCount;
* the items themselves, the number of items is store in openCount
*/
private ByteVector opens;
/** /** The binary content of the 'package_index' array of the JVMS ModulePackages attribute. */
* number of uses items private final ByteVector packageIndex;
*/
private int useCount;
/** /** The main_class_index field of the JVMS ModuleMainClass attribute, or 0. */
* The uses items in bytecode form. This byte vector only contains private int mainClassIndex;
* the items themselves, the number of items is store in useCount
*/
private ByteVector uses;
/** ModuleWriter(final SymbolTable symbolTable, final int name, final int access, final int version) {
* number of provides items super(Opcodes.ASM6);
*/ this.symbolTable = symbolTable;
private int provideCount; this.moduleNameIndex = name;
this.moduleFlags = access;
this.moduleVersionIndex = version;
this.requires = new ByteVector();
this.exports = new ByteVector();
this.opens = new ByteVector();
this.usesIndex = new ByteVector();
this.provides = new ByteVector();
this.packageIndex = new ByteVector();
}
/** @Override
* The uses provides in bytecode form. This byte vector only contains public void visitMainClass(final String mainClass) {
* the items themselves, the number of items is store in provideCount this.mainClassIndex = symbolTable.addConstantClass(mainClass).index;
*/ }
private ByteVector provides;
ModuleWriter(final ClassWriter cw, final int name, @Override
final int access, final int version) { public void visitPackage(final String packaze) {
super(Opcodes.ASM6); packageIndex.putShort(symbolTable.addConstantPackage(packaze).index);
this.cw = cw; packageCount++;
this.size = 16; // name + access + version + 5 counts }
this.name = name;
this.access = access; @Override
this.version = version; public void visitRequire(final String module, final int access, final String version) {
requires
.putShort(symbolTable.addConstantModule(module).index)
.putShort(access)
.putShort(version == null ? 0 : symbolTable.addConstantUtf8(version));
requiresCount++;
}
@Override
public void visitExport(final String packaze, final int access, final String... modules) {
exports.putShort(symbolTable.addConstantPackage(packaze).index).putShort(access);
if (modules == null) {
exports.putShort(0);
} else {
exports.putShort(modules.length);
for (String module : modules) {
exports.putShort(symbolTable.addConstantModule(module).index);
}
} }
exportsCount++;
}
@Override @Override
public void visitMainClass(String mainClass) { public void visitOpen(final String packaze, final int access, final String... modules) {
if (this.mainClass == 0) { // protect against several calls to visitMainClass opens.putShort(symbolTable.addConstantPackage(packaze).index).putShort(access);
cw.newUTF8("ModuleMainClass"); if (modules == null) {
attributeCount++; opens.putShort(0);
attributesSize += 8; } else {
} opens.putShort(modules.length);
this.mainClass = cw.newClass(mainClass); for (String module : modules) {
opens.putShort(symbolTable.addConstantModule(module).index);
}
} }
opensCount++;
}
@Override @Override
public void visitPackage(String packaze) { public void visitUse(final String service) {
if (packages == null) { usesIndex.putShort(symbolTable.addConstantClass(service).index);
// protect against several calls to visitPackage usesCount++;
cw.newUTF8("ModulePackages"); }
packages = new ByteVector();
attributeCount++;
attributesSize += 8;
}
packages.putShort(cw.newPackage(packaze));
packageCount++;
attributesSize += 2;
}
@Override @Override
public void visitRequire(String module, int access, String version) { public void visitProvide(final String service, final String... providers) {
if (requires == null) { provides.putShort(symbolTable.addConstantClass(service).index);
requires = new ByteVector(); provides.putShort(providers.length);
} for (String provider : providers) {
requires.putShort(cw.newModule(module)) provides.putShort(symbolTable.addConstantClass(provider).index);
.putShort(access)
.putShort(version == null? 0: cw.newUTF8(version));
requireCount++;
size += 6;
} }
providesCount++;
}
@Override @Override
public void visitExport(String packaze, int access, String... modules) { public void visitEnd() {
if (exports == null) { // Nothing to do.
exports = new ByteVector(); }
}
exports.putShort(cw.newPackage(packaze)).putShort(access);
if (modules == null) {
exports.putShort(0);
size += 6;
} else {
exports.putShort(modules.length);
for(String module: modules) {
exports.putShort(cw.newModule(module));
}
size += 6 + 2 * modules.length;
}
exportCount++;
}
@Override /**
public void visitOpen(String packaze, int access, String... modules) { * Returns the number of Module, ModulePackages and ModuleMainClass attributes generated by this
if (opens == null) { * ModuleWriter.
opens = new ByteVector(); *
} * @return the number of Module, ModulePackages and ModuleMainClass attributes (between 1 and 3).
opens.putShort(cw.newPackage(packaze)).putShort(access); */
if (modules == null) { int getAttributeCount() {
opens.putShort(0); return 1 + (packageCount > 0 ? 1 : 0) + (mainClassIndex > 0 ? 1 : 0);
size += 6; }
} else {
opens.putShort(modules.length);
for(String module: modules) {
opens.putShort(cw.newModule(module));
}
size += 6 + 2 * modules.length;
}
openCount++;
}
@Override /**
public void visitUse(String service) { * Returns the size of the Module, ModulePackages and ModuleMainClass attributes generated by this
if (uses == null) { * ModuleWriter. Also add the names of these attributes in the constant pool.
uses = new ByteVector(); *
} * @return the size in bytes of the Module, ModulePackages and ModuleMainClass attributes.
uses.putShort(cw.newClass(service)); */
useCount++; int computeAttributesSize() {
size += 2; symbolTable.addConstantUtf8(Constants.MODULE);
// 6 attribute header bytes, 6 bytes for name, flags and version, and 5 * 2 bytes for counts.
int size =
22 + requires.length + exports.length + opens.length + usesIndex.length + provides.length;
if (packageCount > 0) {
symbolTable.addConstantUtf8(Constants.MODULE_PACKAGES);
// 6 attribute header bytes, and 2 bytes for package_count.
size += 8 + packageIndex.length;
} }
if (mainClassIndex > 0) {
symbolTable.addConstantUtf8(Constants.MODULE_MAIN_CLASS);
// 6 attribute header bytes, and 2 bytes for main_class_index.
size += 8;
}
return size;
}
@Override /**
public void visitProvide(String service, String... providers) { * Puts the Module, ModulePackages and ModuleMainClass attributes generated by this ModuleWriter
if (provides == null) { * in the given ByteVector.
provides = new ByteVector(); *
} * @param output where the attributes must be put.
provides.putShort(cw.newClass(service)); */
provides.putShort(providers.length); void putAttributes(final ByteVector output) {
for(String provider: providers) { // 6 bytes for name, flags and version, and 5 * 2 bytes for counts.
provides.putShort(cw.newClass(provider)); int moduleAttributeLength =
} 16 + requires.length + exports.length + opens.length + usesIndex.length + provides.length;
provideCount++; output
size += 4 + 2 * providers.length; .putShort(symbolTable.addConstantUtf8(Constants.MODULE))
.putInt(moduleAttributeLength)
.putShort(moduleNameIndex)
.putShort(moduleFlags)
.putShort(moduleVersionIndex)
.putShort(requiresCount)
.putByteArray(requires.data, 0, requires.length)
.putShort(exportsCount)
.putByteArray(exports.data, 0, exports.length)
.putShort(opensCount)
.putByteArray(opens.data, 0, opens.length)
.putShort(usesCount)
.putByteArray(usesIndex.data, 0, usesIndex.length)
.putShort(providesCount)
.putByteArray(provides.data, 0, provides.length);
if (packageCount > 0) {
output
.putShort(symbolTable.addConstantUtf8(Constants.MODULE_PACKAGES))
.putInt(2 + packageIndex.length)
.putShort(packageCount)
.putByteArray(packageIndex.data, 0, packageIndex.length);
} }
if (mainClassIndex > 0) {
@Override output
public void visitEnd() { .putShort(symbolTable.addConstantUtf8(Constants.MODULE_MAIN_CLASS))
// empty .putInt(2)
} .putShort(mainClassIndex);
void putAttributes(ByteVector out) {
if (mainClass != 0) {
out.putShort(cw.newUTF8("ModuleMainClass")).putInt(2).putShort(mainClass);
}
if (packages != null) {
out.putShort(cw.newUTF8("ModulePackages"))
.putInt(2 + 2 * packageCount)
.putShort(packageCount)
.putByteArray(packages.data, 0, packages.length);
}
}
void put(ByteVector out) {
out.putInt(size);
out.putShort(name).putShort(access).putShort(version);
out.putShort(requireCount);
if (requires != null) {
out.putByteArray(requires.data, 0, requires.length);
}
out.putShort(exportCount);
if (exports != null) {
out.putByteArray(exports.data, 0, exports.length);
}
out.putShort(openCount);
if (opens != null) {
out.putByteArray(opens.data, 0, opens.length);
}
out.putShort(useCount);
if (uses != null) {
out.putByteArray(uses.data, 0, uses.length);
}
out.putShort(provideCount);
if (provides != null) {
out.putByteArray(provides.data, 0, provides.length);
}
} }
}
} }

View File

@@ -1,372 +1,346 @@
/*** // ASM: a very small and fast Java bytecode manipulation framework
* ASM: a very small and fast Java bytecode manipulation framework // Copyright (c) 2000-2011 INRIA, France Telecom
* Copyright (c) 2000-2011 INRIA, France Telecom // All rights reserved.
* All rights reserved. //
* // Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions
* modification, are permitted provided that the following conditions // are met:
* are met: // 1. Redistributions of source code must retain the above copyright
* 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer.
* notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright
* 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the
* notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution.
* documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holders nor the names of its
* 3. Neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from
* contributors may be used to endorse or promote products derived from // this software without specific prior written permission.
* this software without specific prior written permission. //
* // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE.
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.springframework.asm; package org.springframework.asm;
/** /**
* Defines the JVM opcodes, access flags and array type codes. This interface * The JVM opcodes, access flags and array type codes. This interface does not define all the JVM
* does not define all the JVM opcodes because some opcodes are automatically * opcodes because some opcodes are automatically handled. For example, the xLOAD and xSTORE opcodes
* handled. For example, the xLOAD and xSTORE opcodes are automatically replaced * are automatically replaced by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and
* by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n * xSTORE_n opcodes are therefore not defined in this interface. Likewise for LDC, automatically
* opcodes are therefore not defined in this interface. Likewise for LDC, * replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and JSR_W.
* automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and
* JSR_W.
* *
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-6.html">JVMS 6</a>
* @author Eric Bruneton * @author Eric Bruneton
* @author Eugene Kuleshov * @author Eugene Kuleshov
*/ */
public interface Opcodes { public interface Opcodes {
// ASM API versions // ASM API versions.
int ASM4 = 4 << 16 | 0 << 8 | 0; int ASM4 = 4 << 16 | 0 << 8;
int ASM5 = 5 << 16 | 0 << 8 | 0; int ASM5 = 5 << 16 | 0 << 8;
int ASM6 = 6 << 16 | 0 << 8 | 0; int ASM6 = 6 << 16 | 0 << 8;
// versions /**
* <b>Experimental, use at your own risk. This field will be renamed when it becomes stable, this
* will break existing code using it</b>.
*/
int ASM7_EXPERIMENTAL = 1 << 24 | 7 << 16 | 0 << 8;
int V1_1 = 3 << 16 | 45; // Java ClassFile versions (the minor version is stored in the 16 most
int V1_2 = 0 << 16 | 46; // significant bits, and the
int V1_3 = 0 << 16 | 47; // major version in the 16 least significant bits).
int V1_4 = 0 << 16 | 48;
int V1_5 = 0 << 16 | 49;
int V1_6 = 0 << 16 | 50;
int V1_7 = 0 << 16 | 51;
int V1_8 = 0 << 16 | 52;
int V1_9 = 0 << 16 | 53;
// access flags int V1_1 = 3 << 16 | 45;
int V1_2 = 0 << 16 | 46;
int V1_3 = 0 << 16 | 47;
int V1_4 = 0 << 16 | 48;
int V1_5 = 0 << 16 | 49;
int V1_6 = 0 << 16 | 50;
int V1_7 = 0 << 16 | 51;
int V1_8 = 0 << 16 | 52;
int V9 = 0 << 16 | 53;
int V10 = 0 << 16 | 54;
int V11 = 0 << 16 | 55;
int V12 = 0 << 16 | 56;
int ACC_PUBLIC = 0x0001; // class, field, method /**
int ACC_PRIVATE = 0x0002; // class, field, method * Version flag indicating that the class is using 'preview' features.
int ACC_PROTECTED = 0x0004; // class, field, method *
int ACC_STATIC = 0x0008; // field, method * <p>{@code version & V_PREVIEW_EXPERIMENTAL == V_PREVIEW_EXPERIMENTAL} tests if a version is
int ACC_FINAL = 0x0010; // class, field, method, parameter * flagged with {@code V_PREVIEW_EXPERIMENTAL}.
int ACC_SUPER = 0x0020; // class *
int ACC_SYNCHRONIZED = 0x0020; // method * @deprecated This API is experimental.
int ACC_OPEN = 0x0020; // module */
int ACC_TRANSITIVE = 0x0020; // module requires @Deprecated int V_PREVIEW_EXPERIMENTAL = 0xFFFF0000;
int ACC_VOLATILE = 0x0040; // field
int ACC_BRIDGE = 0x0040; // method
int ACC_STATIC_PHASE = 0x0040; // module requires
int ACC_VARARGS = 0x0080; // method
int ACC_TRANSIENT = 0x0080; // field
int ACC_NATIVE = 0x0100; // method
int ACC_INTERFACE = 0x0200; // class
int ACC_ABSTRACT = 0x0400; // class, method
int ACC_STRICT = 0x0800; // method
int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter, module *
int ACC_ANNOTATION = 0x2000; // class
int ACC_ENUM = 0x4000; // class(?) field inner
int ACC_MANDATED = 0x8000; // parameter, module, module *
int ACC_MODULE = 0x8000; // class
// Access flags values, defined in
// - https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.1-200-E.1
// - https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.5-200-A.1
// - https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.6-200-A.1
// - https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.25
// ASM specific pseudo access flags int ACC_PUBLIC = 0x0001; // class, field, method
int ACC_PRIVATE = 0x0002; // class, field, method
int ACC_PROTECTED = 0x0004; // class, field, method
int ACC_STATIC = 0x0008; // field, method
int ACC_FINAL = 0x0010; // class, field, method, parameter
int ACC_SUPER = 0x0020; // class
int ACC_SYNCHRONIZED = 0x0020; // method
int ACC_OPEN = 0x0020; // module
int ACC_TRANSITIVE = 0x0020; // module requires
int ACC_VOLATILE = 0x0040; // field
int ACC_BRIDGE = 0x0040; // method
int ACC_STATIC_PHASE = 0x0040; // module requires
int ACC_VARARGS = 0x0080; // method
int ACC_TRANSIENT = 0x0080; // field
int ACC_NATIVE = 0x0100; // method
int ACC_INTERFACE = 0x0200; // class
int ACC_ABSTRACT = 0x0400; // class, method
int ACC_STRICT = 0x0800; // method
int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter, module *
int ACC_ANNOTATION = 0x2000; // class
int ACC_ENUM = 0x4000; // class(?) field inner
int ACC_MANDATED = 0x8000; // parameter, module, module *
int ACC_MODULE = 0x8000; // class
int ACC_DEPRECATED = 0x20000; // class, field, method // ASM specific access flags.
// WARNING: the 16 least significant bits must NOT be used, to avoid conflicts with standard
// access flags, and also to make sure that these flags are automatically filtered out when
// written in class files (because access flags are stored using 16 bits only).
// types for NEWARRAY int ACC_DEPRECATED = 0x20000; // class, field, method
int T_BOOLEAN = 4; // Possible values for the type operand of the NEWARRAY instruction.
int T_CHAR = 5; // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html#jvms-6.5.newarray.
int T_FLOAT = 6;
int T_DOUBLE = 7;
int T_BYTE = 8;
int T_SHORT = 9;
int T_INT = 10;
int T_LONG = 11;
// tags for Handle int T_BOOLEAN = 4;
int T_CHAR = 5;
int T_FLOAT = 6;
int T_DOUBLE = 7;
int T_BYTE = 8;
int T_SHORT = 9;
int T_INT = 10;
int T_LONG = 11;
int H_GETFIELD = 1; // Possible values for the reference_kind field of CONSTANT_MethodHandle_info structures.
int H_GETSTATIC = 2; // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.4.8.
int H_PUTFIELD = 3;
int H_PUTSTATIC = 4;
int H_INVOKEVIRTUAL = 5;
int H_INVOKESTATIC = 6;
int H_INVOKESPECIAL = 7;
int H_NEWINVOKESPECIAL = 8;
int H_INVOKEINTERFACE = 9;
// stack map frame types int H_GETFIELD = 1;
int H_GETSTATIC = 2;
int H_PUTFIELD = 3;
int H_PUTSTATIC = 4;
int H_INVOKEVIRTUAL = 5;
int H_INVOKESTATIC = 6;
int H_INVOKESPECIAL = 7;
int H_NEWINVOKESPECIAL = 8;
int H_INVOKEINTERFACE = 9;
/** // ASM specific stack map frame types, used in {@link ClassVisitor#visitFrame}.
* Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}.
*/
int F_NEW = -1;
/** /** An expanded frame. See {@link ClassReader#EXPAND_FRAMES}. */
* Represents a compressed frame with complete frame data. int F_NEW = -1;
*/
int F_FULL = 0;
/** /** A compressed frame with complete frame data. */
* Represents a compressed frame where locals are the same as the locals in int F_FULL = 0;
* the previous frame, except that additional 1-3 locals are defined, and
* with an empty stack.
*/
int F_APPEND = 1;
/** /**
* Represents a compressed frame where locals are the same as the locals in * A compressed frame where locals are the same as the locals in the previous frame, except that
* the previous frame, except that the last 1-3 locals are absent and with * additional 1-3 locals are defined, and with an empty stack.
* an empty stack. */
*/ int F_APPEND = 1;
int F_CHOP = 2;
/** /**
* Represents a compressed frame with exactly the same locals as the * A compressed frame where locals are the same as the locals in the previous frame, except that
* previous frame and with an empty stack. * the last 1-3 locals are absent and with an empty stack.
*/ */
int F_SAME = 3; int F_CHOP = 2;
/** /**
* Represents a compressed frame with exactly the same locals as the * A compressed frame with exactly the same locals as the previous frame and with an empty stack.
* previous frame and with a single value on the stack. */
*/ int F_SAME = 3;
int F_SAME1 = 4;
// Do not try to change the following code to use auto-boxing, /**
// these values are compared by reference and not by value * A compressed frame with exactly the same locals as the previous frame and with a single value
// The constructor of Integer was deprecated in 9 * on the stack.
// but we are stuck with it by backward compatibility */
@SuppressWarnings("deprecation") Integer TOP = new Integer(0); int F_SAME1 = 4;
@SuppressWarnings("deprecation") Integer INTEGER = new Integer(1);
@SuppressWarnings("deprecation") Integer FLOAT = new Integer(2);
@SuppressWarnings("deprecation") Integer DOUBLE = new Integer(3);
@SuppressWarnings("deprecation") Integer LONG = new Integer(4);
@SuppressWarnings("deprecation") Integer NULL = new Integer(5);
@SuppressWarnings("deprecation") Integer UNINITIALIZED_THIS = new Integer(6);
// opcodes // visit method (- = idem) // Standard stack map frame element types, used in {@link ClassVisitor#visitFrame}.
int NOP = 0; // visitInsn Integer TOP = Frame.ITEM_TOP;
int ACONST_NULL = 1; // - Integer INTEGER = Frame.ITEM_INTEGER;
int ICONST_M1 = 2; // - Integer FLOAT = Frame.ITEM_FLOAT;
int ICONST_0 = 3; // - Integer DOUBLE = Frame.ITEM_DOUBLE;
int ICONST_1 = 4; // - Integer LONG = Frame.ITEM_LONG;
int ICONST_2 = 5; // - Integer NULL = Frame.ITEM_NULL;
int ICONST_3 = 6; // - Integer UNINITIALIZED_THIS = Frame.ITEM_UNINITIALIZED_THIS;
int ICONST_4 = 7; // -
int ICONST_5 = 8; // - // The JVM opcode values (with the MethodVisitor method name used to visit them in comment, and
int LCONST_0 = 9; // - // where '-' means 'same method name as on the previous line').
int LCONST_1 = 10; // - // See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html.
int FCONST_0 = 11; // -
int FCONST_1 = 12; // - int NOP = 0; // visitInsn
int FCONST_2 = 13; // - int ACONST_NULL = 1; // -
int DCONST_0 = 14; // - int ICONST_M1 = 2; // -
int DCONST_1 = 15; // - int ICONST_0 = 3; // -
int BIPUSH = 16; // visitIntInsn int ICONST_1 = 4; // -
int SIPUSH = 17; // - int ICONST_2 = 5; // -
int LDC = 18; // visitLdcInsn int ICONST_3 = 6; // -
// int LDC_W = 19; // - int ICONST_4 = 7; // -
// int LDC2_W = 20; // - int ICONST_5 = 8; // -
int ILOAD = 21; // visitVarInsn int LCONST_0 = 9; // -
int LLOAD = 22; // - int LCONST_1 = 10; // -
int FLOAD = 23; // - int FCONST_0 = 11; // -
int DLOAD = 24; // - int FCONST_1 = 12; // -
int ALOAD = 25; // - int FCONST_2 = 13; // -
// int ILOAD_0 = 26; // - int DCONST_0 = 14; // -
// int ILOAD_1 = 27; // - int DCONST_1 = 15; // -
// int ILOAD_2 = 28; // - int BIPUSH = 16; // visitIntInsn
// int ILOAD_3 = 29; // - int SIPUSH = 17; // -
// int LLOAD_0 = 30; // - int LDC = 18; // visitLdcInsn
// int LLOAD_1 = 31; // - int ILOAD = 21; // visitVarInsn
// int LLOAD_2 = 32; // - int LLOAD = 22; // -
// int LLOAD_3 = 33; // - int FLOAD = 23; // -
// int FLOAD_0 = 34; // - int DLOAD = 24; // -
// int FLOAD_1 = 35; // - int ALOAD = 25; // -
// int FLOAD_2 = 36; // - int IALOAD = 46; // visitInsn
// int FLOAD_3 = 37; // - int LALOAD = 47; // -
// int DLOAD_0 = 38; // - int FALOAD = 48; // -
// int DLOAD_1 = 39; // - int DALOAD = 49; // -
// int DLOAD_2 = 40; // - int AALOAD = 50; // -
// int DLOAD_3 = 41; // - int BALOAD = 51; // -
// int ALOAD_0 = 42; // - int CALOAD = 52; // -
// int ALOAD_1 = 43; // - int SALOAD = 53; // -
// int ALOAD_2 = 44; // - int ISTORE = 54; // visitVarInsn
// int ALOAD_3 = 45; // - int LSTORE = 55; // -
int IALOAD = 46; // visitInsn int FSTORE = 56; // -
int LALOAD = 47; // - int DSTORE = 57; // -
int FALOAD = 48; // - int ASTORE = 58; // -
int DALOAD = 49; // - int IASTORE = 79; // visitInsn
int AALOAD = 50; // - int LASTORE = 80; // -
int BALOAD = 51; // - int FASTORE = 81; // -
int CALOAD = 52; // - int DASTORE = 82; // -
int SALOAD = 53; // - int AASTORE = 83; // -
int ISTORE = 54; // visitVarInsn int BASTORE = 84; // -
int LSTORE = 55; // - int CASTORE = 85; // -
int FSTORE = 56; // - int SASTORE = 86; // -
int DSTORE = 57; // - int POP = 87; // -
int ASTORE = 58; // - int POP2 = 88; // -
// int ISTORE_0 = 59; // - int DUP = 89; // -
// int ISTORE_1 = 60; // - int DUP_X1 = 90; // -
// int ISTORE_2 = 61; // - int DUP_X2 = 91; // -
// int ISTORE_3 = 62; // - int DUP2 = 92; // -
// int LSTORE_0 = 63; // - int DUP2_X1 = 93; // -
// int LSTORE_1 = 64; // - int DUP2_X2 = 94; // -
// int LSTORE_2 = 65; // - int SWAP = 95; // -
// int LSTORE_3 = 66; // - int IADD = 96; // -
// int FSTORE_0 = 67; // - int LADD = 97; // -
// int FSTORE_1 = 68; // - int FADD = 98; // -
// int FSTORE_2 = 69; // - int DADD = 99; // -
// int FSTORE_3 = 70; // - int ISUB = 100; // -
// int DSTORE_0 = 71; // - int LSUB = 101; // -
// int DSTORE_1 = 72; // - int FSUB = 102; // -
// int DSTORE_2 = 73; // - int DSUB = 103; // -
// int DSTORE_3 = 74; // - int IMUL = 104; // -
// int ASTORE_0 = 75; // - int LMUL = 105; // -
// int ASTORE_1 = 76; // - int FMUL = 106; // -
// int ASTORE_2 = 77; // - int DMUL = 107; // -
// int ASTORE_3 = 78; // - int IDIV = 108; // -
int IASTORE = 79; // visitInsn int LDIV = 109; // -
int LASTORE = 80; // - int FDIV = 110; // -
int FASTORE = 81; // - int DDIV = 111; // -
int DASTORE = 82; // - int IREM = 112; // -
int AASTORE = 83; // - int LREM = 113; // -
int BASTORE = 84; // - int FREM = 114; // -
int CASTORE = 85; // - int DREM = 115; // -
int SASTORE = 86; // - int INEG = 116; // -
int POP = 87; // - int LNEG = 117; // -
int POP2 = 88; // - int FNEG = 118; // -
int DUP = 89; // - int DNEG = 119; // -
int DUP_X1 = 90; // - int ISHL = 120; // -
int DUP_X2 = 91; // - int LSHL = 121; // -
int DUP2 = 92; // - int ISHR = 122; // -
int DUP2_X1 = 93; // - int LSHR = 123; // -
int DUP2_X2 = 94; // - int IUSHR = 124; // -
int SWAP = 95; // - int LUSHR = 125; // -
int IADD = 96; // - int IAND = 126; // -
int LADD = 97; // - int LAND = 127; // -
int FADD = 98; // - int IOR = 128; // -
int DADD = 99; // - int LOR = 129; // -
int ISUB = 100; // - int IXOR = 130; // -
int LSUB = 101; // - int LXOR = 131; // -
int FSUB = 102; // - int IINC = 132; // visitIincInsn
int DSUB = 103; // - int I2L = 133; // visitInsn
int IMUL = 104; // - int I2F = 134; // -
int LMUL = 105; // - int I2D = 135; // -
int FMUL = 106; // - int L2I = 136; // -
int DMUL = 107; // - int L2F = 137; // -
int IDIV = 108; // - int L2D = 138; // -
int LDIV = 109; // - int F2I = 139; // -
int FDIV = 110; // - int F2L = 140; // -
int DDIV = 111; // - int F2D = 141; // -
int IREM = 112; // - int D2I = 142; // -
int LREM = 113; // - int D2L = 143; // -
int FREM = 114; // - int D2F = 144; // -
int DREM = 115; // - int I2B = 145; // -
int INEG = 116; // - int I2C = 146; // -
int LNEG = 117; // - int I2S = 147; // -
int FNEG = 118; // - int LCMP = 148; // -
int DNEG = 119; // - int FCMPL = 149; // -
int ISHL = 120; // - int FCMPG = 150; // -
int LSHL = 121; // - int DCMPL = 151; // -
int ISHR = 122; // - int DCMPG = 152; // -
int LSHR = 123; // - int IFEQ = 153; // visitJumpInsn
int IUSHR = 124; // - int IFNE = 154; // -
int LUSHR = 125; // - int IFLT = 155; // -
int IAND = 126; // - int IFGE = 156; // -
int LAND = 127; // - int IFGT = 157; // -
int IOR = 128; // - int IFLE = 158; // -
int LOR = 129; // - int IF_ICMPEQ = 159; // -
int IXOR = 130; // - int IF_ICMPNE = 160; // -
int LXOR = 131; // - int IF_ICMPLT = 161; // -
int IINC = 132; // visitIincInsn int IF_ICMPGE = 162; // -
int I2L = 133; // visitInsn int IF_ICMPGT = 163; // -
int I2F = 134; // - int IF_ICMPLE = 164; // -
int I2D = 135; // - int IF_ACMPEQ = 165; // -
int L2I = 136; // - int IF_ACMPNE = 166; // -
int L2F = 137; // - int GOTO = 167; // -
int L2D = 138; // - int JSR = 168; // -
int F2I = 139; // - int RET = 169; // visitVarInsn
int F2L = 140; // - int TABLESWITCH = 170; // visiTableSwitchInsn
int F2D = 141; // - int LOOKUPSWITCH = 171; // visitLookupSwitch
int D2I = 142; // - int IRETURN = 172; // visitInsn
int D2L = 143; // - int LRETURN = 173; // -
int D2F = 144; // - int FRETURN = 174; // -
int I2B = 145; // - int DRETURN = 175; // -
int I2C = 146; // - int ARETURN = 176; // -
int I2S = 147; // - int RETURN = 177; // -
int LCMP = 148; // - int GETSTATIC = 178; // visitFieldInsn
int FCMPL = 149; // - int PUTSTATIC = 179; // -
int FCMPG = 150; // - int GETFIELD = 180; // -
int DCMPL = 151; // - int PUTFIELD = 181; // -
int DCMPG = 152; // - int INVOKEVIRTUAL = 182; // visitMethodInsn
int IFEQ = 153; // visitJumpInsn int INVOKESPECIAL = 183; // -
int IFNE = 154; // - int INVOKESTATIC = 184; // -
int IFLT = 155; // - int INVOKEINTERFACE = 185; // -
int IFGE = 156; // - int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsn
int IFGT = 157; // - int NEW = 187; // visitTypeInsn
int IFLE = 158; // - int NEWARRAY = 188; // visitIntInsn
int IF_ICMPEQ = 159; // - int ANEWARRAY = 189; // visitTypeInsn
int IF_ICMPNE = 160; // - int ARRAYLENGTH = 190; // visitInsn
int IF_ICMPLT = 161; // - int ATHROW = 191; // -
int IF_ICMPGE = 162; // - int CHECKCAST = 192; // visitTypeInsn
int IF_ICMPGT = 163; // - int INSTANCEOF = 193; // -
int IF_ICMPLE = 164; // - int MONITORENTER = 194; // visitInsn
int IF_ACMPEQ = 165; // - int MONITOREXIT = 195; // -
int IF_ACMPNE = 166; // - int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
int GOTO = 167; // - int IFNULL = 198; // visitJumpInsn
int JSR = 168; // - int IFNONNULL = 199; // -
int RET = 169; // visitVarInsn
int TABLESWITCH = 170; // visiTableSwitchInsn
int LOOKUPSWITCH = 171; // visitLookupSwitch
int IRETURN = 172; // visitInsn
int LRETURN = 173; // -
int FRETURN = 174; // -
int DRETURN = 175; // -
int ARETURN = 176; // -
int RETURN = 177; // -
int GETSTATIC = 178; // visitFieldInsn
int PUTSTATIC = 179; // -
int GETFIELD = 180; // -
int PUTFIELD = 181; // -
int INVOKEVIRTUAL = 182; // visitMethodInsn
int INVOKESPECIAL = 183; // -
int INVOKESTATIC = 184; // -
int INVOKEINTERFACE = 185; // -
int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsn
int NEW = 187; // visitTypeInsn
int NEWARRAY = 188; // visitIntInsn
int ANEWARRAY = 189; // visitTypeInsn
int ARRAYLENGTH = 190; // visitInsn
int ATHROW = 191; // -
int CHECKCAST = 192; // visitTypeInsn
int INSTANCEOF = 193; // -
int MONITORENTER = 194; // visitInsn
int MONITOREXIT = 195; // -
// int WIDE = 196; // NOT VISITED
int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
int IFNULL = 198; // visitJumpInsn
int IFNONNULL = 199; // -
// int GOTO_W = 200; // -
// int JSR_W = 201; // -
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2017 the original author or authors. * Copyright 2002-2018 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@ package org.springframework.asm;
/** /**
* Utility class exposing constants related to Spring's internal repackaging * Utility class exposing constants related to Spring's internal repackaging
* of the ASM bytecode manipulation library (currently based on version 6.0). * of the ASM bytecode manipulation library (currently based on version 6.2).
* *
* <p>See <a href="package-summary.html">package-level javadocs</a> for more * <p>See <a href="package-summary.html">package-level javadocs</a> for more
* information on {@code org.springframework.asm}. * information on {@code org.springframework.asm}.

View File

@@ -0,0 +1,240 @@
// 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 org.springframework.asm;
/**
* An entry of the constant pool, of the BootstrapMethods attribute, or of the (ASM specific) type
* table of a class.
*
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.4">JVMS
* 4.4</a>
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.23">JVMS
* 4.7.23</a>
* @author Eric Bruneton
*/
abstract class Symbol {
// Tag values for the constant pool entries (using the same order as in the JVMS).
/** The tag value of CONSTANT_Class_info JVMS structures. */
static final int CONSTANT_CLASS_TAG = 7;
/** The tag value of CONSTANT_Fieldref_info JVMS structures. */
static final int CONSTANT_FIELDREF_TAG = 9;
/** The tag value of CONSTANT_Methodref_info JVMS structures. */
static final int CONSTANT_METHODREF_TAG = 10;
/** The tag value of CONSTANT_InterfaceMethodref_info JVMS structures. */
static final int CONSTANT_INTERFACE_METHODREF_TAG = 11;
/** The tag value of CONSTANT_String_info JVMS structures. */
static final int CONSTANT_STRING_TAG = 8;
/** The tag value of CONSTANT_Integer_info JVMS structures. */
static final int CONSTANT_INTEGER_TAG = 3;
/** The tag value of CONSTANT_Float_info JVMS structures. */
static final int CONSTANT_FLOAT_TAG = 4;
/** The tag value of CONSTANT_Long_info JVMS structures. */
static final int CONSTANT_LONG_TAG = 5;
/** The tag value of CONSTANT_Double_info JVMS structures. */
static final int CONSTANT_DOUBLE_TAG = 6;
/** The tag value of CONSTANT_NameAndType_info JVMS structures. */
static final int CONSTANT_NAME_AND_TYPE_TAG = 12;
/** The tag value of CONSTANT_Utf8_info JVMS structures. */
static final int CONSTANT_UTF8_TAG = 1;
/** The tag value of CONSTANT_MethodHandle_info JVMS structures. */
static final int CONSTANT_METHOD_HANDLE_TAG = 15;
/** The tag value of CONSTANT_MethodType_info JVMS structures. */
static final int CONSTANT_METHOD_TYPE_TAG = 16;
/** The tag value of CONSTANT_Dynamic_info JVMS structures. */
static final int CONSTANT_DYNAMIC_TAG = 17;
/** The tag value of CONSTANT_InvokeDynamic_info JVMS structures. */
static final int CONSTANT_INVOKE_DYNAMIC_TAG = 18;
/** The tag value of CONSTANT_Module_info JVMS structures. */
static final int CONSTANT_MODULE_TAG = 19;
/** The tag value of CONSTANT_Package_info JVMS structures. */
static final int CONSTANT_PACKAGE_TAG = 20;
// Tag values for the BootstrapMethods attribute entries (ASM specific tag).
/** The tag value of the BootstrapMethods attribute entries. */
static final int BOOTSTRAP_METHOD_TAG = 64;
// Tag values for the type table entries (ASM specific tags).
/** The tag value of a normal type entry in the (ASM specific) type table of a class. */
static final int TYPE_TAG = 128;
/**
* The tag value of an {@link Frame#ITEM_UNINITIALIZED} type entry in the type table of a class.
*/
static final int UNINITIALIZED_TYPE_TAG = 129;
/** The tag value of a merged type entry in the (ASM specific) type table of a class. */
static final int MERGED_TYPE_TAG = 130;
// Instance fields.
/**
* The index of this symbol in the constant pool, in the BootstrapMethods attribute, or in the
* (ASM specific) type table of a class (depending on the {@link #tag} value).
*/
final int index;
/**
* A tag indicating the type of this symbol. Must be one of the static tag values defined in this
* class.
*/
final int tag;
/**
* The internal name of the owner class of this symbol. Only used for {@link
* #CONSTANT_FIELDREF_TAG}, {@link #CONSTANT_METHODREF_TAG}, {@link
* #CONSTANT_INTERFACE_METHODREF_TAG}, and {@link #CONSTANT_METHOD_HANDLE_TAG} symbols.
*/
final String owner;
/**
* The name of the class field or method corresponding to this symbol. Only used for {@link
* #CONSTANT_FIELDREF_TAG}, {@link #CONSTANT_METHODREF_TAG}, {@link
* #CONSTANT_INTERFACE_METHODREF_TAG}, {@link #CONSTANT_NAME_AND_TYPE_TAG}, {@link
* #CONSTANT_METHOD_HANDLE_TAG}, {@link #CONSTANT_DYNAMIC_TAG} and {@link
* #CONSTANT_INVOKE_DYNAMIC_TAG} symbols.
*/
final String name;
/**
* The string value of this symbol. This is:
*
* <ul>
* <li>a field or method descriptor for {@link #CONSTANT_FIELDREF_TAG}, {@link
* #CONSTANT_METHODREF_TAG}, {@link #CONSTANT_INTERFACE_METHODREF_TAG}, {@link
* #CONSTANT_NAME_AND_TYPE_TAG}, {@link #CONSTANT_METHOD_HANDLE_TAG}, {@link
* #CONSTANT_METHOD_TYPE_TAG}, {@link #CONSTANT_DYNAMIC_TAG} and {@link
* #CONSTANT_INVOKE_DYNAMIC_TAG} symbols,
* <li>an arbitrary string for {@link #CONSTANT_UTF8_TAG} and {@link #CONSTANT_STRING_TAG}
* symbols,
* <li>an internal class name for {@link #CONSTANT_CLASS_TAG}, {@link #TYPE_TAG} and {@link
* #UNINITIALIZED_TYPE_TAG} symbols,
* <li><tt>null</tt> for the other types of symbol.
* </ul>
*/
final String value;
/**
* The numeric value of this symbol. This is:
*
* <ul>
* <li>the symbol's value for {@link #CONSTANT_INTEGER_TAG},{@link #CONSTANT_FLOAT_TAG}, {@link
* #CONSTANT_LONG_TAG}, {@link #CONSTANT_DOUBLE_TAG},
* <li>the CONSTANT_MethodHandle_info reference_kind field value for {@link
* #CONSTANT_METHOD_HANDLE_TAG} symbols,
* <li>the CONSTANT_InvokeDynamic_info bootstrap_method_attr_index field value for {@link
* #CONSTANT_INVOKE_DYNAMIC_TAG} symbols,
* <li>the offset of a bootstrap method in the BootstrapMethods boostrap_methods array, for
* {@link #CONSTANT_DYNAMIC_TAG} or {@link #BOOTSTRAP_METHOD_TAG} symbols,
* <li>the bytecode offset of the NEW instruction that created an {@link
* Frame#ITEM_UNINITIALIZED} type for {@link #UNINITIALIZED_TYPE_TAG} symbols,
* <li>the indices (in the class' type table) of two {@link #TYPE_TAG} source types for {@link
* #MERGED_TYPE_TAG} symbols,
* <li>0 for the other types of symbol.
* </ul>
*/
final long data;
/**
* Additional information about this symbol, generally computed lazily. <i>Warning: the value of
* this field is ignored when comparing Symbol instances</i> (to avoid duplicate entries in a
* SymbolTable). Therefore, this field should only contain data that can be computed from the
* other fields of this class. It contains:
*
* <ul>
* <li>the {@link Type#getArgumentsAndReturnSizes} of the symbol's method descriptor for {@link
* #CONSTANT_METHODREF_TAG}, {@link #CONSTANT_INTERFACE_METHODREF_TAG} and {@link
* #CONSTANT_INVOKE_DYNAMIC_TAG} symbols,
* <li>the index in the InnerClasses_attribute 'classes' array (plus one) corresponding to this
* class, for {@link #CONSTANT_CLASS_TAG} symbols,
* <li>the index (in the class' type table) of the merged type of the two source types for
* {@link #MERGED_TYPE_TAG} symbols,
* <li>0 for the other types of symbol, or if this field has not been computed yet.
* </ul>
*/
int info;
/**
* Constructs a new Symbol. This constructor can't be used directly because the Symbol class is
* abstract. Instead, use the factory methods of the {@link SymbolTable} class.
*
* @param index the symbol index in the constant pool, in the BootstrapMethods attribute, or in
* the (ASM specific) type table of a class (depending on 'tag').
* @param tag the symbol type. Must be one of the static tag values defined in this class.
* @param owner The internal name of the symbol's owner class. Maybe <tt>null</tt>.
* @param name The name of the symbol's corresponding class field or method. Maybe <tt>null</tt>.
* @param value The string value of this symbol. Maybe <tt>null</tt>.
* @param data The numeric value of this symbol.
*/
Symbol(
final int index,
final int tag,
final String owner,
final String name,
final String value,
final long data) {
this.index = index;
this.tag = tag;
this.owner = owner;
this.name = name;
this.value = value;
this.data = data;
}
/**
* @return the result {@link Type#getArgumentsAndReturnSizes} on {@link #value} (memoized in
* {@link #info} for efficiency). This should only be used for {@link
* #CONSTANT_METHODREF_TAG}, {@link #CONSTANT_INTERFACE_METHODREF_TAG} and {@link
* #CONSTANT_INVOKE_DYNAMIC_TAG} symbols.
*/
int getArgumentsAndReturnSizes() {
if (info == 0) {
info = Type.getArgumentsAndReturnSizes(value);
}
return info;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,196 +1,201 @@
/*** // ASM: a very small and fast Java bytecode manipulation framework
* ASM: a very small and fast Java bytecode manipulation framework // Copyright (c) 2000-2011 INRIA, France Telecom
* Copyright (c) 2000-2013 INRIA, France Telecom // All rights reserved.
* All rights reserved. //
* // Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions
* modification, are permitted provided that the following conditions // are met:
* are met: // 1. Redistributions of source code must retain the above copyright
* 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer.
* notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright
* 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the
* notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution.
* documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holders nor the names of its
* 3. Neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from
* contributors may be used to endorse or promote products derived from // this software without specific prior written permission.
* this software without specific prior written permission. //
* // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE.
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.springframework.asm; package org.springframework.asm;
/** /**
* The path to a type argument, wildcard bound, array element type, or static * The path to a type argument, wildcard bound, array element type, or static inner type within an
* inner type within an enclosing type. * enclosing type.
* *
* @author Eric Bruneton * @author Eric Bruneton
*/ */
public class TypePath { public class TypePath {
/** /** A type path step that steps into the element type of an array type. See {@link #getStep}. */
* A type path step that steps into the element type of an array type. See public static final int ARRAY_ELEMENT = 0;
* {@link #getStep getStep}.
*/
public static final int ARRAY_ELEMENT = 0;
/** /** A type path step that steps into the nested type of a class type. See {@link #getStep}. */
* A type path step that steps into the nested type of a class type. See public static final int INNER_TYPE = 1;
* {@link #getStep getStep}.
*/
public static final int INNER_TYPE = 1;
/** /** A type path step that steps into the bound of a wildcard type. See {@link #getStep}. */
* A type path step that steps into the bound of a wildcard type. See public static final int WILDCARD_BOUND = 2;
* {@link #getStep getStep}.
*/
public static final int WILDCARD_BOUND = 2;
/** /** A type path step that steps into a type argument of a generic type. See {@link #getStep}. */
* A type path step that steps into a type argument of a generic type. See public static final int TYPE_ARGUMENT = 3;
* {@link #getStep getStep}.
*/
public static final int TYPE_ARGUMENT = 3;
/** /**
* The byte array where the path is stored, in Java class file format. * The byte array where the 'type_path' structure - as defined in the Java Virtual Machine
*/ * Specification (JVMS) - corresponding to this TypePath is stored. The first byte of the
byte[] b; * structure in this array is given by {@link #typePathOffset}.
*
* @see <a
* href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20.2">JVMS
* 4.7.20.2</a>
*/
private final byte[] typePathContainer;
/** /** The offset of the first byte of the type_path JVMS structure in {@link #typePathContainer}. */
* The offset of the first byte of the type path in 'b'. private final int typePathOffset;
*/
int offset;
/** /**
* Creates a new type path. * Constructs a new TypePath.
* *
* @param b * @param typePathContainer a byte array containing a type_path JVMS structure.
* the byte array containing the type path in Java class file * @param typePathOffset the offset of the first byte of the type_path structure in
* format. * typePathContainer.
* @param offset */
* the offset of the first byte of the type path in 'b'. TypePath(final byte[] typePathContainer, final int typePathOffset) {
*/ this.typePathContainer = typePathContainer;
TypePath(byte[] b, int offset) { this.typePathOffset = typePathOffset;
this.b = b; }
this.offset = offset;
/**
* Returns the length of this path, i.e. its number of steps.
*
* @return the length of this path.
*/
public int getLength() {
// path_length is stored in the first byte of a type_path.
return typePathContainer[typePathOffset];
}
/**
* Returns the value of the given step of this path.
*
* @param index an index between 0 and {@link #getLength()}, exclusive.
* @return one of {@link #ARRAY_ELEMENT}, {@link #INNER_TYPE}, {@link #WILDCARD_BOUND}, or {@link
* #TYPE_ARGUMENT}.
*/
public int getStep(final int index) {
// Returns the type_path_kind of the path element of the given index.
return typePathContainer[typePathOffset + 2 * index + 1];
}
/**
* Returns the index of the type argument that the given step is stepping into. This method should
* only be used for steps whose value is {@link #TYPE_ARGUMENT}.
*
* @param index an index between 0 and {@link #getLength()}, exclusive.
* @return the index of the type argument that the given step is stepping into.
*/
public int getStepArgument(final int index) {
// Returns the type_argument_index of the path element of the given index.
return typePathContainer[typePathOffset + 2 * index + 2];
}
/**
* Converts a type path in string form, in the format used by {@link #toString()}, into a TypePath
* object.
*
* @param typePath a type path in string form, in the format used by {@link #toString()}. May be
* <tt>null</tt> or empty.
* @return the corresponding TypePath object, or <tt>null</tt> if the path is empty.
*/
public static TypePath fromString(final String typePath) {
if (typePath == null || typePath.length() == 0) {
return null;
} }
int typePathLength = typePath.length();
/** ByteVector output = new ByteVector(typePathLength);
* Returns the length of this path. output.putByte(0);
* int typePathIndex = 0;
* @return the length of this path. while (typePathIndex < typePathLength) {
*/ char c = typePath.charAt(typePathIndex++);
public int getLength() { if (c == '[') {
return b[offset]; output.put11(ARRAY_ELEMENT, 0);
} } else if (c == '.') {
output.put11(INNER_TYPE, 0);
/** } else if (c == '*') {
* Returns the value of the given step of this path. output.put11(WILDCARD_BOUND, 0);
* } else if (c >= '0' && c <= '9') {
* @param index int typeArg = c - '0';
* an index between 0 and {@link #getLength()}, exclusive. while (typePathIndex < typePathLength) {
* @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE c = typePath.charAt(typePathIndex++);
* INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or if (c >= '0' && c <= '9') {
* {@link #TYPE_ARGUMENT TYPE_ARGUMENT}. typeArg = typeArg * 10 + c - '0';
*/ } else if (c == ';') {
public int getStep(int index) { break;
return b[offset + 2 * index + 1]; } else {
} throw new IllegalArgumentException();
}
/**
* Returns the index of the type argument that the given step is stepping
* into. This method should only be used for steps whose value is
* {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
*
* @param index
* an index between 0 and {@link #getLength()}, exclusive.
* @return the index of the type argument that the given step is stepping
* into.
*/
public int getStepArgument(int index) {
return b[offset + 2 * index + 2];
}
/**
* Converts a type path in string form, in the format used by
* {@link #toString()}, into a TypePath object.
*
* @param typePath
* a type path in string form, in the format used by
* {@link #toString()}. May be null or empty.
* @return the corresponding TypePath object, or null if the path is empty.
*/
public static TypePath fromString(final String typePath) {
if (typePath == null || typePath.length() == 0) {
return null;
} }
int n = typePath.length(); output.put11(TYPE_ARGUMENT, typeArg);
ByteVector out = new ByteVector(n); } else {
out.putByte(0); throw new IllegalArgumentException();
for (int i = 0; i < n;) { }
char c = typePath.charAt(i++);
if (c == '[') {
out.put11(ARRAY_ELEMENT, 0);
} else if (c == '.') {
out.put11(INNER_TYPE, 0);
} else if (c == '*') {
out.put11(WILDCARD_BOUND, 0);
} else if (c >= '0' && c <= '9') {
int typeArg = c - '0';
while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') {
typeArg = typeArg * 10 + c - '0';
i += 1;
}
if (i < n && typePath.charAt(i) == ';') {
i += 1;
}
out.put11(TYPE_ARGUMENT, typeArg);
}
}
out.data[0] = (byte) (out.length / 2);
return new TypePath(out.data, 0);
} }
output.data[0] = (byte) (output.length / 2);
return new TypePath(output.data, 0);
}
/** /**
* Returns a string representation of this type path. {@link #ARRAY_ELEMENT * Returns a string representation of this type path. {@link #ARRAY_ELEMENT} steps are represented
* ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE * with '[', {@link #INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND} steps with '*' and {@link
* INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps * #TYPE_ARGUMENT} steps with their type argument index in decimal form followed by ';'.
* with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type */
* argument index in decimal form followed by ';'. @Override
*/ public String toString() {
@Override int length = getLength();
public String toString() { StringBuilder result = new StringBuilder(length * 2);
int length = getLength(); for (int i = 0; i < length; ++i) {
StringBuilder result = new StringBuilder(length * 2); switch (getStep(i)) {
for (int i = 0; i < length; ++i) { case ARRAY_ELEMENT:
switch (getStep(i)) { result.append('[');
case ARRAY_ELEMENT: break;
result.append('['); case INNER_TYPE:
break; result.append('.');
case INNER_TYPE: break;
result.append('.'); case WILDCARD_BOUND:
break; result.append('*');
case WILDCARD_BOUND: break;
result.append('*'); case TYPE_ARGUMENT:
break; result.append(getStepArgument(i)).append(';');
case TYPE_ARGUMENT: break;
result.append(getStepArgument(i)).append(';'); default:
break; throw new AssertionError();
default: }
result.append('_');
}
}
return result.toString();
} }
return result.toString();
}
/**
* Puts the type_path JVMS structure corresponding to the given TypePath into the given
* ByteVector.
*
* @param typePath a TypePath instance, or <tt>null</tt> for empty paths.
* @param output where the type path must be put.
*/
static void put(final TypePath typePath, final ByteVector output) {
if (typePath == null) {
output.putByte(0);
} else {
int length = typePath.typePathContainer[typePath.typePathOffset] * 2 + 1;
output.putByteArray(typePath.typePathContainer, typePath.typePathOffset, length);
}
}
} }

View File

@@ -1,452 +1,436 @@
/*** // ASM: a very small and fast Java bytecode manipulation framework
* ASM: a very small and fast Java bytecode manipulation framework // Copyright (c) 2000-2011 INRIA, France Telecom
* Copyright (c) 2000-2013 INRIA, France Telecom // All rights reserved.
* All rights reserved. //
* // Redistribution and use in source and binary forms, with or without
* Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions
* modification, are permitted provided that the following conditions // are met:
* are met: // 1. Redistributions of source code must retain the above copyright
* 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer.
* notice, this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright
* 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the
* notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution.
* documentation and/or other materials provided with the distribution. // 3. Neither the name of the copyright holders nor the names of its
* 3. Neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from
* contributors may be used to endorse or promote products derived from // this software without specific prior written permission.
* this software without specific prior written permission. //
* // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF // THE POSSIBILITY OF SUCH DAMAGE.
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.springframework.asm; package org.springframework.asm;
/** /**
* A reference to a type appearing in a class, field or method declaration, or * A reference to a type appearing in a class, field or method declaration, or on an instruction.
* on an instruction. Such a reference designates the part of the class where * Such a reference designates the part of the class where the referenced type is appearing (e.g. an
* the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws' * 'extends', 'implements' or 'throws' clause, a 'new' instruction, a 'catch' clause, a type cast, a
* clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable * local variable declaration, etc).
* declaration, etc).
* *
* @author Eric Bruneton * @author Eric Bruneton
*/ */
public class TypeReference { public class TypeReference {
/** /**
* The sort of type references that target a type parameter of a generic * The sort of type references that target a type parameter of a generic class. See {@link
* class. See {@link #getSort getSort}. * #getSort}.
*/ */
public final static int CLASS_TYPE_PARAMETER = 0x00; public static final int CLASS_TYPE_PARAMETER = 0x00;
/** /**
* The sort of type references that target a type parameter of a generic * The sort of type references that target a type parameter of a generic method. See {@link
* method. See {@link #getSort getSort}. * #getSort}.
*/ */
public final static int METHOD_TYPE_PARAMETER = 0x01; public static final int METHOD_TYPE_PARAMETER = 0x01;
/** /**
* The sort of type references that target the super class of a class or one * The sort of type references that target the super class of a class or one of the interfaces it
* of the interfaces it implements. See {@link #getSort getSort}. * implements. See {@link #getSort}.
*/ */
public final static int CLASS_EXTENDS = 0x10; public static final int CLASS_EXTENDS = 0x10;
/** /**
* The sort of type references that target a bound of a type parameter of a * The sort of type references that target a bound of a type parameter of a generic class. See
* generic class. See {@link #getSort getSort}. * {@link #getSort}.
*/ */
public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11; public static final int CLASS_TYPE_PARAMETER_BOUND = 0x11;
/** /**
* The sort of type references that target a bound of a type parameter of a * The sort of type references that target a bound of a type parameter of a generic method. See
* generic method. See {@link #getSort getSort}. * {@link #getSort}.
*/ */
public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12; public static final int METHOD_TYPE_PARAMETER_BOUND = 0x12;
/** /** The sort of type references that target the type of a field. See {@link #getSort}. */
* The sort of type references that target the type of a field. See public static final int FIELD = 0x13;
* {@link #getSort getSort}.
*/
public final static int FIELD = 0x13;
/** /** The sort of type references that target the return type of a method. See {@link #getSort}. */
* The sort of type references that target the return type of a method. See public static final int METHOD_RETURN = 0x14;
* {@link #getSort getSort}.
*/
public final static int METHOD_RETURN = 0x14;
/** /**
* The sort of type references that target the receiver type of a method. * The sort of type references that target the receiver type of a method. See {@link #getSort}.
* See {@link #getSort getSort}. */
*/ public static final int METHOD_RECEIVER = 0x15;
public final static int METHOD_RECEIVER = 0x15;
/** /**
* The sort of type references that target the type of a formal parameter of * The sort of type references that target the type of a formal parameter of a method. See {@link
* a method. See {@link #getSort getSort}. * #getSort}.
*/ */
public final static int METHOD_FORMAL_PARAMETER = 0x16; public static final int METHOD_FORMAL_PARAMETER = 0x16;
/** /**
* The sort of type references that target the type of an exception declared * The sort of type references that target the type of an exception declared in the throws clause
* in the throws clause of a method. See {@link #getSort getSort}. * of a method. See {@link #getSort}.
*/ */
public final static int THROWS = 0x17; public static final int THROWS = 0x17;
/** /**
* The sort of type references that target the type of a local variable in a * The sort of type references that target the type of a local variable in a method. See {@link
* method. See {@link #getSort getSort}. * #getSort}.
*/ */
public final static int LOCAL_VARIABLE = 0x40; public static final int LOCAL_VARIABLE = 0x40;
/** /**
* The sort of type references that target the type of a resource variable * The sort of type references that target the type of a resource variable in a method. See {@link
* in a method. See {@link #getSort getSort}. * #getSort}.
*/ */
public final static int RESOURCE_VARIABLE = 0x41; public static final int RESOURCE_VARIABLE = 0x41;
/** /**
* The sort of type references that target the type of the exception of a * The sort of type references that target the type of the exception of a 'catch' clause in a
* 'catch' clause in a method. See {@link #getSort getSort}. * method. See {@link #getSort}.
*/ */
public final static int EXCEPTION_PARAMETER = 0x42; public static final int EXCEPTION_PARAMETER = 0x42;
/** /**
* The sort of type references that target the type declared in an * The sort of type references that target the type declared in an 'instanceof' instruction. See
* 'instanceof' instruction. See {@link #getSort getSort}. * {@link #getSort}.
*/ */
public final static int INSTANCEOF = 0x43; public static final int INSTANCEOF = 0x43;
/** /**
* The sort of type references that target the type of the object created by * The sort of type references that target the type of the object created by a 'new' instruction.
* a 'new' instruction. See {@link #getSort getSort}. * See {@link #getSort}.
*/ */
public final static int NEW = 0x44; public static final int NEW = 0x44;
/** /**
* The sort of type references that target the receiver type of a * The sort of type references that target the receiver type of a constructor reference. See
* constructor reference. See {@link #getSort getSort}. * {@link #getSort}.
*/ */
public final static int CONSTRUCTOR_REFERENCE = 0x45; public static final int CONSTRUCTOR_REFERENCE = 0x45;
/** /**
* The sort of type references that target the receiver type of a method * The sort of type references that target the receiver type of a method reference. See {@link
* reference. See {@link #getSort getSort}. * #getSort}.
*/ */
public final static int METHOD_REFERENCE = 0x46; public static final int METHOD_REFERENCE = 0x46;
/** /**
* The sort of type references that target the type declared in an explicit * The sort of type references that target the type declared in an explicit or implicit cast
* or implicit cast instruction. See {@link #getSort getSort}. * instruction. See {@link #getSort}.
*/ */
public final static int CAST = 0x47; public static final int CAST = 0x47;
/** /**
* The sort of type references that target a type parameter of a generic * The sort of type references that target a type parameter of a generic constructor in a
* constructor in a constructor call. See {@link #getSort getSort}. * constructor call. See {@link #getSort}.
*/ */
public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48; public static final int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
/** /**
* The sort of type references that target a type parameter of a generic * The sort of type references that target a type parameter of a generic method in a method call.
* method in a method call. See {@link #getSort getSort}. * See {@link #getSort}.
*/ */
public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49; public static final int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
/** /**
* The sort of type references that target a type parameter of a generic * The sort of type references that target a type parameter of a generic constructor in a
* constructor in a constructor reference. See {@link #getSort getSort}. * constructor reference. See {@link #getSort}.
*/ */
public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A; public static final int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
/** /**
* The sort of type references that target a type parameter of a generic * The sort of type references that target a type parameter of a generic method in a method
* method in a method reference. See {@link #getSort getSort}. * reference. See {@link #getSort}.
*/ */
public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B; public static final int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
/** /**
* The type reference value in Java class file format. * The target_type and target_info structures - as defined in the Java Virtual Machine
*/ * Specification (JVMS) - corresponding to this type reference. target_type uses one byte, and all
private int value; * the target_info union fields use up to 3 bytes (except localvar_target, handled with the
* specific method {@link MethodVisitor#visitLocalVariableAnnotation}). Thus, both structures can
* be stored in an int.
*
* <p>This int field stores target_type (called the TypeReference 'sort' in the public API of this
* class) in its most significant byte, followed by the target_info fields. Depending on
* target_type, 1, 2 or even 3 least significant bytes of this field are unused. target_info
* fields which reference bytecode offsets are set to 0 (these offsets are ignored in ClassReader,
* and recomputed in MethodWriter).
*
* @see <a href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20">JVMS
* 4.7.20</a>
* @see <a
* href="https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.20.1">JVMS
* 4.7.20.1</a>
*/
private final int targetTypeAndInfo;
/** /**
* Creates a new TypeReference. * Constructs a new TypeReference.
* *
* @param typeRef * @param typeRef the int encoded value of the type reference, as received in a visit method
* the int encoded value of the type reference, as received in a * related to type annotations, such as {@link ClassVisitor#visitTypeAnnotation}.
* visit method related to type annotations, like */
* visitTypeAnnotation. public TypeReference(final int typeRef) {
*/ this.targetTypeAndInfo = typeRef;
public TypeReference(int typeRef) { }
this.value = typeRef;
} /**
* Returns a type reference of the given sort.
/** *
* Returns a type reference of the given sort. * @param sort one of {@link #FIELD}, {@link #METHOD_RETURN}, {@link #METHOD_RECEIVER}, {@link
* * #LOCAL_VARIABLE}, {@link #RESOURCE_VARIABLE}, {@link #INSTANCEOF}, {@link #NEW}, {@link
* @param sort * #CONSTRUCTOR_REFERENCE}, or {@link #METHOD_REFERENCE}.
* {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN}, * @return a type reference of the given sort.
* {@link #METHOD_RECEIVER METHOD_RECEIVER}, */
* {@link #LOCAL_VARIABLE LOCAL_VARIABLE}, public static TypeReference newTypeReference(final int sort) {
* {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE}, return new TypeReference(sort << 24);
* {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW}, }
* {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or
* {@link #METHOD_REFERENCE METHOD_REFERENCE}. /**
* @return a type reference of the given sort. * Returns a reference to a type parameter of a generic class or method.
*/ *
public static TypeReference newTypeReference(int sort) { * @param sort one of {@link #CLASS_TYPE_PARAMETER} or {@link #METHOD_TYPE_PARAMETER}.
return new TypeReference(sort << 24); * @param paramIndex the type parameter index.
} * @return a reference to the given generic class or method type parameter.
*/
/** public static TypeReference newTypeParameterReference(final int sort, final int paramIndex) {
* Returns a reference to a type parameter of a generic class or method. return new TypeReference((sort << 24) | (paramIndex << 16));
* }
* @param sort
* {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or /**
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}. * Returns a reference to a type parameter bound of a generic class or method.
* @param paramIndex *
* the type parameter index. * @param sort one of {@link #CLASS_TYPE_PARAMETER} or {@link #METHOD_TYPE_PARAMETER}.
* @return a reference to the given generic class or method type parameter. * @param paramIndex the type parameter index.
*/ * @param boundIndex the type bound index within the above type parameters.
public static TypeReference newTypeParameterReference(int sort, * @return a reference to the given generic class or method type parameter bound.
int paramIndex) { */
return new TypeReference((sort << 24) | (paramIndex << 16)); public static TypeReference newTypeParameterBoundReference(
} final int sort, final int paramIndex, final int boundIndex) {
return new TypeReference((sort << 24) | (paramIndex << 16) | (boundIndex << 8));
/** }
* Returns a reference to a type parameter bound of a generic class or
* method. /**
* * Returns a reference to the super class or to an interface of the 'implements' clause of a
* @param sort * class.
* {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or *
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}. * @param itfIndex the index of an interface in the 'implements' clause of a class, or -1 to
* @param paramIndex * reference the super class of the class.
* the type parameter index. * @return a reference to the given super type of a class.
* @param boundIndex */
* the type bound index within the above type parameters. public static TypeReference newSuperTypeReference(final int itfIndex) {
* @return a reference to the given generic class or method type parameter return new TypeReference((CLASS_EXTENDS << 24) | ((itfIndex & 0xFFFF) << 8));
* bound. }
*/
public static TypeReference newTypeParameterBoundReference(int sort, /**
int paramIndex, int boundIndex) { * Returns a reference to the type of a formal parameter of a method.
return new TypeReference((sort << 24) | (paramIndex << 16) *
| (boundIndex << 8)); * @param paramIndex the formal parameter index.
} * @return a reference to the type of the given method formal parameter.
*/
/** public static TypeReference newFormalParameterReference(final int paramIndex) {
* Returns a reference to the super class or to an interface of the return new TypeReference((METHOD_FORMAL_PARAMETER << 24) | (paramIndex << 16));
* 'implements' clause of a class. }
*
* @param itfIndex /**
* the index of an interface in the 'implements' clause of a * Returns a reference to the type of an exception, in a 'throws' clause of a method.
* class, or -1 to reference the super class of the class. *
* @return a reference to the given super type of a class. * @param exceptionIndex the index of an exception in a 'throws' clause of a method.
*/ * @return a reference to the type of the given exception.
public static TypeReference newSuperTypeReference(int itfIndex) { */
itfIndex &= 0xFFFF; public static TypeReference newExceptionReference(final int exceptionIndex) {
return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8)); return new TypeReference((THROWS << 24) | (exceptionIndex << 8));
} }
/** /**
* Returns a reference to the type of a formal parameter of a method. * Returns a reference to the type of the exception declared in a 'catch' clause of a method.
* *
* @param paramIndex * @param tryCatchBlockIndex the index of a try catch block (using the order in which they are
* the formal parameter index. * visited with visitTryCatchBlock).
* * @return a reference to the type of the given exception.
* @return a reference to the type of the given method formal parameter. */
*/ public static TypeReference newTryCatchReference(final int tryCatchBlockIndex) {
public static TypeReference newFormalParameterReference(int paramIndex) { return new TypeReference((EXCEPTION_PARAMETER << 24) | (tryCatchBlockIndex << 8));
return new TypeReference((METHOD_FORMAL_PARAMETER << 24) }
| (paramIndex << 16));
} /**
* Returns a reference to the type of a type argument in a constructor or method call or
/** * reference.
* Returns a reference to the type of an exception, in a 'throws' clause of *
* a method. * @param sort one of {@link #CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link
* * #METHOD_INVOCATION_TYPE_ARGUMENT}, {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link
* @param exceptionIndex * #METHOD_REFERENCE_TYPE_ARGUMENT}.
* the index of an exception in a 'throws' clause of a method. * @param argIndex the type argument index.
* * @return a reference to the type of the given type argument.
* @return a reference to the type of the given exception. */
*/ public static TypeReference newTypeArgumentReference(final int sort, final int argIndex) {
public static TypeReference newExceptionReference(int exceptionIndex) { return new TypeReference((sort << 24) | argIndex);
return new TypeReference((THROWS << 24) | (exceptionIndex << 8)); }
}
/**
/** * Returns the sort of this type reference.
* Returns a reference to the type of the exception declared in a 'catch' *
* clause of a method. * @return one of {@link #CLASS_TYPE_PARAMETER}, {@link #METHOD_TYPE_PARAMETER}, {@link
* * #CLASS_EXTENDS}, {@link #CLASS_TYPE_PARAMETER_BOUND}, {@link #METHOD_TYPE_PARAMETER_BOUND},
* @param tryCatchBlockIndex * {@link #FIELD}, {@link #METHOD_RETURN}, {@link #METHOD_RECEIVER}, {@link
* the index of a try catch block (using the order in which they * #METHOD_FORMAL_PARAMETER}, {@link #THROWS}, {@link #LOCAL_VARIABLE}, {@link
* are visited with visitTryCatchBlock). * #RESOURCE_VARIABLE}, {@link #EXCEPTION_PARAMETER}, {@link #INSTANCEOF}, {@link #NEW},
* * {@link #CONSTRUCTOR_REFERENCE}, {@link #METHOD_REFERENCE}, {@link #CAST}, {@link
* @return a reference to the type of the given exception. * #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link #METHOD_INVOCATION_TYPE_ARGUMENT}, {@link
*/ * #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link #METHOD_REFERENCE_TYPE_ARGUMENT}.
public static TypeReference newTryCatchReference(int tryCatchBlockIndex) { */
return new TypeReference((EXCEPTION_PARAMETER << 24) public int getSort() {
| (tryCatchBlockIndex << 8)); return targetTypeAndInfo >>> 24;
} }
/** /**
* Returns a reference to the type of a type argument in a constructor or * Returns the index of the type parameter referenced by this type reference. This method must
* method call or reference. * only be used for type references whose sort is {@link #CLASS_TYPE_PARAMETER}, {@link
* * #METHOD_TYPE_PARAMETER}, {@link #CLASS_TYPE_PARAMETER_BOUND} or {@link
* @param sort * #METHOD_TYPE_PARAMETER_BOUND}.
* {@link #CAST CAST}, *
* {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT * @return a type parameter index.
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, */
* {@link #METHOD_INVOCATION_TYPE_ARGUMENT public int getTypeParameterIndex() {
* METHOD_INVOCATION_TYPE_ARGUMENT}, return (targetTypeAndInfo & 0x00FF0000) >> 16;
* {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT }
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
* {@link #METHOD_REFERENCE_TYPE_ARGUMENT /**
* METHOD_REFERENCE_TYPE_ARGUMENT}. * Returns the index of the type parameter bound, within the type parameter {@link
* @param argIndex * #getTypeParameterIndex}, referenced by this type reference. This method must only be used for
* the type argument index. * type references whose sort is {@link #CLASS_TYPE_PARAMETER_BOUND} or {@link
* * #METHOD_TYPE_PARAMETER_BOUND}.
* @return a reference to the type of the given type argument. *
*/ * @return a type parameter bound index.
public static TypeReference newTypeArgumentReference(int sort, int argIndex) { */
return new TypeReference((sort << 24) | argIndex); public int getTypeParameterBoundIndex() {
} return (targetTypeAndInfo & 0x0000FF00) >> 8;
}
/**
* Returns the sort of this type reference. /**
* * Returns the index of the "super type" of a class that is referenced by this type reference.
* @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}, * This method must only be used for type references whose sort is {@link #CLASS_EXTENDS}.
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}, *
* {@link #CLASS_EXTENDS CLASS_EXTENDS}, * @return the index of an interface in the 'implements' clause of a class, or -1 if this type
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND}, * reference references the type of the super class.
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}, */
* {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN}, public int getSuperTypeIndex() {
* {@link #METHOD_RECEIVER METHOD_RECEIVER}, return (short) ((targetTypeAndInfo & 0x00FFFF00) >> 8);
* {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}, }
* {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
* {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE}, /**
* {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER}, * Returns the index of the formal parameter whose type is referenced by this type reference. This
* {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW}, * method must only be used for type references whose sort is {@link #METHOD_FORMAL_PARAMETER}.
* {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, *
* {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST}, * @return a formal parameter index.
* {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT */
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, public int getFormalParameterIndex() {
* {@link #METHOD_INVOCATION_TYPE_ARGUMENT return (targetTypeAndInfo & 0x00FF0000) >> 16;
* METHOD_INVOCATION_TYPE_ARGUMENT}, }
* {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or /**
* {@link #METHOD_REFERENCE_TYPE_ARGUMENT * Returns the index of the exception, in a 'throws' clause of a method, whose type is referenced
* METHOD_REFERENCE_TYPE_ARGUMENT}. * by this type reference. This method must only be used for type references whose sort is {@link
*/ * #THROWS}.
public int getSort() { *
return value >>> 24; * @return the index of an exception in the 'throws' clause of a method.
} */
public int getExceptionIndex() {
/** return (targetTypeAndInfo & 0x00FFFF00) >> 8;
* Returns the index of the type parameter referenced by this type }
* reference. This method must only be used for type references whose sort
* is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER}, /**
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}, * Returns the index of the try catch block (using the order in which they are visited with
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or * visitTryCatchBlock), whose 'catch' type is referenced by this type reference. This method must
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}. * only be used for type references whose sort is {@link #EXCEPTION_PARAMETER} .
* *
* @return a type parameter index. * @return the index of an exception in the 'throws' clause of a method.
*/ */
public int getTypeParameterIndex() { public int getTryCatchBlockIndex() {
return (value & 0x00FF0000) >> 16; return (targetTypeAndInfo & 0x00FFFF00) >> 8;
} }
/** /**
* Returns the index of the type parameter bound, within the type parameter * Returns the index of the type argument referenced by this type reference. This method must only
* {@link #getTypeParameterIndex}, referenced by this type reference. This * be used for type references whose sort is {@link #CAST}, {@link
* method must only be used for type references whose sort is * #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link #METHOD_INVOCATION_TYPE_ARGUMENT}, {@link
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or * #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link #METHOD_REFERENCE_TYPE_ARGUMENT}.
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}. *
* * @return a type parameter index.
* @return a type parameter bound index. */
*/ public int getTypeArgumentIndex() {
public int getTypeParameterBoundIndex() { return targetTypeAndInfo & 0xFF;
return (value & 0x0000FF00) >> 8; }
}
/**
/** * Returns the int encoded value of this type reference, suitable for use in visit methods related
* Returns the index of the "super type" of a class that is referenced by * to type annotations, like visitTypeAnnotation.
* this type reference. This method must only be used for type references *
* whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}. * @return the int encoded value of this type reference.
* */
* @return the index of an interface in the 'implements' clause of a class, public int getValue() {
* or -1 if this type reference references the type of the super return targetTypeAndInfo;
* class. }
*/
public int getSuperTypeIndex() { /**
return (short) ((value & 0x00FFFF00) >> 8); * Puts the given target_type and target_info JVMS structures into the given ByteVector.
} *
* @param targetTypeAndInfo a target_type and a target_info structures encoded as in {@link
/** * #targetTypeAndInfo}. LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported.
* Returns the index of the formal parameter whose type is referenced by * @param output where the type reference must be put.
* this type reference. This method must only be used for type references */
* whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}. static void putTarget(final int targetTypeAndInfo, final ByteVector output) {
* switch (targetTypeAndInfo >>> 24) {
* @return a formal parameter index. case CLASS_TYPE_PARAMETER:
*/ case METHOD_TYPE_PARAMETER:
public int getFormalParameterIndex() { case METHOD_FORMAL_PARAMETER:
return (value & 0x00FF0000) >> 16; output.putShort(targetTypeAndInfo >>> 16);
} break;
case FIELD:
/** case METHOD_RETURN:
* Returns the index of the exception, in a 'throws' clause of a method, case METHOD_RECEIVER:
* whose type is referenced by this type reference. This method must only be output.putByte(targetTypeAndInfo >>> 24);
* used for type references whose sort is {@link #THROWS THROWS}. break;
* case CAST:
* @return the index of an exception in the 'throws' clause of a method. case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
*/ case METHOD_INVOCATION_TYPE_ARGUMENT:
public int getExceptionIndex() { case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
return (value & 0x00FFFF00) >> 8; case METHOD_REFERENCE_TYPE_ARGUMENT:
} output.putInt(targetTypeAndInfo);
break;
/** case CLASS_EXTENDS:
* Returns the index of the try catch block (using the order in which they case CLASS_TYPE_PARAMETER_BOUND:
* are visited with visitTryCatchBlock), whose 'catch' type is referenced by case METHOD_TYPE_PARAMETER_BOUND:
* this type reference. This method must only be used for type references case THROWS:
* whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} . case EXCEPTION_PARAMETER:
* case INSTANCEOF:
* @return the index of an exception in the 'throws' clause of a method. case NEW:
*/ case CONSTRUCTOR_REFERENCE:
public int getTryCatchBlockIndex() { case METHOD_REFERENCE:
return (value & 0x00FFFF00) >> 8; output.put12(targetTypeAndInfo >>> 24, (targetTypeAndInfo & 0xFFFF00) >> 8);
} break;
default:
/** throw new IllegalArgumentException();
* Returns the index of the type argument referenced by this type reference.
* This method must only be used for type references whose sort is
* {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
* CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
* {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT},
* {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
* CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
* {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}.
*
* @return a type parameter index.
*/
public int getTypeArgumentIndex() {
return value & 0xFF;
}
/**
* Returns the int encoded value of this type reference, suitable for use in
* visit methods related to type annotations, like visitTypeAnnotation.
*
* @return the int encoded value of this type reference.
*/
public int getValue() {
return value;
} }
}
} }

View File

@@ -1,6 +1,6 @@
/** /**
* Spring's repackaging of * Spring's repackaging of
* <a href="http://asm.ow2.org">ASM</a> * <a href="https://gitlab.ow2.org/asm/asm">ASM</a>
* (for internal use only). * (for internal use only).
* *
* <p>This repackaging technique avoids any potential conflicts with * <p>This repackaging technique avoids any potential conflicts with