Upgrade to ASM master (6.2+) and CGLIB 3.2.7
Issue: SPR-16398
This commit is contained in:
parent
aabc5d9766
commit
a1d209726c
|
|
@ -7,11 +7,11 @@ dependencyManagement {
|
|||
}
|
||||
}
|
||||
|
||||
// As of Spring 4.0.3, spring-core includes asm 5.x and repackages cglib 3.2, inlining
|
||||
// both into the spring-core jar. cglib 3.2 itself depends on asm 5.x and is therefore
|
||||
// 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.6+ itself depends on asm 6.x and is therefore
|
||||
// further transformed by the JarJar task to depend on org.springframework.asm; this
|
||||
// avoids including two different copies of asm unnecessarily.
|
||||
def cglibVersion = "3.2.6"
|
||||
def cglibVersion = "3.2.7"
|
||||
def objenesisVersion = "2.6"
|
||||
|
||||
configurations {
|
||||
|
|
|
|||
|
|
@ -1,169 +1,150 @@
|
|||
/***
|
||||
* 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.
|
||||
*/
|
||||
// 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 visitor to visit a Java annotation. The methods of this class must be
|
||||
* called in the following order: ( <tt>visit</tt> | <tt>visitEnum</tt> |
|
||||
* <tt>visitAnnotation</tt> | <tt>visitArray</tt> )* <tt>visitEnd</tt>.
|
||||
*
|
||||
* A visitor to visit a Java annotation. The methods of this class must be called in the following
|
||||
* order: ( <tt>visit</tt> | <tt>visitEnum</tt> | <tt>visitAnnotation</tt> | <tt>visitArray</tt> )*
|
||||
* <tt>visitEnd</tt>.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
* @author Eugene Kuleshov
|
||||
*/
|
||||
public abstract class AnnotationVisitor {
|
||||
|
||||
/**
|
||||
* The ASM API version implemented by this visitor. The value of this field
|
||||
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
*/
|
||||
protected final int api;
|
||||
/**
|
||||
* The ASM API version implemented by this visitor. The value of this field must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7_EXPERIMENTAL}.
|
||||
*/
|
||||
protected final int api;
|
||||
|
||||
/**
|
||||
* The annotation visitor to which this visitor must delegate method calls.
|
||||
* May be null.
|
||||
*/
|
||||
protected AnnotationVisitor av;
|
||||
/** The annotation visitor to which this visitor must delegate method calls. May be null. */
|
||||
protected AnnotationVisitor av;
|
||||
|
||||
/**
|
||||
* 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} or {@link Opcodes#ASM6}.
|
||||
*/
|
||||
public AnnotationVisitor(final int api) {
|
||||
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}.
|
||||
*/
|
||||
public AnnotationVisitor(final int api) {
|
||||
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}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be one
|
||||
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
* @param av
|
||||
* the annotation visitor to which this visitor must delegate
|
||||
* method calls. May be null.
|
||||
*/
|
||||
public AnnotationVisitor(final int api, final AnnotationVisitor av) {
|
||||
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.api = api;
|
||||
this.av = av;
|
||||
/**
|
||||
* Visits a primitive value of the annotation.
|
||||
*
|
||||
* @param name the value name.
|
||||
* @param value the actual value, whose type must be {@link Byte}, {@link Boolean}, {@link
|
||||
* Character}, {@link Short}, {@link Integer} , {@link Long}, {@link Float}, {@link Double},
|
||||
* {@link String} or {@link Type} of {@link Type#OBJECT} or {@link Type#ARRAY} sort. This
|
||||
* value can also be an array of byte, boolean, short, char, int, long, float or double values
|
||||
* (this is equivalent to using {@link #visitArray} and visiting each array element in turn,
|
||||
* but is more convenient).
|
||||
*/
|
||||
public void visit(final String name, final Object value) {
|
||||
if (av != null) {
|
||||
av.visit(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a primitive value of the annotation.
|
||||
*
|
||||
* @param name
|
||||
* the value name.
|
||||
* @param value
|
||||
* the actual value, whose type must be {@link Byte},
|
||||
* {@link Boolean}, {@link Character}, {@link Short},
|
||||
* {@link Integer} , {@link Long}, {@link Float}, {@link Double},
|
||||
* {@link String} or {@link Type} of OBJECT or ARRAY sort. This
|
||||
* 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.
|
||||
*
|
||||
* @param name the value name.
|
||||
* @param descriptor the class descriptor of the enumeration class.
|
||||
* @param value the actual enumeration value.
|
||||
*/
|
||||
public void visitEnum(final String name, final String descriptor, final String value) {
|
||||
if (av != null) {
|
||||
av.visitEnum(name, descriptor, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits an enumeration value of the annotation.
|
||||
*
|
||||
* @param name
|
||||
* the value name.
|
||||
* @param desc
|
||||
* the class descriptor of the enumeration class.
|
||||
* @param value
|
||||
* the actual enumeration value.
|
||||
*/
|
||||
public void visitEnum(String name, String desc, String value) {
|
||||
if (av != null) {
|
||||
av.visitEnum(name, desc, value);
|
||||
}
|
||||
/**
|
||||
* Visits a nested annotation value of the annotation.
|
||||
*
|
||||
* @param name the value name.
|
||||
* @param descriptor the class descriptor of the nested annotation class.
|
||||
* @return a visitor to visit the actual nested annotation value, or <tt>null</tt> if this visitor
|
||||
* is not interested in visiting this nested annotation. <i>The nested annotation value must
|
||||
* be fully visited before calling other methods on this annotation visitor</i>.
|
||||
*/
|
||||
public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
|
||||
if (av != null) {
|
||||
return av.visitAnnotation(name, descriptor);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a nested annotation value of the annotation.
|
||||
*
|
||||
* @param name
|
||||
* the value name.
|
||||
* @param desc
|
||||
* the class descriptor of the nested annotation class.
|
||||
* @return a visitor to visit the actual nested annotation value, or
|
||||
* <tt>null</tt> if this visitor is not interested in visiting this
|
||||
* nested annotation. <i>The nested annotation value must be fully
|
||||
* visited before calling other methods on this annotation
|
||||
* visitor</i>.
|
||||
*/
|
||||
public AnnotationVisitor visitAnnotation(String name, String desc) {
|
||||
if (av != null) {
|
||||
return av.visitAnnotation(name, desc);
|
||||
}
|
||||
return null;
|
||||
/**
|
||||
* 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
|
||||
* visit}. This is what {@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(final String name) {
|
||||
if (av != null) {
|
||||
return av.visitArray(name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 visit}. This is what
|
||||
* {@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();
|
||||
}
|
||||
/** Visits the end of the annotation. */
|
||||
public void visitEnd() {
|
||||
if (av != null) {
|
||||
av.visitEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,371 +1,418 @@
|
|||
/***
|
||||
* 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.
|
||||
*/
|
||||
// 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 {@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 Eugene Kuleshov
|
||||
*/
|
||||
final class AnnotationWriter extends AnnotationVisitor {
|
||||
|
||||
/**
|
||||
* The class writer to which this annotation must be added.
|
||||
*/
|
||||
private final ClassWriter cw;
|
||||
/** Where the constants used in this AnnotationWriter must be stored. */
|
||||
private final SymbolTable symbolTable;
|
||||
|
||||
/**
|
||||
* The number of values in this annotation.
|
||||
*/
|
||||
private int size;
|
||||
/**
|
||||
* Whether values are named or not. AnnotationWriter instances used for annotation default and
|
||||
* annotation arrays use unnamed values (i.e. they generate an 'element_value' structure for each
|
||||
* value, instead of an element_name_index followed by an element_value).
|
||||
*/
|
||||
private final boolean useNamedValues;
|
||||
|
||||
/**
|
||||
* <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation
|
||||
* writers used for annotation default and annotation arrays use unnamed
|
||||
* values.
|
||||
*/
|
||||
private final boolean named;
|
||||
/**
|
||||
* The 'annotation' or 'type_annotation' JVMS structure corresponding to the annotation values
|
||||
* visited so far. All the fields of these structures, except the last one - the
|
||||
* element_value_pairs array, must be set before this ByteVector is passed to the constructor
|
||||
* (num_element_value_pairs can be set to 0, it is reset to the correct value in {@link
|
||||
* #visitEnd()}). The element_value_pairs array is filled incrementally in the various visit()
|
||||
* methods.
|
||||
*
|
||||
* <p>Note: as an exception to the above rules, for AnnotationDefault attributes (which contain a
|
||||
* single element_value by definition), this ByteVector is initially empty when passed to the
|
||||
* constructor, and {@link #numElementValuePairsOffset} is set to -1.
|
||||
*/
|
||||
private final ByteVector annotation;
|
||||
|
||||
/**
|
||||
* The annotation values in bytecode form. This byte vector only contains
|
||||
* the values themselves, i.e. the number of values must be stored as a
|
||||
* unsigned short just before these bytes.
|
||||
*/
|
||||
private final ByteVector bv;
|
||||
/**
|
||||
* The offset in {@link #annotation} where {@link #numElementValuePairs} must be stored (or -1 for
|
||||
* the case of AnnotationDefault attributes).
|
||||
*/
|
||||
private final int numElementValuePairsOffset;
|
||||
|
||||
/**
|
||||
* The byte vector to be used to store the number of values of this
|
||||
* annotation. See {@link #bv}.
|
||||
*/
|
||||
private final ByteVector parent;
|
||||
/** The number of element value pairs visited so far. */
|
||||
private int numElementValuePairs;
|
||||
|
||||
/**
|
||||
* Where the number of values of this annotation must be stored in
|
||||
* {@link #parent}.
|
||||
*/
|
||||
private final int offset;
|
||||
/**
|
||||
* The previous AnnotationWriter. This field is used to store the list of annotations of a
|
||||
* Runtime[In]Visible[Type]Annotations attribute. It is unused for nested or array annotations
|
||||
* (annotation values of annotation type), or for AnnotationDefault attributes.
|
||||
*/
|
||||
private final AnnotationWriter previousAnnotation;
|
||||
|
||||
/**
|
||||
* Next annotation writer. This field is used to store annotation lists.
|
||||
*/
|
||||
AnnotationWriter next;
|
||||
/**
|
||||
* The next AnnotationWriter. This field is used to store the list of annotations of a
|
||||
* Runtime[In]Visible[Type]Annotations attribute. It is unused for nested or array annotations
|
||||
* (annotation values of annotation type), or for AnnotationDefault attributes.
|
||||
*/
|
||||
private AnnotationWriter nextAnnotation;
|
||||
|
||||
/**
|
||||
* Previous annotation writer. This field is used to store annotation lists.
|
||||
*/
|
||||
AnnotationWriter prev;
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Constructors
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs a new {@link AnnotationWriter}.
|
||||
*
|
||||
* @param cw
|
||||
* the class writer to which this annotation must be added.
|
||||
* @param named
|
||||
* <tt>true<tt> if values are named, <tt>false</tt> otherwise.
|
||||
* @param bv
|
||||
* where the annotation values must be stored.
|
||||
* @param parent
|
||||
* where the number of annotation values must be stored.
|
||||
* @param offset
|
||||
* where in <tt>parent</tt> the number of annotation values must
|
||||
* be stored.
|
||||
*/
|
||||
AnnotationWriter(final ClassWriter cw, final boolean named,
|
||||
final ByteVector bv, final ByteVector parent, final int offset) {
|
||||
super(Opcodes.ASM6);
|
||||
this.cw = cw;
|
||||
this.named = named;
|
||||
this.bv = bv;
|
||||
this.parent = parent;
|
||||
this.offset = offset;
|
||||
/**
|
||||
* Constructs a new {@link AnnotationWriter}.
|
||||
*
|
||||
* @param symbolTable where the constants used in this AnnotationWriter must be stored.
|
||||
* @param useNamedValues whether values are named or not. AnnotationDefault and annotation arrays
|
||||
* use unnamed values.
|
||||
* @param annotation where the 'annotation' or 'type_annotation' JVMS structure corresponding to
|
||||
* the visited content must be stored. This ByteVector must already contain all the fields of
|
||||
* the structure except the last one (the element_value_pairs array).
|
||||
* @param previousAnnotation the previously visited annotation of the
|
||||
* Runtime[In]Visible[Type]Annotations attribute to which this annotation belongs, or null in
|
||||
* other cases (e.g. nested or array annotations).
|
||||
*/
|
||||
AnnotationWriter(
|
||||
final SymbolTable symbolTable,
|
||||
final boolean useNamedValues,
|
||||
final ByteVector annotation,
|
||||
final AnnotationWriter previousAnnotation) {
|
||||
super(Opcodes.ASM6);
|
||||
this.symbolTable = symbolTable;
|
||||
this.useNamedValues = useNamedValues;
|
||||
this.annotation = annotation;
|
||||
// By hypothesis, num_element_value_pairs is stored in the last unsigned short of 'annotation'.
|
||||
this.numElementValuePairsOffset = annotation.length == 0 ? -1 : annotation.length - 2;
|
||||
this.previousAnnotation = previousAnnotation;
|
||||
if (previousAnnotation != null) {
|
||||
previousAnnotation.nextAnnotation = this;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// 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) {
|
||||
++size;
|
||||
if (named) {
|
||||
bv.putShort(cw.newUTF8(name));
|
||||
}
|
||||
if (value instanceof String) {
|
||||
bv.put12('s', cw.newUTF8((String) value));
|
||||
} else if (value instanceof Byte) {
|
||||
bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index);
|
||||
} else if (value instanceof Boolean) {
|
||||
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);
|
||||
}
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Implementation of the AnnotationVisitor abstract class
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void visit(final String name, final Object value) {
|
||||
// Case of an element_value with a const_value_index, class_info_index or array_index field.
|
||||
// See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1.
|
||||
++numElementValuePairs;
|
||||
if (useNamedValues) {
|
||||
annotation.putShort(symbolTable.addConstantUtf8(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnum(final String name, final String desc,
|
||||
final String value) {
|
||||
++size;
|
||||
if (named) {
|
||||
bv.putShort(cw.newUTF8(name));
|
||||
}
|
||||
bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value));
|
||||
if (value instanceof String) {
|
||||
annotation.put12('s', symbolTable.addConstantUtf8((String) value));
|
||||
} else if (value instanceof Byte) {
|
||||
annotation.put12('B', symbolTable.addConstantInteger(((Byte) value).byteValue()).index);
|
||||
} else if (value instanceof Boolean) {
|
||||
int booleanValue = ((Boolean) value).booleanValue() ? 1 : 0;
|
||||
annotation.put12('Z', symbolTable.addConstantInteger(booleanValue).index);
|
||||
} else if (value instanceof Character) {
|
||||
annotation.put12('C', symbolTable.addConstantInteger(((Character) value).charValue()).index);
|
||||
} else if (value instanceof Short) {
|
||||
annotation.put12('S', symbolTable.addConstantInteger(((Short) value).shortValue()).index);
|
||||
} else if (value instanceof Type) {
|
||||
annotation.put12('c', symbolTable.addConstantUtf8(((Type) value).getDescriptor()));
|
||||
} else if (value instanceof byte[]) {
|
||||
byte[] byteArray = (byte[]) value;
|
||||
annotation.put12('[', byteArray.length);
|
||||
for (byte byteValue : byteArray) {
|
||||
annotation.put12('B', symbolTable.addConstantInteger(byteValue).index);
|
||||
}
|
||||
} else if (value instanceof boolean[]) {
|
||||
boolean[] booleanArray = (boolean[]) value;
|
||||
annotation.put12('[', booleanArray.length);
|
||||
for (boolean booleanValue : booleanArray) {
|
||||
annotation.put12('Z', symbolTable.addConstantInteger(booleanValue ? 1 : 0).index);
|
||||
}
|
||||
} else if (value instanceof short[]) {
|
||||
short[] shortArray = (short[]) value;
|
||||
annotation.put12('[', shortArray.length);
|
||||
for (short shortValue : shortArray) {
|
||||
annotation.put12('S', symbolTable.addConstantInteger(shortValue).index);
|
||||
}
|
||||
} else if (value instanceof char[]) {
|
||||
char[] charArray = (char[]) value;
|
||||
annotation.put12('[', charArray.length);
|
||||
for (char charValue : charArray) {
|
||||
annotation.put12('C', symbolTable.addConstantInteger(charValue).index);
|
||||
}
|
||||
} else if (value instanceof int[]) {
|
||||
int[] intArray = (int[]) value;
|
||||
annotation.put12('[', intArray.length);
|
||||
for (int intValue : intArray) {
|
||||
annotation.put12('I', symbolTable.addConstantInteger(intValue).index);
|
||||
}
|
||||
} else if (value instanceof long[]) {
|
||||
long[] longArray = (long[]) value;
|
||||
annotation.put12('[', longArray.length);
|
||||
for (long longValue : longArray) {
|
||||
annotation.put12('J', symbolTable.addConstantLong(longValue).index);
|
||||
}
|
||||
} else if (value instanceof float[]) {
|
||||
float[] floatArray = (float[]) value;
|
||||
annotation.put12('[', floatArray.length);
|
||||
for (float floatValue : floatArray) {
|
||||
annotation.put12('F', symbolTable.addConstantFloat(floatValue).index);
|
||||
}
|
||||
} else if (value instanceof double[]) {
|
||||
double[] doubleArray = (double[]) value;
|
||||
annotation.put12('[', doubleArray.length);
|
||||
for (double doubleValue : doubleArray) {
|
||||
annotation.put12('D', symbolTable.addConstantDouble(doubleValue).index);
|
||||
}
|
||||
} else {
|
||||
Symbol symbol = symbolTable.addConstant(value);
|
||||
annotation.put12(".s.IFJDCS".charAt(symbol.tag), symbol.index);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(final String name,
|
||||
final String desc) {
|
||||
++size;
|
||||
if (named) {
|
||||
bv.putShort(cw.newUTF8(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);
|
||||
@Override
|
||||
public void visitEnum(final String name, final String descriptor, final String value) {
|
||||
// Case of an element_value with an enum_const_value field.
|
||||
// See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1.
|
||||
++numElementValuePairs;
|
||||
if (useNamedValues) {
|
||||
annotation.putShort(symbolTable.addConstantUtf8(name));
|
||||
}
|
||||
annotation
|
||||
.put12('e', symbolTable.addConstantUtf8(descriptor))
|
||||
.putShort(symbolTable.addConstantUtf8(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitArray(final String name) {
|
||||
++size;
|
||||
if (named) {
|
||||
bv.putShort(cw.newUTF8(name));
|
||||
}
|
||||
// write tag, and reserve space for array size
|
||||
bv.put12('[', 0);
|
||||
return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(final String name, final String descriptor) {
|
||||
// Case of an element_value with an annotation_value field.
|
||||
// See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1.
|
||||
++numElementValuePairs;
|
||||
if (useNamedValues) {
|
||||
annotation.putShort(symbolTable.addConstantUtf8(name));
|
||||
}
|
||||
// Write tag and type_index, and reserve 2 bytes for num_element_value_pairs.
|
||||
annotation.put12('@', symbolTable.addConstantUtf8(descriptor)).putShort(0);
|
||||
return new AnnotationWriter(symbolTable, annotation, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
if (parent != null) {
|
||||
byte[] data = parent.data;
|
||||
data[offset] = (byte) (size >>> 8);
|
||||
data[offset + 1] = (byte) size;
|
||||
}
|
||||
@Override
|
||||
public AnnotationVisitor visitArray(final String name) {
|
||||
// Case of an element_value with an array_value field.
|
||||
// https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.1
|
||||
++numElementValuePairs;
|
||||
if (useNamedValues) {
|
||||
annotation.putShort(symbolTable.addConstantUtf8(name));
|
||||
}
|
||||
// Write tag, and reserve 2 bytes for num_values. Here we take advantage of the fact that the
|
||||
// end of an element_value of array type is similar to the end of an 'annotation' structure: an
|
||||
// unsigned short num_values followed by num_values element_value, versus an unsigned short
|
||||
// num_element_value_pairs, followed by num_element_value_pairs { element_name_index,
|
||||
// element_value } tuples. This allows us to use an AnnotationWriter with unnamed values to
|
||||
// visit the array elements. Its num_element_value_pairs will correspond to the number of array
|
||||
// elements and will be stored in what is in fact num_values.
|
||||
annotation.put12('[', 0);
|
||||
return new AnnotationWriter(symbolTable, /* useNamedValues = */ false, annotation, null);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Utility methods
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Returns the size of this annotation writer list.
|
||||
*
|
||||
* @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;
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
if (numElementValuePairsOffset != -1) {
|
||||
byte[] data = annotation.data;
|
||||
data[numElementValuePairsOffset] = (byte) (numElementValuePairs >>> 8);
|
||||
data[numElementValuePairsOffset + 1] = (byte) numElementValuePairs;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the annotations of this annotation writer list into the given byte
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Utility methods
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Puts the given annotation lists into the given byte vector.
|
||||
*
|
||||
* @param panns
|
||||
* an array of annotation writer lists.
|
||||
* @param off
|
||||
* index of the first annotation to be written.
|
||||
* @param out
|
||||
* where the annotations must be put.
|
||||
*/
|
||||
static void put(final AnnotationWriter[] panns, final int off,
|
||||
final ByteVector out) {
|
||||
int size = 1 + 2 * (panns.length - off);
|
||||
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;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Returns the size of a Runtime[In]Visible[Type]Annotations attribute containing this annotation
|
||||
* and all its <i>predecessors</i> (see {@link #previousAnnotation}. Also adds the attribute name
|
||||
* to the constant pool of the class (if not null).
|
||||
*
|
||||
* @param attributeName one of "Runtime[In]Visible[Type]Annotations", or null.
|
||||
* @return the size in bytes of a Runtime[In]Visible[Type]Annotations attribute containing this
|
||||
* annotation and all its predecessors. This includes the size of the attribute_name_index and
|
||||
* attribute_length fields.
|
||||
*/
|
||||
int computeAnnotationsSize(final String attributeName) {
|
||||
if (attributeName != null) {
|
||||
symbolTable.addConstantUtf8(attributeName);
|
||||
}
|
||||
// The attribute_name_index, attribute_length and num_annotations fields use 8 bytes.
|
||||
int attributeSize = 8;
|
||||
AnnotationWriter annotationWriter = this;
|
||||
while (annotationWriter != null) {
|
||||
attributeSize += annotationWriter.annotation.length;
|
||||
annotationWriter = annotationWriter.previousAnnotation;
|
||||
}
|
||||
return attributeSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the given type reference and type path into the given bytevector.
|
||||
* LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported.
|
||||
*
|
||||
* @param typeRef
|
||||
* a reference to the annotated type. See {@link TypeReference}.
|
||||
* @param typePath
|
||||
* the path to the annotated type argument, wildcard bound, array
|
||||
* element type, or static inner type within 'typeRef'. May be
|
||||
* <tt>null</tt> if the annotation targets 'typeRef' as a whole.
|
||||
* @param out
|
||||
* where the type reference and type path must be put.
|
||||
*/
|
||||
static void putTarget(int typeRef, TypePath typePath, ByteVector out) {
|
||||
switch (typeRef >>> 24) {
|
||||
case 0x00: // CLASS_TYPE_PARAMETER
|
||||
case 0x01: // METHOD_TYPE_PARAMETER
|
||||
case 0x16: // METHOD_FORMAL_PARAMETER
|
||||
out.putShort(typeRef >>> 16);
|
||||
break;
|
||||
case 0x13: // FIELD
|
||||
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);
|
||||
}
|
||||
/**
|
||||
* Puts a Runtime[In]Visible[Type]Annotations attribute containing this annotations and all its
|
||||
* <i>predecessors</i> (see {@link #previousAnnotation} in the given ByteVector. Annotations are
|
||||
* put in the same order they have been visited.
|
||||
*
|
||||
* @param attributeNameIndex the constant pool index of the attribute name (one of
|
||||
* "Runtime[In]Visible[Type]Annotations").
|
||||
* @param output where the attribute must be put.
|
||||
*/
|
||||
void putAnnotations(final int attributeNameIndex, final ByteVector output) {
|
||||
int attributeLength = 2; // For num_annotations.
|
||||
int numAnnotations = 0;
|
||||
AnnotationWriter annotationWriter = this;
|
||||
AnnotationWriter firstAnnotation = null;
|
||||
while (annotationWriter != null) {
|
||||
// In case the user forgot to call visitEnd().
|
||||
annotationWriter.visitEnd();
|
||||
attributeLength += annotationWriter.annotation.length;
|
||||
numAnnotations++;
|
||||
firstAnnotation = annotationWriter;
|
||||
annotationWriter = annotationWriter.previousAnnotation;
|
||||
}
|
||||
output.putShort(attributeNameIndex);
|
||||
output.putInt(attributeLength);
|
||||
output.putShort(numAnnotations);
|
||||
annotationWriter = firstAnnotation;
|
||||
while (annotationWriter != null) {
|
||||
output.putByteArray(annotationWriter.annotation.data, 0, annotationWriter.annotation.length);
|
||||
annotationWriter = annotationWriter.nextAnnotation;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,255 +1,323 @@
|
|||
/***
|
||||
* 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.
|
||||
*/
|
||||
// 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 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 Eugene Kuleshov
|
||||
*/
|
||||
public class Attribute {
|
||||
|
||||
/**
|
||||
* The type of this attribute.
|
||||
*/
|
||||
public final String type;
|
||||
/** The type of this attribute, also called its name in the JVMS. */
|
||||
public final String type;
|
||||
|
||||
/**
|
||||
* The raw value of this attribute, used only for unknown attributes.
|
||||
*/
|
||||
byte[] value;
|
||||
/**
|
||||
* 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>
|
||||
* included.
|
||||
*/
|
||||
private byte[] content;
|
||||
|
||||
/**
|
||||
* The next attribute in this attribute list. May be <tt>null</tt>.
|
||||
*/
|
||||
Attribute next;
|
||||
/**
|
||||
* 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 nextAttribute;
|
||||
|
||||
/**
|
||||
* Constructs a new empty attribute.
|
||||
*
|
||||
* @param type
|
||||
* the type of the attribute.
|
||||
*/
|
||||
protected Attribute(final String type) {
|
||||
this.type = type;
|
||||
/**
|
||||
* Constructs a new empty attribute.
|
||||
*
|
||||
* @param type the type of the attribute.
|
||||
*/
|
||||
protected Attribute(final String 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
|
||||
* 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 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.
|
||||
* @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 = 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.
|
||||
*
|
||||
* @return <tt>true</tt> if this type of attribute is a code attribute.
|
||||
*/
|
||||
public boolean isCodeAttribute() {
|
||||
return false;
|
||||
/**
|
||||
* 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 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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 null;
|
||||
}
|
||||
/** A set of attribute prototypes (attributes with the same type are considered equal). */
|
||||
static final class Set {
|
||||
|
||||
/**
|
||||
* 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 static final int SIZE_INCREMENT = 6;
|
||||
|
||||
/**
|
||||
* Returns the byte array form of this attribute.
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
private int size;
|
||||
private Attribute[] data = new Attribute[SIZE_INCREMENT];
|
||||
|
||||
/**
|
||||
* Returns the length of the attribute list that begins with this attribute.
|
||||
*
|
||||
* @return the length of the attribute list that begins with this attribute.
|
||||
*/
|
||||
final int getCount() {
|
||||
int count = 0;
|
||||
Attribute attr = this;
|
||||
while (attr != null) {
|
||||
count += 1;
|
||||
attr = attr.next;
|
||||
void addAttributes(final Attribute attributeList) {
|
||||
Attribute attribute = attributeList;
|
||||
while (attribute != null) {
|
||||
if (!contains(attribute)) {
|
||||
add(attribute);
|
||||
}
|
||||
return count;
|
||||
attribute = attribute.nextAttribute;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of all the attributes in this attribute list.
|
||||
*
|
||||
* @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.
|
||||
* @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;
|
||||
Attribute[] toArray() {
|
||||
Attribute[] result = new Attribute[size];
|
||||
System.arraycopy(data, 0, result, 0, size);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes all the attributes of this attribute list in the given byte
|
||||
* vector.
|
||||
*
|
||||
* @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;
|
||||
private boolean contains(final Attribute attribute) {
|
||||
for (int i = 0; i < size; ++i) {
|
||||
if (data[i].type.equals(attribute.type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,339 +1,360 @@
|
|||
/***
|
||||
* 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.
|
||||
*/
|
||||
// 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 dynamically extensible vector of bytes. This class is roughly equivalent to
|
||||
* a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
|
||||
*
|
||||
* A dynamically extensible vector of bytes. This class is roughly equivalent to a DataOutputStream
|
||||
* on top of a ByteArrayOutputStream, but is more efficient.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class ByteVector {
|
||||
|
||||
/**
|
||||
* The content of this vector.
|
||||
*/
|
||||
byte[] data;
|
||||
/** The content of this vector. Only the first {@link #length} bytes contain real data. */
|
||||
byte[] data;
|
||||
|
||||
/**
|
||||
* Actual number of bytes in this vector.
|
||||
*/
|
||||
int length;
|
||||
/** The actual number of bytes in this vector. */
|
||||
int length;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ByteVector ByteVector} with a default initial
|
||||
* size.
|
||||
*/
|
||||
public ByteVector() {
|
||||
data = new byte[64];
|
||||
/** Constructs a new {@link ByteVector} with a default initial capacity. */
|
||||
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
|
||||
* size.
|
||||
*
|
||||
* @param initialSize
|
||||
* the initial size of the byte vector to be constructed.
|
||||
*/
|
||||
public ByteVector(final int initialSize) {
|
||||
data = new byte[initialSize];
|
||||
/**
|
||||
* Puts two bytes into this byte vector. The byte vector is automatically enlarged if necessary.
|
||||
*
|
||||
* @param byteValue1 a byte.
|
||||
* @param byteValue2 another byte.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
final ByteVector put11(final int byteValue1, final int byteValue2) {
|
||||
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
|
||||
* enlarged if necessary.
|
||||
*
|
||||
* @param b
|
||||
* a byte.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putByte(final int b) {
|
||||
int length = this.length;
|
||||
if (length + 1 > data.length) {
|
||||
enlarge(1);
|
||||
}
|
||||
data[length++] = (byte) b;
|
||||
this.length = length;
|
||||
return this;
|
||||
/**
|
||||
* Puts a short into this byte vector. The byte vector is automatically enlarged if necessary.
|
||||
*
|
||||
* @param shortValue a short.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putShort(final int shortValue) {
|
||||
int currentLength = length;
|
||||
if (currentLength + 2 > data.length) {
|
||||
enlarge(2);
|
||||
}
|
||||
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
|
||||
* enlarged if necessary.
|
||||
*
|
||||
* @param b1
|
||||
* a byte.
|
||||
* @param b2
|
||||
* another byte.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
ByteVector put11(final int b1, final int b2) {
|
||||
int length = this.length;
|
||||
if (length + 2 > data.length) {
|
||||
enlarge(2);
|
||||
}
|
||||
byte[] data = this.data;
|
||||
data[length++] = (byte) b1;
|
||||
data[length++] = (byte) b2;
|
||||
this.length = length;
|
||||
return this;
|
||||
/**
|
||||
* Puts a byte and a short into this byte vector. The byte vector is automatically enlarged if
|
||||
* necessary.
|
||||
*
|
||||
* @param byteValue a byte.
|
||||
* @param shortValue a short.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
final ByteVector put12(final int byteValue, final int shortValue) {
|
||||
int currentLength = length;
|
||||
if (currentLength + 3 > data.length) {
|
||||
enlarge(3);
|
||||
}
|
||||
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
|
||||
* enlarged if necessary.
|
||||
*
|
||||
* @param s
|
||||
* a short.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putShort(final int s) {
|
||||
int length = this.length;
|
||||
if (length + 2 > data.length) {
|
||||
enlarge(2);
|
||||
}
|
||||
byte[] data = this.data;
|
||||
data[length++] = (byte) (s >>> 8);
|
||||
data[length++] = (byte) s;
|
||||
this.length = length;
|
||||
return this;
|
||||
/**
|
||||
* Puts two bytes and a short into this byte vector. The byte vector is automatically enlarged if
|
||||
* necessary.
|
||||
*
|
||||
* @param byteValue1 a byte.
|
||||
* @param byteValue2 another byte.
|
||||
* @param shortValue a short.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
final ByteVector put112(final int byteValue1, final int byteValue2, final int shortValue) {
|
||||
int currentLength = length;
|
||||
if (currentLength + 4 > data.length) {
|
||||
enlarge(4);
|
||||
}
|
||||
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
|
||||
* automatically enlarged if necessary.
|
||||
*
|
||||
* @param b
|
||||
* a byte.
|
||||
* @param s
|
||||
* a short.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
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;
|
||||
/**
|
||||
* Puts an int into this byte vector. The byte vector is automatically enlarged if necessary.
|
||||
*
|
||||
* @param intValue an int.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putInt(final int intValue) {
|
||||
int currentLength = length;
|
||||
if (currentLength + 4 > data.length) {
|
||||
enlarge(4);
|
||||
}
|
||||
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
|
||||
* enlarged if necessary.
|
||||
*
|
||||
* @param i
|
||||
* an int.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putInt(final int i) {
|
||||
int length = this.length;
|
||||
if (length + 4 > data.length) {
|
||||
enlarge(4);
|
||||
}
|
||||
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;
|
||||
/**
|
||||
* Puts one byte and two shorts into this byte vector. The byte vector is automatically enlarged
|
||||
* if necessary.
|
||||
*
|
||||
* @param byteValue a byte.
|
||||
* @param shortValue1 a short.
|
||||
* @param shortValue2 another short.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
final ByteVector put122(final int byteValue, final int shortValue1, final int shortValue2) {
|
||||
int currentLength = length;
|
||||
if (currentLength + 5 > data.length) {
|
||||
enlarge(5);
|
||||
}
|
||||
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
|
||||
* enlarged if necessary.
|
||||
*
|
||||
* @param l
|
||||
* a long.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putLong(final long l) {
|
||||
int length = this.length;
|
||||
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;
|
||||
/**
|
||||
* Puts a long into this byte vector. The byte vector is automatically enlarged if necessary.
|
||||
*
|
||||
* @param longValue a long.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putLong(final long longValue) {
|
||||
int currentLength = length;
|
||||
if (currentLength + 8 > data.length) {
|
||||
enlarge(8);
|
||||
}
|
||||
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
|
||||
* automatically enlarged if necessary.
|
||||
*
|
||||
* @param s
|
||||
* a String whose UTF8 encoded length must be less than 65536.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putUTF8(final String s) {
|
||||
int charLength = s.length();
|
||||
if (charLength > 65535) {
|
||||
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;
|
||||
/**
|
||||
* Puts an UTF8 string into this byte vector. The byte vector is automatically enlarged if
|
||||
* necessary.
|
||||
*
|
||||
* @param stringValue a String whose UTF8 encoded length must be less than 65536.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putUTF8(final String stringValue) {
|
||||
int charLength = stringValue.length();
|
||||
if (charLength > 65535) {
|
||||
throw new IllegalArgumentException("UTF8 string too large");
|
||||
}
|
||||
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
|
||||
* automatically enlarged if necessary. The string length is encoded in two
|
||||
* bytes before the encoded characters, if there is space for that (i.e. if
|
||||
* this.length - i - 2 >= 0).
|
||||
*
|
||||
* @param s
|
||||
* the String to encode.
|
||||
* @param i
|
||||
* the index of the first character to encode. The previous
|
||||
* characters are supposed to have already been encoded, using
|
||||
* only one byte per character.
|
||||
* @param maxByteLength
|
||||
* the maximum byte length of the encoded string, including the
|
||||
* already encoded characters.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
ByteVector encodeUTF8(final String s, int i, int maxByteLength) {
|
||||
int charLength = s.length();
|
||||
int byteLength = i;
|
||||
char c;
|
||||
for (int j = i; j < charLength; ++j) {
|
||||
c = s.charAt(j);
|
||||
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;
|
||||
/**
|
||||
* Puts an UTF8 string into this byte vector. The byte vector is automatically enlarged if
|
||||
* necessary. The string length is encoded in two bytes before the encoded characters, if there is
|
||||
* space for that (i.e. if this.length - offset - 2 >= 0).
|
||||
*
|
||||
* @param stringValue the String to encode.
|
||||
* @param offset the index of the first character to encode. The previous characters are supposed
|
||||
* to have already been encoded, using only one byte per character.
|
||||
* @param maxByteLength the maximum byte length of the encoded string, including the already
|
||||
* encoded characters.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
final ByteVector encodeUTF8(final String stringValue, final int offset, final int maxByteLength) {
|
||||
int charLength = stringValue.length();
|
||||
int byteLength = offset;
|
||||
for (int i = offset; i < charLength; ++i) {
|
||||
char charValue = stringValue.charAt(i);
|
||||
if (charValue >= '\u0001' && charValue <= '\u007F') {
|
||||
byteLength++;
|
||||
} else if (charValue <= '\u07FF') {
|
||||
byteLength += 2;
|
||||
} else {
|
||||
byteLength += 3;
|
||||
}
|
||||
}
|
||||
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
|
||||
* automatically enlarged if necessary.
|
||||
*
|
||||
* @param b
|
||||
* an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
|
||||
* null bytes into this byte vector.
|
||||
* @param off
|
||||
* index of the fist byte of b that must be copied.
|
||||
* @param len
|
||||
* number of bytes of b that must be copied.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putByteArray(final byte[] b, final int off, final int len) {
|
||||
if (length + len > data.length) {
|
||||
enlarge(len);
|
||||
}
|
||||
if (b != null) {
|
||||
System.arraycopy(b, off, data, length, len);
|
||||
}
|
||||
length += len;
|
||||
return this;
|
||||
/**
|
||||
* Puts an array of bytes into this byte vector. The byte vector is automatically enlarged if
|
||||
* necessary.
|
||||
*
|
||||
* @param byteArrayValue an array of bytes. May be <tt>null</tt> to put <tt>byteLength</tt> null
|
||||
* bytes into this byte vector.
|
||||
* @param byteOffset index of the first byte of byteArrayValue that must be copied.
|
||||
* @param byteLength number of bytes of byteArrayValue that must be copied.
|
||||
* @return this byte vector.
|
||||
*/
|
||||
public ByteVector putByteArray(
|
||||
final byte[] byteArrayValue, final int byteOffset, final int byteLength) {
|
||||
if (length + byteLength > data.length) {
|
||||
enlarge(byteLength);
|
||||
}
|
||||
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.
|
||||
*
|
||||
* @param size
|
||||
* number of additional bytes that this byte vector should be
|
||||
* able to receive.
|
||||
*/
|
||||
private void enlarge(final int size) {
|
||||
int length1 = 2 * data.length;
|
||||
int length2 = length + size;
|
||||
byte[] newData = new byte[length1 > length2 ? length1 : length2];
|
||||
System.arraycopy(data, 0, newData, 0, length);
|
||||
data = newData;
|
||||
}
|
||||
/**
|
||||
* Enlarges this byte vector so that it can receive 'size' more bytes.
|
||||
*
|
||||
* @param size number of additional bytes that this byte vector should be able to receive.
|
||||
*/
|
||||
private void enlarge(final int size) {
|
||||
int doubleCapacity = 2 * data.length;
|
||||
int minimalCapacity = length + size;
|
||||
byte[] newData = new byte[doubleCapacity > minimalCapacity ? doubleCapacity : minimalCapacity];
|
||||
System.arraycopy(data, 0, newData, 0, length);
|
||||
data = newData;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,344 +1,337 @@
|
|||
/***
|
||||
* 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.
|
||||
*/
|
||||
// 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 visitor to visit a Java class. The methods of this class must be called in
|
||||
* the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
|
||||
* <tt>visitModule</tt> ][ <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
|
||||
* <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (
|
||||
* <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )*
|
||||
* <tt>visitEnd</tt>.
|
||||
*
|
||||
* A visitor to visit a Java class. The methods of this class must be called in the following order:
|
||||
* <tt>visit</tt> [ <tt>visitSource</tt> ] [ <tt>visitModule</tt> ][ <tt>visitNestHost</tt> ][
|
||||
* <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> | <tt>visitTypeAnnotation</tt> |
|
||||
* <tt>visitAttribute</tt> )* ( <tt>visitNestMember</tt> | <tt>visitInnerClass</tt> |
|
||||
* <tt>visitField</tt> | <tt>visitMethod</tt> )* <tt>visitEnd</tt>.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public abstract class ClassVisitor {
|
||||
|
||||
/**
|
||||
* The ASM API version implemented by this visitor. The value of this field
|
||||
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
*/
|
||||
protected final int api;
|
||||
/**
|
||||
* The ASM API version implemented by this visitor. The value of this field must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7_EXPERIMENTAL}.
|
||||
*/
|
||||
protected final int api;
|
||||
|
||||
/**
|
||||
* The class visitor to which this visitor must delegate method calls. May
|
||||
* be null.
|
||||
*/
|
||||
protected ClassVisitor cv;
|
||||
/** The class visitor to which this visitor must delegate method calls. May be null. */
|
||||
protected ClassVisitor cv;
|
||||
|
||||
/**
|
||||
* 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} or {@link Opcodes#ASM6}.
|
||||
*/
|
||||
public ClassVisitor(final int api) {
|
||||
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}.
|
||||
*/
|
||||
public ClassVisitor(final int api) {
|
||||
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}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be one
|
||||
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
* @param cv
|
||||
* the class visitor to which this visitor must delegate method
|
||||
* calls. May be null.
|
||||
*/
|
||||
public ClassVisitor(final int api, final ClassVisitor cv) {
|
||||
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.api = api;
|
||||
this.cv = cv;
|
||||
/**
|
||||
* Visits the header of the class.
|
||||
*
|
||||
* @param version the class version. The minor version is stored in the 16 most significant bits,
|
||||
* and the major version in the 16 least significant bits.
|
||||
* @param access the class's access flags (see {@link Opcodes}). This parameter also indicates if
|
||||
* the class is deprecated.
|
||||
* @param name the internal name of the class (see {@link Type#getInternalName()}).
|
||||
* @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()}).
|
||||
* 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()}). May be <tt>null</tt>.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @param version
|
||||
* the class version.
|
||||
* @param access
|
||||
* the class's access flags (see {@link Opcodes}). This parameter
|
||||
* also indicates if the class is deprecated.
|
||||
* @param name
|
||||
* the internal name of the class (see
|
||||
* {@link Type#getInternalName() getInternalName}).
|
||||
* @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.
|
||||
*
|
||||
* @param source the name of the source file from which the class was compiled. May be
|
||||
* <tt>null</tt>.
|
||||
* @param debug additional debug information to compute the correspondence between source and
|
||||
* compiled elements of the class. May be <tt>null</tt>.
|
||||
*/
|
||||
public void visitSource(final String source, final String debug) {
|
||||
if (cv != null) {
|
||||
cv.visitSource(source, debug);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits the source of the class.
|
||||
*
|
||||
* @param source
|
||||
* the name of the source file from which the class was compiled.
|
||||
* May be <tt>null</tt>.
|
||||
* @param debug
|
||||
* additional debug information to compute the correspondance
|
||||
* between source and compiled elements of the class. May be
|
||||
* <tt>null</tt>.
|
||||
*/
|
||||
public void visitSource(String source, String debug) {
|
||||
if (cv != null) {
|
||||
cv.visitSource(source, debug);
|
||||
}
|
||||
/**
|
||||
* Visit the module corresponding to the class.
|
||||
*
|
||||
* @param name the fully qualified name (using dots) of the module.
|
||||
* @param access the module access flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC} and {@code
|
||||
* ACC_MANDATED}.
|
||||
* @param version the module version, or <tt>null</tt>.
|
||||
* @return a visitor to visit the module values, or <tt>null</tt> if this visitor is not
|
||||
* interested in visiting this module.
|
||||
*/
|
||||
public ModuleVisitor visitModule(final String name, final int access, final String version) {
|
||||
if (api < Opcodes.ASM6) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
if (cv != null) {
|
||||
return cv.visitModule(name, access, version);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit the module corresponding to the class.
|
||||
* @param name
|
||||
* module name
|
||||
* @param access
|
||||
* module flags, among {@code ACC_OPEN}, {@code ACC_SYNTHETIC}
|
||||
* and {@code ACC_MANDATED}.
|
||||
* @param version
|
||||
* module version or null.
|
||||
* @return a visitor to visit the module values, or <tt>null</tt> if
|
||||
* this visitor is not interested in visiting this module.
|
||||
*/
|
||||
public ModuleVisitor visitModule(String name, int access, String version) {
|
||||
if (api < Opcodes.ASM6) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
if (cv != null) {
|
||||
return cv.visitModule(name, access, version);
|
||||
}
|
||||
return null;
|
||||
/**
|
||||
* <b>Experimental, use at your own risk. This method will be renamed when it becomes stable, this
|
||||
* will break existing code using it</b>. Visits the nest host class of the class. A nest is a set
|
||||
* of classes of the same package that share access to their private members. One of these
|
||||
* classes, called the host, lists the other members of the nest, which in turn should link to the
|
||||
* host of their nest. This method must be called only once and only if the visited class is a
|
||||
* non-host member of a nest. A class is implicitly its own nest, so it's invalid to call this
|
||||
* method with the visited class name as argument.
|
||||
*
|
||||
* @param nestHost the internal name of the host class of the nest.
|
||||
*/
|
||||
public void visitNestHostExperimental(final String nestHost) {
|
||||
if (api < Opcodes.ASM7_EXPERIMENTAL) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
if (cv != null) {
|
||||
cv.visitNestHostExperimental(nestHost);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits the enclosing class of the class. This method must be called only
|
||||
* if the class has an enclosing class.
|
||||
*
|
||||
* @param owner
|
||||
* 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 not enclosed in a method of its
|
||||
* enclosing class.
|
||||
* @param desc
|
||||
* the descriptor of the method that contains the class, or
|
||||
* <tt>null</tt> if the class is not enclosed in a method of its
|
||||
* enclosing class.
|
||||
*/
|
||||
public void visitOuterClass(String owner, String name, String desc) {
|
||||
if (cv != null) {
|
||||
cv.visitOuterClass(owner, name, desc);
|
||||
}
|
||||
/**
|
||||
* Visits the enclosing class of the class. This method must be called only if the class has an
|
||||
* enclosing class.
|
||||
*
|
||||
* @param owner 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
|
||||
* not enclosed in a method of its enclosing class.
|
||||
* @param descriptor the descriptor of the method that contains the class, or <tt>null</tt> if the
|
||||
* class is not enclosed in a method of its enclosing class.
|
||||
*/
|
||||
public void visitOuterClass(final String owner, final String name, final String descriptor) {
|
||||
if (cv != null) {
|
||||
cv.visitOuterClass(owner, name, descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits an annotation of the class.
|
||||
*
|
||||
* @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 visitAnnotation(String desc, boolean visible) {
|
||||
if (cv != null) {
|
||||
return cv.visitAnnotation(desc, visible);
|
||||
}
|
||||
return null;
|
||||
/**
|
||||
* Visits an annotation of the class.
|
||||
*
|
||||
* @param descriptor 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 visitAnnotation(final String descriptor, final boolean visible) {
|
||||
if (cv != null) {
|
||||
return cv.visitAnnotation(descriptor, visible);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits an annotation on a type in the class signature.
|
||||
*
|
||||
* @param typeRef
|
||||
* a reference to the annotated type. The sort of this type
|
||||
* reference must be {@link TypeReference#CLASS_TYPE_PARAMETER
|
||||
* CLASS_TYPE_PARAMETER},
|
||||
* {@link TypeReference#CLASS_TYPE_PARAMETER_BOUND
|
||||
* CLASS_TYPE_PARAMETER_BOUND} or
|
||||
* {@link TypeReference#CLASS_EXTENDS CLASS_EXTENDS}. See
|
||||
* {@link TypeReference}.
|
||||
* @param typePath
|
||||
* the path to the annotated type argument, wildcard bound, array
|
||||
* element type, or static inner type within 'typeRef'. May be
|
||||
* <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 (cv != null) {
|
||||
return cv.visitTypeAnnotation(typeRef, typePath, desc, visible);
|
||||
}
|
||||
return null;
|
||||
/**
|
||||
* Visits an annotation on a type in the class signature.
|
||||
*
|
||||
* @param typeRef a reference to the annotated type. The sort of this type reference must be
|
||||
* {@link TypeReference#CLASS_TYPE_PARAMETER}, {@link
|
||||
* TypeReference#CLASS_TYPE_PARAMETER_BOUND} or {@link TypeReference#CLASS_EXTENDS}. See
|
||||
* {@link TypeReference}.
|
||||
* @param typePath the path to the annotated type argument, wildcard bound, array element type, or
|
||||
* static inner type within 'typeRef'. May be <tt>null</tt> if the annotation targets
|
||||
* 'typeRef' as a whole.
|
||||
* @param descriptor 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(
|
||||
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
|
||||
if (api < Opcodes.ASM5) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
if (cv != null) {
|
||||
return cv.visitTypeAnnotation(typeRef, typePath, descriptor, visible);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a non standard attribute of the class.
|
||||
*
|
||||
* @param attr
|
||||
* an attribute.
|
||||
*/
|
||||
public void visitAttribute(Attribute attr) {
|
||||
if (cv != null) {
|
||||
cv.visitAttribute(attr);
|
||||
}
|
||||
/**
|
||||
* Visits a non standard attribute of the class.
|
||||
*
|
||||
* @param attribute an attribute.
|
||||
*/
|
||||
public void visitAttribute(final Attribute attribute) {
|
||||
if (cv != null) {
|
||||
cv.visitAttribute(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits information about an inner class. This inner class is not
|
||||
* necessarily a member of the class being visited.
|
||||
*
|
||||
* @param name
|
||||
* the internal name of an inner class (see
|
||||
* {@link Type#getInternalName() getInternalName}).
|
||||
* @param outerName
|
||||
* the internal name of the class to which the inner class
|
||||
* belongs (see {@link Type#getInternalName() getInternalName}).
|
||||
* May be <tt>null</tt> for not member classes.
|
||||
* @param innerName
|
||||
* the (simple) name of the inner class inside its enclosing
|
||||
* class. May be <tt>null</tt> for anonymous inner classes.
|
||||
* @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);
|
||||
}
|
||||
/**
|
||||
* <b>Experimental, use at your own risk. This method will be renamed when it becomes stable, this
|
||||
* 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
|
||||
* the host, lists the other members of the nest, which in turn should link to the host of their
|
||||
* nest. This method must be called only if the visited class is the host of a nest. A nest host
|
||||
* is implicitly a member of its own nest, so it's invalid to call this method with the visited
|
||||
* class name as argument.
|
||||
*
|
||||
* @param nestMember the internal name of a nest member.
|
||||
*/
|
||||
public void visitNestMemberExperimental(final String nestMember) {
|
||||
if (api < Opcodes.ASM7_EXPERIMENTAL) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
if (cv != null) {
|
||||
cv.visitNestMemberExperimental(nestMember);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a field of the class.
|
||||
*
|
||||
* @param access
|
||||
* the field's access flags (see {@link Opcodes}). This parameter
|
||||
* also indicates if the field is synthetic and/or deprecated.
|
||||
* @param name
|
||||
* the field's name.
|
||||
* @param desc
|
||||
* the field's descriptor (see {@link Type Type}).
|
||||
* @param signature
|
||||
* the field's signature. May be <tt>null</tt> if the field's
|
||||
* type does not use generic types.
|
||||
* @param value
|
||||
* the field's initial value. This parameter, which may be
|
||||
* <tt>null</tt> if the field does not have an initial value,
|
||||
* 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 information about an inner class. This inner class is not necessarily a member of the
|
||||
* class being visited.
|
||||
*
|
||||
* @param name the internal name of an inner class (see {@link Type#getInternalName()}).
|
||||
* @param outerName the internal name of the class to which the inner class belongs (see {@link
|
||||
* Type#getInternalName()}). May be <tt>null</tt> for not member classes.
|
||||
* @param innerName the (simple) name of the inner class inside its enclosing class. May be
|
||||
* <tt>null</tt> for anonymous inner classes.
|
||||
* @param access the access flags of the inner class as originally declared in the enclosing
|
||||
* class.
|
||||
*/
|
||||
public void visitInnerClass(
|
||||
final String name, final String outerName, final String innerName, final int access) {
|
||||
if (cv != null) {
|
||||
cv.visitInnerClass(name, outerName, innerName, access);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a method of the class. This method <i>must</i> return a new
|
||||
* {@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 method's access flags (see {@link Opcodes}). This
|
||||
* parameter also indicates if the method is synthetic and/or
|
||||
* deprecated.
|
||||
* @param name
|
||||
* the method's name.
|
||||
* @param desc
|
||||
* the method's descriptor (see {@link Type 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() 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(int access, String name, String desc,
|
||||
String signature, String[] exceptions) {
|
||||
if (cv != null) {
|
||||
return cv.visitMethod(access, name, desc, signature, exceptions);
|
||||
}
|
||||
return null;
|
||||
/**
|
||||
* Visits a field of the class.
|
||||
*
|
||||
* @param access the field's access flags (see {@link Opcodes}). This parameter also indicates if
|
||||
* the field is synthetic and/or deprecated.
|
||||
* @param name the field's name.
|
||||
* @param descriptor the field's descriptor (see {@link Type}).
|
||||
* @param signature the field's signature. May be <tt>null</tt> if the field's type does not use
|
||||
* generic types.
|
||||
* @param value the field's initial value. This parameter, which may be <tt>null</tt> if the field
|
||||
* does not have an initial value, 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(
|
||||
final int access,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final Object value) {
|
||||
if (cv != null) {
|
||||
return cv.visitField(access, name, descriptor, signature, value);
|
||||
}
|
||||
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();
|
||||
}
|
||||
/**
|
||||
* Visits a method of the class. This method <i>must</i> return a new {@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 method's access flags (see {@link Opcodes}). This parameter also indicates if
|
||||
* the method is synthetic and/or deprecated.
|
||||
* @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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -1,145 +1,137 @@
|
|||
/***
|
||||
* 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.
|
||||
*/
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* Information about a class being parsed in a {@link ClassReader}.
|
||||
*
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
class Context {
|
||||
final class Context {
|
||||
|
||||
/**
|
||||
* Prototypes of the attributes that must be parsed for this class.
|
||||
*/
|
||||
Attribute[] attrs;
|
||||
/** The prototypes of the attributes that must be parsed in this class. */
|
||||
Attribute[] attributePrototypes;
|
||||
|
||||
/**
|
||||
* The {@link ClassReader} option flags for the parsing of this class.
|
||||
*/
|
||||
int flags;
|
||||
/**
|
||||
* 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
|
||||
* {@link ClassReader#EXPAND_ASM_INSNS}.
|
||||
*/
|
||||
int parsingOptions;
|
||||
|
||||
/**
|
||||
* The buffer used to read strings.
|
||||
*/
|
||||
char[] buffer;
|
||||
/** The buffer used to read strings in the constant pool. */
|
||||
char[] charBuffer;
|
||||
|
||||
/**
|
||||
* The start index of each bootstrap method.
|
||||
*/
|
||||
int[] bootstrapMethods;
|
||||
// Information about the current method, i.e. the one read in the current (or latest) call
|
||||
// to {@link ClassReader#readMethod()}.
|
||||
|
||||
/**
|
||||
* The access flags of the method currently being parsed.
|
||||
*/
|
||||
int access;
|
||||
/** The access flags of the current method. */
|
||||
int currentMethodAccessFlags;
|
||||
|
||||
/**
|
||||
* The name of the method currently being parsed.
|
||||
*/
|
||||
String name;
|
||||
/** The name of the current method. */
|
||||
String currentMethodName;
|
||||
|
||||
/**
|
||||
* The descriptor of the method currently being parsed.
|
||||
*/
|
||||
String desc;
|
||||
/** The descriptor of the current method. */
|
||||
String currentMethodDescriptor;
|
||||
|
||||
/**
|
||||
* The label objects, indexed by bytecode offset, of the method currently
|
||||
* being parsed (only bytecode offsets for which a label is needed have a
|
||||
* non null associated Label object).
|
||||
*/
|
||||
Label[] labels;
|
||||
/**
|
||||
* The labels of the current method, indexed by bytecode offset (only bytecode offsets for which a
|
||||
* label is needed have a non null associated Label).
|
||||
*/
|
||||
Label[] currentMethodLabels;
|
||||
|
||||
/**
|
||||
* The target of the type annotation currently being parsed.
|
||||
*/
|
||||
int typeRef;
|
||||
// Information about the current type annotation target, i.e. the one read in the current
|
||||
// (or latest) call to {@link ClassReader#readAnnotationTarget()}.
|
||||
|
||||
/**
|
||||
* The path of the type annotation currently being parsed.
|
||||
*/
|
||||
TypePath typePath;
|
||||
/**
|
||||
* The target_type and target_info of the current type annotation target, encoded as described in
|
||||
* {@link TypeReference}.
|
||||
*/
|
||||
int currentTypeAnnotationTarget;
|
||||
|
||||
/**
|
||||
* The offset of the latest stack map frame that has been parsed.
|
||||
*/
|
||||
int offset;
|
||||
/** The target_path of the current type annotation target. */
|
||||
TypePath currentTypeAnnotationTargetPath;
|
||||
|
||||
/**
|
||||
* The labels corresponding to the start of the local variable ranges in the
|
||||
* local variable type annotation currently being parsed.
|
||||
*/
|
||||
Label[] start;
|
||||
/** The start of each local variable range in the current local variable annotation. */
|
||||
Label[] currentLocalVariableAnnotationRangeStarts;
|
||||
|
||||
/**
|
||||
* The labels corresponding to the end of the local variable ranges in the
|
||||
* local variable type annotation currently being parsed.
|
||||
*/
|
||||
Label[] end;
|
||||
/** The end of each local variable range in the current local variable annotation. */
|
||||
Label[] currentLocalVariableAnnotationRangeEnds;
|
||||
|
||||
/**
|
||||
* The local variable indices for each local variable range in the local
|
||||
* variable type annotation currently being parsed.
|
||||
*/
|
||||
int[] index;
|
||||
/**
|
||||
* The local variable index of each local variable range in the current local variable annotation.
|
||||
*/
|
||||
int[] currentLocalVariableAnnotationRangeIndices;
|
||||
|
||||
/**
|
||||
* The encoding of the latest stack map frame that has been parsed.
|
||||
*/
|
||||
int mode;
|
||||
// Information about the current stack map frame, i.e. the one read in the current (or latest)
|
||||
// call to {@link ClassReader#readFrame()}.
|
||||
|
||||
/**
|
||||
* The number of locals in the latest stack map frame that has been parsed.
|
||||
*/
|
||||
int localCount;
|
||||
/** The bytecode offset of the current stack map frame. */
|
||||
int currentFrameOffset;
|
||||
|
||||
/**
|
||||
* The number locals in the latest stack map frame that has been parsed,
|
||||
* minus the number of locals in the previous frame.
|
||||
*/
|
||||
int localDiff;
|
||||
/**
|
||||
* The type of the current stack map frame. One of {@link Opcodes#F_FULL}, {@link
|
||||
* Opcodes#F_APPEND}, {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or {@link Opcodes#F_SAME1}.
|
||||
*/
|
||||
int currentFrameType;
|
||||
|
||||
/**
|
||||
* The local values of the latest stack map frame that has been parsed.
|
||||
*/
|
||||
Object[] local;
|
||||
/**
|
||||
* 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).
|
||||
*/
|
||||
int currentFrameLocalCount;
|
||||
|
||||
/**
|
||||
* The stack size of the latest stack map frame that has been parsed.
|
||||
*/
|
||||
int stackCount;
|
||||
/**
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
Object[] stack;
|
||||
/**
|
||||
* 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
|
||||
* 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,56 +1,56 @@
|
|||
/***
|
||||
* 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.
|
||||
*/
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* Information about the input stack map frame at the "current" instruction of a
|
||||
* method. This is implemented as a Frame subclass for a "basic block"
|
||||
* containing only one instruction.
|
||||
*
|
||||
* Information about the input stack map frame at the "current" instruction of a method. This is
|
||||
* implemented as a Frame subclass for a "basic block" containing only one instruction.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
class CurrentFrame extends Frame {
|
||||
|
||||
/**
|
||||
* Sets this CurrentFrame to the input stack map frame of the next "current"
|
||||
* 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.
|
||||
*/
|
||||
@Override
|
||||
void execute(int opcode, int arg, ClassWriter cw, Item item) {
|
||||
super.execute(opcode, arg, cw, item);
|
||||
Frame successor = new Frame();
|
||||
merge(cw, successor, 0);
|
||||
set(successor);
|
||||
owner.inputStackTop = 0;
|
||||
}
|
||||
final class CurrentFrame extends Frame {
|
||||
|
||||
CurrentFrame(final Label owner) {
|
||||
super(owner);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this CurrentFrame to the input stack map frame of the next "current" 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.
|
||||
*/
|
||||
@Override
|
||||
void execute(
|
||||
final int opcode, final int arg, final Symbol symbolArg, final SymbolTable symbolTable) {
|
||||
super.execute(opcode, arg, symbolArg, symbolTable);
|
||||
Frame successor = new Frame(null);
|
||||
merge(symbolTable, successor, 0);
|
||||
copyFrom(successor);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,75 +1,91 @@
|
|||
/***
|
||||
* 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.
|
||||
*/
|
||||
// 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 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
|
||||
*/
|
||||
class Edge {
|
||||
final class Edge {
|
||||
|
||||
/**
|
||||
* Denotes a normal control flow graph edge.
|
||||
*/
|
||||
static final int NORMAL = 0;
|
||||
/**
|
||||
* A control flow graph edge corresponding to a jump or ret instruction. Only used with {@link
|
||||
* ClassWriter#COMPUTE_FRAMES}.
|
||||
*/
|
||||
static final int JUMP = 0;
|
||||
|
||||
/**
|
||||
* Denotes a control flow graph edge corresponding to an exception handler.
|
||||
* More precisely any {@link Edge} whose {@link #info} is strictly positive
|
||||
* corresponds to an exception handler. The actual value of {@link #info} is
|
||||
* the index, in the {@link ClassWriter} type table, of the exception that
|
||||
* is catched.
|
||||
*/
|
||||
static final int EXCEPTION = 0x7FFFFFFF;
|
||||
/**
|
||||
* A control flow graph edge corresponding to an exception handler. Only used with {@link
|
||||
* ClassWriter#COMPUTE_MAXS}.
|
||||
*/
|
||||
static final int EXCEPTION = 0x7FFFFFFF;
|
||||
|
||||
/**
|
||||
* Information about this control flow graph edge. If
|
||||
* {@link ClassWriter#COMPUTE_MAXS} is used this field is the (relative)
|
||||
* stack size in the basic block from which this edge originates. This size
|
||||
* is equal to the stack size at the "jump" instruction to which this edge
|
||||
* corresponds, relatively to the stack size at the beginning of the
|
||||
* originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used,
|
||||
* this field is the kind of this control flow graph edge (i.e. NORMAL or
|
||||
* EXCEPTION).
|
||||
*/
|
||||
int info;
|
||||
/**
|
||||
* Information about this control flow graph edge.
|
||||
*
|
||||
* <ul>
|
||||
* <li>If {@link ClassWriter#COMPUTE_MAXS} is used, this field contains either a stack size
|
||||
* delta (for an edge corresponding to a jump instruction), or the value EXCEPTION (for an
|
||||
* edge corresponding to an exception handler). The stack size delta is the stack size just
|
||||
* after the jump instruction, minus the stack size at the beginning of the predecessor
|
||||
* 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
|
||||
* (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 the basic block from which this edge originates.
|
||||
*/
|
||||
Label successor;
|
||||
/** The successor block of this control flow graph edge. */
|
||||
final Label successor;
|
||||
|
||||
/**
|
||||
* The next edge in the list of successors of the originating basic block.
|
||||
* See {@link Label#successors successors}.
|
||||
*/
|
||||
Edge next;
|
||||
/**
|
||||
* The next edge in the list of outgoing edges of a basic block. See {@link Label#outgoingEdges}.
|
||||
*/
|
||||
Edge nextEdge;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,152 +1,138 @@
|
|||
/***
|
||||
* 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.
|
||||
*/
|
||||
// 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 visitor to visit a Java field. The methods of this class must be called in
|
||||
* the following order: ( <tt>visitAnnotation</tt> |
|
||||
* <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
|
||||
*
|
||||
* A visitor to visit a Java field. The methods of this class must be called in the following order:
|
||||
* ( <tt>visitAnnotation</tt> | <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )*
|
||||
* <tt>visitEnd</tt>.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public abstract class FieldVisitor {
|
||||
|
||||
/**
|
||||
* The ASM API version implemented by this visitor. The value of this field
|
||||
* must be one of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
*/
|
||||
protected final int api;
|
||||
/**
|
||||
* The ASM API version implemented by this visitor. The value of this field must be one of {@link
|
||||
* Opcodes#ASM4}, {@link Opcodes#ASM5}, {@link Opcodes#ASM6} or {@link Opcodes#ASM7_EXPERIMENTAL}.
|
||||
*/
|
||||
protected final int api;
|
||||
|
||||
/**
|
||||
* The field visitor to which this visitor must delegate method calls. May
|
||||
* be null.
|
||||
*/
|
||||
protected FieldVisitor fv;
|
||||
/** The field visitor to which this visitor must delegate method calls. May be null. */
|
||||
protected FieldVisitor fv;
|
||||
|
||||
/**
|
||||
* 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} or {@link Opcodes#ASM6}.
|
||||
*/
|
||||
public FieldVisitor(final int api) {
|
||||
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}.
|
||||
*/
|
||||
public FieldVisitor(final int api) {
|
||||
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}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be one
|
||||
* of {@link Opcodes#ASM4}, {@link Opcodes#ASM5} or {@link Opcodes#ASM6}.
|
||||
* @param fv
|
||||
* the field visitor to which this visitor must delegate method
|
||||
* calls. May be null.
|
||||
*/
|
||||
public FieldVisitor(final int api, final FieldVisitor fv) {
|
||||
if (api < Opcodes.ASM4 || api > Opcodes.ASM6) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.api = api;
|
||||
this.fv = fv;
|
||||
/**
|
||||
* Visits an annotation of the field.
|
||||
*
|
||||
* @param descriptor 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 visitAnnotation(final String descriptor, final boolean visible) {
|
||||
if (fv != null) {
|
||||
return fv.visitAnnotation(descriptor, visible);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits an annotation of the field.
|
||||
*
|
||||
* @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 visitAnnotation(String desc, boolean visible) {
|
||||
if (fv != null) {
|
||||
return fv.visitAnnotation(desc, visible);
|
||||
}
|
||||
return null;
|
||||
/**
|
||||
* Visits an annotation on the type of the field.
|
||||
*
|
||||
* @param typeRef a reference to the annotated type. The sort of this type reference must be
|
||||
* {@link TypeReference#FIELD}. See {@link TypeReference}.
|
||||
* @param typePath the path to the annotated type argument, wildcard bound, array element type, or
|
||||
* static inner type within 'typeRef'. May be <tt>null</tt> if the annotation targets
|
||||
* 'typeRef' as a whole.
|
||||
* @param descriptor 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(
|
||||
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.
|
||||
*
|
||||
* @param typeRef
|
||||
* a reference to the annotated type. The sort of this type
|
||||
* reference must be {@link TypeReference#FIELD FIELD}. See
|
||||
* {@link TypeReference}.
|
||||
* @param typePath
|
||||
* the path to the annotated type argument, wildcard bound, array
|
||||
* element type, or static inner type within 'typeRef'. May be
|
||||
* <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.
|
||||
*
|
||||
* @param attribute an attribute.
|
||||
*/
|
||||
public void visitAttribute(final Attribute attribute) {
|
||||
if (fv != null) {
|
||||
fv.visitAttribute(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a non standard attribute of the field.
|
||||
*
|
||||
* @param attr
|
||||
* an attribute.
|
||||
*/
|
||||
public void visitAttribute(Attribute attr) {
|
||||
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();
|
||||
}
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,329 +1,346 @@
|
|||
/***
|
||||
* 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.
|
||||
*/
|
||||
// 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 {@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
|
||||
*/
|
||||
final class FieldWriter extends FieldVisitor {
|
||||
|
||||
/**
|
||||
* The class writer to which this field must be added.
|
||||
*/
|
||||
private final ClassWriter cw;
|
||||
/** Where the constants used in this FieldWriter must be stored. */
|
||||
private final SymbolTable symbolTable;
|
||||
|
||||
/**
|
||||
* Access flags of this field.
|
||||
*/
|
||||
private final int access;
|
||||
// Note: fields are ordered as in the field_info structure, and those related to attributes are
|
||||
// ordered as in Section 4.7 of the JVMS.
|
||||
|
||||
/**
|
||||
* The index of the constant pool item that contains the name of this
|
||||
* method.
|
||||
*/
|
||||
private final int name;
|
||||
/**
|
||||
* The access_flags field of the field_info JVMS structure. This field can contain ASM specific
|
||||
* access flags, such as {@link Opcodes#ACC_DEPRECATED}, which are removed when generating the
|
||||
* ClassFile structure.
|
||||
*/
|
||||
private final int accessFlags;
|
||||
|
||||
/**
|
||||
* The index of the constant pool item that contains the descriptor of this
|
||||
* field.
|
||||
*/
|
||||
private final int desc;
|
||||
/** The name_index field of the field_info JVMS structure. */
|
||||
private final int nameIndex;
|
||||
|
||||
/**
|
||||
* The index of the constant pool item that contains the signature of this
|
||||
* field.
|
||||
*/
|
||||
private int signature;
|
||||
/** The descriptor_index field of the field_info JVMS structure. */
|
||||
private final int descriptorIndex;
|
||||
|
||||
/**
|
||||
* The index of the constant pool item that contains the constant value of
|
||||
* this field.
|
||||
*/
|
||||
private int value;
|
||||
/**
|
||||
* The signature_index field of the Signature attribute of this field_info, or 0 if there is no
|
||||
* Signature attribute.
|
||||
*/
|
||||
private int signatureIndex;
|
||||
|
||||
/**
|
||||
* The runtime visible annotations of this field. May be <tt>null</tt>.
|
||||
*/
|
||||
private AnnotationWriter anns;
|
||||
/**
|
||||
* The constantvalue_index field of the ConstantValue attribute of this field_info, or 0 if there
|
||||
* is no ConstantValue attribute.
|
||||
*/
|
||||
private int constantValueIndex;
|
||||
|
||||
/**
|
||||
* The runtime invisible annotations of this field. May be <tt>null</tt>.
|
||||
*/
|
||||
private AnnotationWriter ianns;
|
||||
/**
|
||||
* 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 lastRuntimeVisibleAnnotation;
|
||||
|
||||
/**
|
||||
* The runtime visible type annotations of this field. May be <tt>null</tt>.
|
||||
*/
|
||||
private AnnotationWriter tanns;
|
||||
/**
|
||||
* 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 lastRuntimeInvisibleAnnotation;
|
||||
|
||||
/**
|
||||
* The runtime invisible type annotations of this field. May be
|
||||
* <tt>null</tt>.
|
||||
*/
|
||||
private AnnotationWriter itanns;
|
||||
/**
|
||||
* The last runtime visible type annotation of this field. The previous ones can be accessed with
|
||||
* the {@link AnnotationWriter#previousAnnotation} field. May be <tt>null</tt>.
|
||||
*/
|
||||
private AnnotationWriter lastRuntimeVisibleTypeAnnotation;
|
||||
|
||||
/**
|
||||
* The non standard attributes of this field. May be <tt>null</tt>.
|
||||
*/
|
||||
private Attribute attrs;
|
||||
/**
|
||||
* 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 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}.
|
||||
*
|
||||
* @param cw
|
||||
* the class writer to which this field must be added.
|
||||
* @param access
|
||||
* the field's access flags (see {@link Opcodes}).
|
||||
* @param name
|
||||
* the field's name.
|
||||
* @param desc
|
||||
* the field's descriptor (see {@link Type}).
|
||||
* @param signature
|
||||
* the field's signature. May be <tt>null</tt>.
|
||||
* @param value
|
||||
* the field's constant value. May be <tt>null</tt>.
|
||||
*/
|
||||
FieldWriter(final ClassWriter cw, final int access, final String name,
|
||||
final String desc, final String signature, final Object value) {
|
||||
super(Opcodes.ASM6);
|
||||
if (cw.firstField == null) {
|
||||
cw.firstField = this;
|
||||
} else {
|
||||
cw.lastField.fv = this;
|
||||
}
|
||||
cw.lastField = this;
|
||||
this.cw = cw;
|
||||
this.access = access;
|
||||
this.name = cw.newUTF8(name);
|
||||
this.desc = cw.newUTF8(desc);
|
||||
if (ClassReader.SIGNATURES && signature != null) {
|
||||
this.signature = cw.newUTF8(signature);
|
||||
}
|
||||
if (value != null) {
|
||||
this.value = cw.newConstItem(value).index;
|
||||
}
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Constructs a new {@link FieldWriter}.
|
||||
*
|
||||
* @param symbolTable where the constants used in this FieldWriter must be stored.
|
||||
* @param access the field's access flags (see {@link Opcodes}).
|
||||
* @param name the field's name.
|
||||
* @param descriptor the field's descriptor (see {@link Type}).
|
||||
* @param signature the field's signature. May be <tt>null</tt>.
|
||||
* @param constantValue the field's constant value. May be <tt>null</tt>.
|
||||
*/
|
||||
FieldWriter(
|
||||
final SymbolTable symbolTable,
|
||||
final int access,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final String signature,
|
||||
final Object constantValue) {
|
||||
super(Opcodes.ASM6);
|
||||
this.symbolTable = symbolTable;
|
||||
this.accessFlags = access;
|
||||
this.nameIndex = symbolTable.addConstantUtf8(name);
|
||||
this.descriptorIndex = symbolTable.addConstantUtf8(descriptor);
|
||||
if (signature != null) {
|
||||
this.signatureIndex = symbolTable.addConstantUtf8(signature);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// 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;
|
||||
if (constantValue != null) {
|
||||
this.constantValueIndex = symbolTable.addConstant(constantValue).index;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitTypeAnnotation(final int typeRef,
|
||||
final TypePath typePath, final String desc, final boolean visible) {
|
||||
if (!ClassReader.ANNOTATIONS) {
|
||||
return null;
|
||||
}
|
||||
ByteVector bv = new ByteVector();
|
||||
// write target_type and target_info
|
||||
AnnotationWriter.putTarget(typeRef, typePath, bv);
|
||||
// write type, and reserve space for values count
|
||||
bv.putShort(cw.newUTF8(desc)).putShort(0);
|
||||
AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
|
||||
bv.length - 2);
|
||||
if (visible) {
|
||||
aw.next = tanns;
|
||||
tanns = aw;
|
||||
} else {
|
||||
aw.next = itanns;
|
||||
itanns = aw;
|
||||
}
|
||||
return aw;
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// Implementation of the FieldVisitor abstract class
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
|
||||
// Create a ByteVector to hold an 'annotation' JVMS structure.
|
||||
// See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.7.16.
|
||||
ByteVector annotation = new ByteVector();
|
||||
// Write type_index and reserve space for num_element_value_pairs.
|
||||
annotation.putShort(symbolTable.addConstantUtf8(descriptor)).putShort(0);
|
||||
if (visible) {
|
||||
return lastRuntimeVisibleAnnotation =
|
||||
new AnnotationWriter(symbolTable, annotation, lastRuntimeVisibleAnnotation);
|
||||
} else {
|
||||
return lastRuntimeInvisibleAnnotation =
|
||||
new AnnotationWriter(symbolTable, annotation, lastRuntimeInvisibleAnnotation);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitAttribute(final Attribute attr) {
|
||||
attr.next = attrs;
|
||||
attrs = attr;
|
||||
@Override
|
||||
public AnnotationVisitor visitTypeAnnotation(
|
||||
final int typeRef, final TypePath typePath, final String descriptor, final boolean visible) {
|
||||
// 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
|
||||
public void visitEnd() {
|
||||
@Override
|
||||
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;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Utility methods
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* 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;
|
||||
// Before Java 1.5, synthetic fields are represented with a Synthetic attribute.
|
||||
if ((accessFlags & Opcodes.ACC_SYNTHETIC) != 0
|
||||
&& symbolTable.getMajorVersion() < Opcodes.V1_5) {
|
||||
// Synthetic attributes always use 6 bytes.
|
||||
symbolTable.addConstantUtf8(Constants.SYNTHETIC);
|
||||
size += 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the content of this field into the given byte vector.
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
if (signatureIndex != 0) {
|
||||
// Signature attributes always use 8 bytes.
|
||||
symbolTable.addConstantUtf8(Constants.SIGNATURE);
|
||||
size += 8;
|
||||
}
|
||||
// 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
|
|
@ -1,222 +1,189 @@
|
|||
/***
|
||||
* 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.
|
||||
*/
|
||||
// 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 reference to a field or a method.
|
||||
*
|
||||
*
|
||||
* @author Remi Forax
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public final class Handle {
|
||||
|
||||
/**
|
||||
* The kind of field or method designated by this Handle. Should 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}.
|
||||
*/
|
||||
final int tag;
|
||||
/**
|
||||
* The kind of field or method designated by this Handle. Should 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}.
|
||||
*/
|
||||
private final int tag;
|
||||
|
||||
/**
|
||||
* The internal name of the class that owns the field or method designated
|
||||
* by this handle.
|
||||
*/
|
||||
final String owner;
|
||||
/** The internal name of the class that owns the field or method designated by this handle. */
|
||||
private final String owner;
|
||||
|
||||
/**
|
||||
* The name of the field or method designated by this handle.
|
||||
*/
|
||||
final String name;
|
||||
/** The name of the field or method designated by this handle. */
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* The descriptor of the field or method designated by this handle.
|
||||
*/
|
||||
final String desc;
|
||||
/** The descriptor of the field or method designated by this handle. */
|
||||
private final String descriptor;
|
||||
|
||||
/** Whether the owner is an interface or not. */
|
||||
private final boolean isInterface;
|
||||
|
||||
/**
|
||||
* Indicate if the owner is an interface or not.
|
||||
*/
|
||||
final boolean itf;
|
||||
/**
|
||||
* 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 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.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @deprecated this constructor has been superseded
|
||||
* by {@link #Handle(int, String, String, String, boolean)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public Handle(int tag, String owner, String name, String desc) {
|
||||
this(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE);
|
||||
/**
|
||||
* 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 descriptor the descriptor of the field or method designated by this handle.
|
||||
* @param isInterface whether the owner is an interface or not.
|
||||
*/
|
||||
public Handle(
|
||||
final int tag,
|
||||
final String owner,
|
||||
final String name,
|
||||
final String descriptor,
|
||||
final boolean isInterface) {
|
||||
this.tag = tag;
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
this.descriptor = descriptor;
|
||||
this.isInterface = isInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
if (!(object instanceof Handle)) {
|
||||
return false;
|
||||
}
|
||||
Handle handle = (Handle) object;
|
||||
return tag == handle.tag
|
||||
&& isInterface == handle.isInterface
|
||||
&& owner.equals(handle.owner)
|
||||
&& name.equals(handle.name)
|
||||
&& descriptor.equals(handle.descriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return tag
|
||||
+ (isInterface ? 64 : 0)
|
||||
+ owner.hashCode() * name.hashCode() * descriptor.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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": "") + ')';
|
||||
}
|
||||
/**
|
||||
* Returns the textual representation of this handle. The textual representation is:
|
||||
*
|
||||
* <ul>
|
||||
* <li>for a reference to a class: owner "." name descriptor " (" tag ")",
|
||||
* <li>for a reference to an interface: owner "." name descriptor " (" tag " itf)".
|
||||
* </ul>
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return owner + '.' + name + descriptor + " (" + tag + (isInterface ? " itf" : "") + ')';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,121 +1,198 @@
|
|||
/***
|
||||
* 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.
|
||||
*/
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
class Handler {
|
||||
final class Handler {
|
||||
|
||||
/**
|
||||
* Beginning of the exception handler's scope (inclusive).
|
||||
*/
|
||||
Label start;
|
||||
/**
|
||||
* The start_pc field of this JVMS exception_table entry. Corresponds to the beginning of the
|
||||
* exception handler's scope (inclusive).
|
||||
*/
|
||||
final Label startPc;
|
||||
|
||||
/**
|
||||
* End of the exception handler's scope (exclusive).
|
||||
*/
|
||||
Label end;
|
||||
/**
|
||||
* The end_pc field of this JVMS exception_table entry. Corresponds to the end of the exception
|
||||
* handler's scope (exclusive).
|
||||
*/
|
||||
final Label endPc;
|
||||
|
||||
/**
|
||||
* Beginning of the exception handler's code.
|
||||
*/
|
||||
Label handler;
|
||||
/**
|
||||
* The handler_pc field of this JVMS exception_table entry. Corresponding to the beginning of the
|
||||
* exception handler's code.
|
||||
*/
|
||||
final Label handlerPc;
|
||||
|
||||
/**
|
||||
* Internal name of the type of exceptions handled by this handler, or
|
||||
* <tt>null</tt> to catch any exceptions.
|
||||
*/
|
||||
String desc;
|
||||
/**
|
||||
* The catch_type field of this JVMS exception_table entry. This is the constant pool index of the
|
||||
* internal name of the type of exceptions handled by this handler, or 0 to catch any exceptions.
|
||||
*/
|
||||
final int catchType;
|
||||
|
||||
/**
|
||||
* Constant pool index of the internal name of the type of exceptions
|
||||
* handled by this handler, or 0 to catch any exceptions.
|
||||
*/
|
||||
int type;
|
||||
/**
|
||||
* The internal name of the type of exceptions handled by this handler, or <tt>null</tt> to catch
|
||||
* any exceptions.
|
||||
*/
|
||||
final String catchTypeDescriptor;
|
||||
|
||||
/**
|
||||
* Next exception handler block info.
|
||||
*/
|
||||
Handler next;
|
||||
/** The next exception handler. */
|
||||
Handler nextHandler;
|
||||
|
||||
/**
|
||||
* Removes the range between start and end from the given exception
|
||||
* handlers.
|
||||
*
|
||||
* @param h
|
||||
* an exception handler list.
|
||||
* @param start
|
||||
* the start of the range to be removed.
|
||||
* @param end
|
||||
* the end of the range to be removed. Maybe null.
|
||||
* @return the exception handler list with the start-end range removed.
|
||||
*/
|
||||
static Handler remove(Handler h, Label start, Label end) {
|
||||
if (h == null) {
|
||||
return null;
|
||||
} else {
|
||||
h.next = remove(h.next, start, end);
|
||||
}
|
||||
int hstart = h.start.position;
|
||||
int hend = h.end.position;
|
||||
int s = start.position;
|
||||
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) {
|
||||
if (e >= hend) {
|
||||
// [hstart,hend[ fully included in [s,e[, h removed
|
||||
h = h.next;
|
||||
} else {
|
||||
// [hstart,hend[ minus [s,e[ = [e,hend[
|
||||
h.start = end;
|
||||
}
|
||||
} else if (e >= hend) {
|
||||
// [hstart,hend[ minus [s,e[ = [hstart,s[
|
||||
h.end = start;
|
||||
} else {
|
||||
// [hstart,hend[ minus [s,e[ = [hstart,s[ + [e,hend[
|
||||
Handler g = new Handler();
|
||||
g.start = end;
|
||||
g.end = h.end;
|
||||
g.handler = h.handler;
|
||||
g.desc = h.desc;
|
||||
g.type = h.type;
|
||||
g.next = h.next;
|
||||
h.end = start;
|
||||
h.next = g;
|
||||
}
|
||||
}
|
||||
return h;
|
||||
/**
|
||||
* Constructs a new Handler.
|
||||
*
|
||||
* @param startPc the start_pc field of this JVMS exception_table entry.
|
||||
* @param endPc the end_pc field of this JVMS exception_table entry.
|
||||
* @param handlerPc the handler_pc field of this JVMS exception_table entry.
|
||||
* @param catchType The catch_type field of this JVMS exception_table entry.
|
||||
* @param catchTypeDescriptor The internal name of the type of exceptions handled by this handler,
|
||||
* or <tt>null</tt> to catch any exceptions.
|
||||
*/
|
||||
Handler(
|
||||
final Label startPc,
|
||||
final Label endPc,
|
||||
final Label handlerPc,
|
||||
final int catchType,
|
||||
final String catchTypeDescriptor) {
|
||||
this.startPc = startPc;
|
||||
this.endPc = endPc;
|
||||
this.handlerPc = handlerPc;
|
||||
this.catchType = catchType;
|
||||
this.catchTypeDescriptor = catchTypeDescriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new Handler from the given one, with a different scope.
|
||||
*
|
||||
* @param handler an existing Handler.
|
||||
* @param startPc the start_pc field of this JVMS exception_table entry.
|
||||
* @param endPc the end_pc field of this JVMS exception_table entry.
|
||||
*/
|
||||
Handler(final Handler handler, final Label startPc, final Label endPc) {
|
||||
this(startPc, endPc, handler.handlerPc, handler.catchType, handler.catchTypeDescriptor);
|
||||
this.nextHandler = handler.nextHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the range between start and end from the Handler list that begins with the given
|
||||
* element.
|
||||
*
|
||||
* @param firstHandler the beginning of a Handler list. May be <tt>null</tt>.
|
||||
* @param start the start of the range to be removed.
|
||||
* @param end the end of the range to be removed. Maybe <tt>null</tt>.
|
||||
* @return the exception handler list with the start-end range removed.
|
||||
*/
|
||||
static Handler removeRange(final Handler firstHandler, final Label start, final Label end) {
|
||||
if (firstHandler == null) {
|
||||
return null;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,178 +1,175 @@
|
|||
/***
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// 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 visitor to visit a Java module. The methods of this class must be called in
|
||||
* the following order: <tt>visitVersion</tt> | <tt>visitMainClass</tt> |
|
||||
* <tt>visitTargetPlatform</tt> | ( <tt>visitConcealedPackage</tt> | <tt>visitRequire</tt> |
|
||||
* <tt>visitExport</tt> | <tt>visitUse</tt> | <tt>visitProvide</tt> )* <tt>visitEnd</tt>.
|
||||
*
|
||||
* A visitor to visit a Java module. The methods of this class must be called in the following
|
||||
* order: <tt>visitMainClass</tt> | ( <tt>visitPackage</tt> | <tt>visitRequire</tt> |
|
||||
* <tt>visitExport</tt> | <tt>visitOpen</tt> | <tt>visitUse</tt> | <tt>visitProvide</tt> )*
|
||||
* <tt>visitEnd</tt>.
|
||||
*
|
||||
* @author Remi Forax
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public abstract class ModuleVisitor {
|
||||
/**
|
||||
* The ASM API version implemented by this visitor. The value of this field
|
||||
* must be {@link Opcodes#ASM6}.
|
||||
*/
|
||||
protected final int api;
|
||||
|
||||
/**
|
||||
* The module visitor to which this visitor must delegate method calls. May
|
||||
* be null.
|
||||
*/
|
||||
protected ModuleVisitor mv;
|
||||
|
||||
|
||||
public ModuleVisitor(final int api) {
|
||||
this(api, null);
|
||||
}
|
||||
/**
|
||||
* The ASM API version implemented by this visitor. The value of this field must be one of {@link
|
||||
* Opcodes#ASM6} or {@link Opcodes#ASM7_EXPERIMENTAL}.
|
||||
*/
|
||||
protected final int api;
|
||||
|
||||
/**
|
||||
* Constructs a new {@link MethodVisitor}.
|
||||
*
|
||||
* @param api
|
||||
* the ASM API version implemented by this visitor. Must be {@link Opcodes#ASM6}.
|
||||
* @param mv
|
||||
* the method visitor to which this visitor must delegate method
|
||||
* calls. May be null.
|
||||
*/
|
||||
public ModuleVisitor(final int api, final ModuleVisitor mv) {
|
||||
if (api != Opcodes.ASM6) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.api = api;
|
||||
this.mv = mv;
|
||||
/** The module visitor to which this visitor must delegate method calls. May 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit the main class of the current module.
|
||||
*
|
||||
* @param mainClass the main class of the current module.
|
||||
*/
|
||||
public void visitMainClass(String mainClass) {
|
||||
if (mv != null) {
|
||||
mv.visitMainClass(mainClass);
|
||||
}
|
||||
this.api = api;
|
||||
this.mv = moduleVisitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit the main class of the current module.
|
||||
*
|
||||
* @param mainClass the internal name of the main class of the current module.
|
||||
*/
|
||||
public void visitMainClass(final String mainClass) {
|
||||
if (mv != null) {
|
||||
mv.visitMainClass(mainClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a concealed package of the current module.
|
||||
*
|
||||
* @param packaze name of a concealed package
|
||||
*/
|
||||
public void visitPackage(String packaze) {
|
||||
if (mv != null) {
|
||||
mv.visitPackage(packaze);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a package of the current module.
|
||||
*
|
||||
* @param packaze the internal name of a package.
|
||||
*/
|
||||
public void visitPackage(final String packaze) {
|
||||
if (mv != null) {
|
||||
mv.visitPackage(packaze);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a dependence of the current module.
|
||||
*
|
||||
* @param module the module name of the dependence
|
||||
* @param access the access flag of the dependence among
|
||||
* ACC_TRANSITIVE, ACC_STATIC_PHASE, ACC_SYNTHETIC
|
||||
* and ACC_MANDATED.
|
||||
* @param version the module version at compile time or null.
|
||||
*/
|
||||
public void visitRequire(String module, int access, String version) {
|
||||
if (mv != null) {
|
||||
mv.visitRequire(module, access, version);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visits a dependence of the current module.
|
||||
*
|
||||
* @param module the fully qualified name (using dots) of the dependence.
|
||||
* @param access the access flag of the dependence among {@code ACC_TRANSITIVE}, {@code
|
||||
* ACC_STATIC_PHASE}, {@code ACC_SYNTHETIC} and {@code ACC_MANDATED}.
|
||||
* @param version the module version at compile time, or <tt>null</tt>.
|
||||
*/
|
||||
public void visitRequire(final String module, final int access, final String version) {
|
||||
if (mv != null) {
|
||||
mv.visitRequire(module, access, version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit an exported package of the current module.
|
||||
*
|
||||
* @param packaze the name of the exported package.
|
||||
* @param access the access flag of the exported package,
|
||||
* valid values are among {@code ACC_SYNTHETIC} and
|
||||
* {@code ACC_MANDATED}.
|
||||
* @param modules names of the modules that can access to
|
||||
* the public classes of the exported package or
|
||||
* <tt>null</tt>.
|
||||
*/
|
||||
public void visitExport(String packaze, int access, String... modules) {
|
||||
if (mv != null) {
|
||||
mv.visitExport(packaze, access, modules);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit an exported package of the current module.
|
||||
*
|
||||
* @param packaze the internal name of the exported package.
|
||||
* @param access the access flag of the exported package, valid values are among {@code
|
||||
* ACC_SYNTHETIC} and {@code ACC_MANDATED}.
|
||||
* @param modules the fully qualified names (using dots) of the modules that can access the public
|
||||
* classes of the exported package, or <tt>null</tt>.
|
||||
*/
|
||||
public void visitExport(final String packaze, final int access, final String... modules) {
|
||||
if (mv != null) {
|
||||
mv.visitExport(packaze, access, modules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit an open package of the current module.
|
||||
*
|
||||
* @param packaze the name of the opened package.
|
||||
* @param access the access flag of the opened package,
|
||||
* valid values are among {@code ACC_SYNTHETIC} and
|
||||
* {@code ACC_MANDATED}.
|
||||
* @param modules names of the modules that can use deep
|
||||
* reflection to the classes of the open package or
|
||||
* <tt>null</tt>.
|
||||
*/
|
||||
public void visitOpen(String packaze, int access, String... modules) {
|
||||
if (mv != null) {
|
||||
mv.visitOpen(packaze, access, modules);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit an open package of the current module.
|
||||
*
|
||||
* @param packaze the internal name of the opened package.
|
||||
* @param access the access flag of the opened package, valid values are among {@code
|
||||
* ACC_SYNTHETIC} and {@code ACC_MANDATED}.
|
||||
* @param modules the fully qualified names (using dots) of the modules that can use deep
|
||||
* reflection to the classes of the open package, or <tt>null</tt>.
|
||||
*/
|
||||
public void visitOpen(final String packaze, final int access, final String... modules) {
|
||||
if (mv != null) {
|
||||
mv.visitOpen(packaze, access, modules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a service used by the current module.
|
||||
* The name must be the name of an interface or an
|
||||
* abstract class.
|
||||
*
|
||||
* @param service the internal name of the service.
|
||||
*/
|
||||
public void visitUse(String service) {
|
||||
if (mv != null) {
|
||||
mv.visitUse(service);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit a service used by the current module. The name must be the internal name of an interface
|
||||
* or a class.
|
||||
*
|
||||
* @param service the internal name of the service.
|
||||
*/
|
||||
public void visitUse(final String service) {
|
||||
if (mv != null) {
|
||||
mv.visitUse(service);
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit an implementation of a service.
|
||||
*
|
||||
* @param service the internal name of the service
|
||||
* @param providers the internal names of the implementations
|
||||
* of the service (there is at least one provider).
|
||||
*/
|
||||
public void visitProvide(String service, String... providers) {
|
||||
if (mv != null) {
|
||||
mv.visitProvide(service, providers);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit an implementation of a service.
|
||||
*
|
||||
* @param service the internal name of the service.
|
||||
* @param providers the internal names of the implementations of the service (there is at least
|
||||
* one provider).
|
||||
*/
|
||||
public void visitProvide(final String service, final String... providers) {
|
||||
if (mv != null) {
|
||||
mv.visitProvide(service, providers);
|
||||
}
|
||||
|
||||
public void visitEnd() {
|
||||
if (mv != null) {
|
||||
mv.visitEnd();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public void visitEnd() {
|
||||
if (mv != null) {
|
||||
mv.visitEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,293 +1,253 @@
|
|||
/***
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// 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 {@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 Eric Bruneton
|
||||
*/
|
||||
final class ModuleWriter extends ModuleVisitor {
|
||||
/**
|
||||
* The class writer to which this Module attribute must be added.
|
||||
*/
|
||||
private final ClassWriter cw;
|
||||
|
||||
/**
|
||||
* size in byte of the Module attribute.
|
||||
*/
|
||||
int size;
|
||||
|
||||
/**
|
||||
* Number of attributes associated with the current module
|
||||
* (Version, ConcealPackages, etc)
|
||||
*/
|
||||
int attributeCount;
|
||||
|
||||
/**
|
||||
* Size in bytes of the attributes associated with the current module
|
||||
*/
|
||||
int attributesSize;
|
||||
|
||||
/**
|
||||
* module name index in the constant pool
|
||||
*/
|
||||
private final int name;
|
||||
|
||||
/**
|
||||
* module access flags
|
||||
*/
|
||||
private final int access;
|
||||
|
||||
/**
|
||||
* module version index in the constant pool or 0
|
||||
*/
|
||||
private final int version;
|
||||
|
||||
/**
|
||||
* module main class index in the constant pool or 0
|
||||
*/
|
||||
private int mainClass;
|
||||
|
||||
/**
|
||||
* number of packages
|
||||
*/
|
||||
private int packageCount;
|
||||
|
||||
/**
|
||||
* The packages in bytecode form. This byte vector only contains
|
||||
* the items themselves, the number of items is store in packageCount
|
||||
*/
|
||||
private ByteVector packages;
|
||||
|
||||
/**
|
||||
* number of requires items
|
||||
*/
|
||||
private int requireCount;
|
||||
|
||||
/**
|
||||
* The requires items in bytecode form. This byte vector only contains
|
||||
* the items themselves, the number of items is store in requireCount
|
||||
*/
|
||||
private ByteVector requires;
|
||||
|
||||
/**
|
||||
* number of exports items
|
||||
*/
|
||||
private int exportCount;
|
||||
|
||||
/**
|
||||
* The exports items in bytecode form. This byte vector only contains
|
||||
* the items themselves, the number of items is store in exportCount
|
||||
*/
|
||||
private ByteVector exports;
|
||||
|
||||
/**
|
||||
* number of opens items
|
||||
*/
|
||||
private int openCount;
|
||||
|
||||
/**
|
||||
* The opens items in bytecode form. This byte vector only contains
|
||||
* the items themselves, the number of items is store in openCount
|
||||
*/
|
||||
private ByteVector opens;
|
||||
|
||||
/**
|
||||
* number of uses items
|
||||
*/
|
||||
private int useCount;
|
||||
|
||||
/**
|
||||
* The uses items in bytecode form. This byte vector only contains
|
||||
* the items themselves, the number of items is store in useCount
|
||||
*/
|
||||
private ByteVector uses;
|
||||
|
||||
/**
|
||||
* number of provides items
|
||||
*/
|
||||
private int provideCount;
|
||||
|
||||
/**
|
||||
* The uses provides in bytecode form. This byte vector only contains
|
||||
* the items themselves, the number of items is store in provideCount
|
||||
*/
|
||||
private ByteVector provides;
|
||||
|
||||
ModuleWriter(final ClassWriter cw, final int name,
|
||||
final int access, final int version) {
|
||||
super(Opcodes.ASM6);
|
||||
this.cw = cw;
|
||||
this.size = 16; // name + access + version + 5 counts
|
||||
this.name = name;
|
||||
this.access = access;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMainClass(String mainClass) {
|
||||
if (this.mainClass == 0) { // protect against several calls to visitMainClass
|
||||
cw.newUTF8("ModuleMainClass");
|
||||
attributeCount++;
|
||||
attributesSize += 8;
|
||||
}
|
||||
this.mainClass = cw.newClass(mainClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPackage(String packaze) {
|
||||
if (packages == null) {
|
||||
// protect against several calls to visitPackage
|
||||
cw.newUTF8("ModulePackages");
|
||||
packages = new ByteVector();
|
||||
attributeCount++;
|
||||
attributesSize += 8;
|
||||
}
|
||||
packages.putShort(cw.newPackage(packaze));
|
||||
packageCount++;
|
||||
attributesSize += 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitRequire(String module, int access, String version) {
|
||||
if (requires == null) {
|
||||
requires = new ByteVector();
|
||||
}
|
||||
requires.putShort(cw.newModule(module))
|
||||
.putShort(access)
|
||||
.putShort(version == null? 0: cw.newUTF8(version));
|
||||
requireCount++;
|
||||
size += 6;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitExport(String packaze, int access, String... modules) {
|
||||
if (exports == null) {
|
||||
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) {
|
||||
if (opens == null) {
|
||||
opens = new ByteVector();
|
||||
}
|
||||
opens.putShort(cw.newPackage(packaze)).putShort(access);
|
||||
if (modules == null) {
|
||||
opens.putShort(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) {
|
||||
if (uses == null) {
|
||||
uses = new ByteVector();
|
||||
}
|
||||
uses.putShort(cw.newClass(service));
|
||||
useCount++;
|
||||
size += 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitProvide(String service, String... providers) {
|
||||
if (provides == null) {
|
||||
provides = new ByteVector();
|
||||
}
|
||||
provides.putShort(cw.newClass(service));
|
||||
provides.putShort(providers.length);
|
||||
for(String provider: providers) {
|
||||
provides.putShort(cw.newClass(provider));
|
||||
}
|
||||
provideCount++;
|
||||
size += 4 + 2 * providers.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
// empty
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
/** Where the constants used in this AnnotationWriter must be stored. */
|
||||
private final SymbolTable symbolTable;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
/** The module_name_index field of the JVMS Module attribute. */
|
||||
private final int moduleNameIndex;
|
||||
|
||||
/** The module_flags field of the JVMS Module attribute. */
|
||||
private final int moduleFlags;
|
||||
|
||||
/** The module_version_index field of the JVMS Module attribute. */
|
||||
private final int moduleVersionIndex;
|
||||
|
||||
/** The requires_count field of the JVMS Module attribute. */
|
||||
private int requiresCount;
|
||||
|
||||
/** The binary content of the 'requires' array of the JVMS Module attribute. */
|
||||
private final ByteVector requires;
|
||||
|
||||
/** The exports_count field of the JVMS Module attribute. */
|
||||
private int exportsCount;
|
||||
|
||||
/** The binary content of the 'exports' array of the JVMS Module attribute. */
|
||||
private final ByteVector exports;
|
||||
|
||||
/** The opens_count field of the JVMS Module attribute. */
|
||||
private int opensCount;
|
||||
|
||||
/** The binary content of the 'opens' array of the JVMS Module attribute. */
|
||||
private final ByteVector opens;
|
||||
|
||||
/** The uses_count field of the JVMS Module attribute. */
|
||||
private int usesCount;
|
||||
|
||||
/** The binary content of the 'uses_index' array of the JVMS Module attribute. */
|
||||
private final ByteVector usesIndex;
|
||||
|
||||
/** The provides_count field of the JVMS Module attribute. */
|
||||
private int providesCount;
|
||||
|
||||
/** The binary content of the 'provides' array of the JVMS Module attribute. */
|
||||
private final ByteVector provides;
|
||||
|
||||
/** The provides_count field of the JVMS ModulePackages attribute. */
|
||||
private int packageCount;
|
||||
|
||||
/** The binary content of the 'package_index' array of the JVMS ModulePackages attribute. */
|
||||
private final ByteVector packageIndex;
|
||||
|
||||
/** The main_class_index field of the JVMS ModuleMainClass attribute, or 0. */
|
||||
private int mainClassIndex;
|
||||
|
||||
ModuleWriter(final SymbolTable symbolTable, final int name, final int access, final int version) {
|
||||
super(Opcodes.ASM6);
|
||||
this.symbolTable = symbolTable;
|
||||
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
|
||||
public void visitMainClass(final String mainClass) {
|
||||
this.mainClassIndex = symbolTable.addConstantClass(mainClass).index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPackage(final String packaze) {
|
||||
packageIndex.putShort(symbolTable.addConstantPackage(packaze).index);
|
||||
packageCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
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
|
||||
public void visitOpen(final String packaze, final int access, final String... modules) {
|
||||
opens.putShort(symbolTable.addConstantPackage(packaze).index).putShort(access);
|
||||
if (modules == null) {
|
||||
opens.putShort(0);
|
||||
} else {
|
||||
opens.putShort(modules.length);
|
||||
for (String module : modules) {
|
||||
opens.putShort(symbolTable.addConstantModule(module).index);
|
||||
}
|
||||
}
|
||||
opensCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitUse(final String service) {
|
||||
usesIndex.putShort(symbolTable.addConstantClass(service).index);
|
||||
usesCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitProvide(final String service, final String... providers) {
|
||||
provides.putShort(symbolTable.addConstantClass(service).index);
|
||||
provides.putShort(providers.length);
|
||||
for (String provider : providers) {
|
||||
provides.putShort(symbolTable.addConstantClass(provider).index);
|
||||
}
|
||||
providesCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of Module, ModulePackages and ModuleMainClass attributes generated by this
|
||||
* ModuleWriter.
|
||||
*
|
||||
* @return the number of Module, ModulePackages and ModuleMainClass attributes (between 1 and 3).
|
||||
*/
|
||||
int getAttributeCount() {
|
||||
return 1 + (packageCount > 0 ? 1 : 0) + (mainClassIndex > 0 ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the Module, ModulePackages and ModuleMainClass attributes generated by this
|
||||
* ModuleWriter. Also add the names of these attributes in the constant pool.
|
||||
*
|
||||
* @return the size in bytes of the Module, ModulePackages and ModuleMainClass attributes.
|
||||
*/
|
||||
int computeAttributesSize() {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the Module, ModulePackages and ModuleMainClass attributes generated by this ModuleWriter
|
||||
* in the given ByteVector.
|
||||
*
|
||||
* @param output where the attributes must be put.
|
||||
*/
|
||||
void putAttributes(final ByteVector output) {
|
||||
// 6 bytes for name, flags and version, and 5 * 2 bytes for counts.
|
||||
int moduleAttributeLength =
|
||||
16 + requires.length + exports.length + opens.length + usesIndex.length + provides.length;
|
||||
output
|
||||
.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) {
|
||||
output
|
||||
.putShort(symbolTable.addConstantUtf8(Constants.MODULE_MAIN_CLASS))
|
||||
.putInt(2)
|
||||
.putShort(mainClassIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,372 +1,346 @@
|
|||
/***
|
||||
* 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.
|
||||
*/
|
||||
// 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 the JVM opcodes, access flags and array type codes. This interface
|
||||
* does not define all the JVM opcodes because some opcodes are automatically
|
||||
* handled. For example, the xLOAD and xSTORE opcodes are automatically replaced
|
||||
* by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n
|
||||
* opcodes are therefore not defined in this interface. Likewise for LDC,
|
||||
* automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and
|
||||
* JSR_W.
|
||||
*
|
||||
* The JVM opcodes, access flags and array type codes. This interface does not define all the JVM
|
||||
* opcodes because some opcodes are automatically handled. For example, the xLOAD and xSTORE opcodes
|
||||
* are automatically replaced by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and
|
||||
* xSTORE_n opcodes are therefore not defined in this interface. Likewise for LDC, 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 Eugene Kuleshov
|
||||
*/
|
||||
public interface Opcodes {
|
||||
|
||||
// ASM API versions
|
||||
// ASM API versions.
|
||||
|
||||
int ASM4 = 4 << 16 | 0 << 8 | 0;
|
||||
int ASM5 = 5 << 16 | 0 << 8 | 0;
|
||||
int ASM6 = 6 << 16 | 0 << 8 | 0;
|
||||
int ASM4 = 4 << 16 | 0 << 8;
|
||||
int ASM5 = 5 << 16 | 0 << 8;
|
||||
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;
|
||||
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 V1_9 = 0 << 16 | 53;
|
||||
// Java ClassFile versions (the minor version is stored in the 16 most
|
||||
// significant bits, and the
|
||||
// major version in the 16 least significant bits).
|
||||
|
||||
// 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
|
||||
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
|
||||
/**
|
||||
* Version flag indicating that the class is using 'preview' features.
|
||||
*
|
||||
* <p>{@code version & V_PREVIEW_EXPERIMENTAL == V_PREVIEW_EXPERIMENTAL} tests if a version is
|
||||
* flagged with {@code V_PREVIEW_EXPERIMENTAL}.
|
||||
*
|
||||
* @deprecated This API is experimental.
|
||||
*/
|
||||
@Deprecated int V_PREVIEW_EXPERIMENTAL = 0xFFFF0000;
|
||||
|
||||
// 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;
|
||||
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;
|
||||
// Possible values for the type operand of the NEWARRAY instruction.
|
||||
// See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html#jvms-6.5.newarray.
|
||||
|
||||
// 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;
|
||||
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;
|
||||
// Possible values for the reference_kind field of CONSTANT_MethodHandle_info structures.
|
||||
// See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.4.8.
|
||||
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}.
|
||||
*/
|
||||
int F_NEW = -1;
|
||||
// ASM specific stack map frame types, used in {@link ClassVisitor#visitFrame}.
|
||||
|
||||
/**
|
||||
* Represents a compressed frame with complete frame data.
|
||||
*/
|
||||
int F_FULL = 0;
|
||||
/** An expanded frame. See {@link ClassReader#EXPAND_FRAMES}. */
|
||||
int F_NEW = -1;
|
||||
|
||||
/**
|
||||
* Represents a compressed frame where locals are the same as the locals in
|
||||
* the previous frame, except that additional 1-3 locals are defined, and
|
||||
* with an empty stack.
|
||||
*/
|
||||
int F_APPEND = 1;
|
||||
/** A compressed frame with complete frame data. */
|
||||
int F_FULL = 0;
|
||||
|
||||
/**
|
||||
* Represents a compressed frame where locals are the same as the locals in
|
||||
* the previous frame, except that the last 1-3 locals are absent and with
|
||||
* an empty stack.
|
||||
*/
|
||||
int F_CHOP = 2;
|
||||
/**
|
||||
* A compressed frame where locals are the same as the locals in the previous frame, except that
|
||||
* additional 1-3 locals are defined, and with an empty stack.
|
||||
*/
|
||||
int F_APPEND = 1;
|
||||
|
||||
/**
|
||||
* Represents a compressed frame with exactly the same locals as the
|
||||
* previous frame and with an empty stack.
|
||||
*/
|
||||
int F_SAME = 3;
|
||||
/**
|
||||
* A compressed frame where locals are the same as the locals in the previous frame, except that
|
||||
* the last 1-3 locals are absent and with an empty stack.
|
||||
*/
|
||||
int F_CHOP = 2;
|
||||
|
||||
/**
|
||||
* Represents a compressed frame with exactly the same locals as the
|
||||
* previous frame and with a single value on the stack.
|
||||
*/
|
||||
int F_SAME1 = 4;
|
||||
/**
|
||||
* A compressed frame with exactly the same locals as the previous frame and with an empty stack.
|
||||
*/
|
||||
int F_SAME = 3;
|
||||
|
||||
// Do not try to change the following code to use auto-boxing,
|
||||
// these values are compared by reference and not by value
|
||||
// The constructor of Integer was deprecated in 9
|
||||
// but we are stuck with it by backward compatibility
|
||||
@SuppressWarnings("deprecation") Integer TOP = new Integer(0);
|
||||
@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);
|
||||
/**
|
||||
* A compressed frame with exactly the same locals as the previous frame and with a single value
|
||||
* on the stack.
|
||||
*/
|
||||
int F_SAME1 = 4;
|
||||
|
||||
// opcodes // visit method (- = idem)
|
||||
// Standard stack map frame element types, used in {@link ClassVisitor#visitFrame}.
|
||||
|
||||
int NOP = 0; // visitInsn
|
||||
int ACONST_NULL = 1; // -
|
||||
int ICONST_M1 = 2; // -
|
||||
int ICONST_0 = 3; // -
|
||||
int ICONST_1 = 4; // -
|
||||
int ICONST_2 = 5; // -
|
||||
int ICONST_3 = 6; // -
|
||||
int ICONST_4 = 7; // -
|
||||
int ICONST_5 = 8; // -
|
||||
int LCONST_0 = 9; // -
|
||||
int LCONST_1 = 10; // -
|
||||
int FCONST_0 = 11; // -
|
||||
int FCONST_1 = 12; // -
|
||||
int FCONST_2 = 13; // -
|
||||
int DCONST_0 = 14; // -
|
||||
int DCONST_1 = 15; // -
|
||||
int BIPUSH = 16; // visitIntInsn
|
||||
int SIPUSH = 17; // -
|
||||
int LDC = 18; // visitLdcInsn
|
||||
// int LDC_W = 19; // -
|
||||
// int LDC2_W = 20; // -
|
||||
int ILOAD = 21; // visitVarInsn
|
||||
int LLOAD = 22; // -
|
||||
int FLOAD = 23; // -
|
||||
int DLOAD = 24; // -
|
||||
int ALOAD = 25; // -
|
||||
// int ILOAD_0 = 26; // -
|
||||
// int ILOAD_1 = 27; // -
|
||||
// int ILOAD_2 = 28; // -
|
||||
// int ILOAD_3 = 29; // -
|
||||
// int LLOAD_0 = 30; // -
|
||||
// int LLOAD_1 = 31; // -
|
||||
// int LLOAD_2 = 32; // -
|
||||
// int LLOAD_3 = 33; // -
|
||||
// int FLOAD_0 = 34; // -
|
||||
// int FLOAD_1 = 35; // -
|
||||
// int FLOAD_2 = 36; // -
|
||||
// int FLOAD_3 = 37; // -
|
||||
// int DLOAD_0 = 38; // -
|
||||
// int DLOAD_1 = 39; // -
|
||||
// int DLOAD_2 = 40; // -
|
||||
// int DLOAD_3 = 41; // -
|
||||
// int ALOAD_0 = 42; // -
|
||||
// int ALOAD_1 = 43; // -
|
||||
// int ALOAD_2 = 44; // -
|
||||
// int ALOAD_3 = 45; // -
|
||||
int IALOAD = 46; // visitInsn
|
||||
int LALOAD = 47; // -
|
||||
int FALOAD = 48; // -
|
||||
int DALOAD = 49; // -
|
||||
int AALOAD = 50; // -
|
||||
int BALOAD = 51; // -
|
||||
int CALOAD = 52; // -
|
||||
int SALOAD = 53; // -
|
||||
int ISTORE = 54; // visitVarInsn
|
||||
int LSTORE = 55; // -
|
||||
int FSTORE = 56; // -
|
||||
int DSTORE = 57; // -
|
||||
int ASTORE = 58; // -
|
||||
// int ISTORE_0 = 59; // -
|
||||
// int ISTORE_1 = 60; // -
|
||||
// int ISTORE_2 = 61; // -
|
||||
// int ISTORE_3 = 62; // -
|
||||
// int LSTORE_0 = 63; // -
|
||||
// int LSTORE_1 = 64; // -
|
||||
// int LSTORE_2 = 65; // -
|
||||
// int LSTORE_3 = 66; // -
|
||||
// int FSTORE_0 = 67; // -
|
||||
// int FSTORE_1 = 68; // -
|
||||
// int FSTORE_2 = 69; // -
|
||||
// int FSTORE_3 = 70; // -
|
||||
// int DSTORE_0 = 71; // -
|
||||
// int DSTORE_1 = 72; // -
|
||||
// int DSTORE_2 = 73; // -
|
||||
// int DSTORE_3 = 74; // -
|
||||
// int ASTORE_0 = 75; // -
|
||||
// int ASTORE_1 = 76; // -
|
||||
// int ASTORE_2 = 77; // -
|
||||
// int ASTORE_3 = 78; // -
|
||||
int IASTORE = 79; // visitInsn
|
||||
int LASTORE = 80; // -
|
||||
int FASTORE = 81; // -
|
||||
int DASTORE = 82; // -
|
||||
int AASTORE = 83; // -
|
||||
int BASTORE = 84; // -
|
||||
int CASTORE = 85; // -
|
||||
int SASTORE = 86; // -
|
||||
int POP = 87; // -
|
||||
int POP2 = 88; // -
|
||||
int DUP = 89; // -
|
||||
int DUP_X1 = 90; // -
|
||||
int DUP_X2 = 91; // -
|
||||
int DUP2 = 92; // -
|
||||
int DUP2_X1 = 93; // -
|
||||
int DUP2_X2 = 94; // -
|
||||
int SWAP = 95; // -
|
||||
int IADD = 96; // -
|
||||
int LADD = 97; // -
|
||||
int FADD = 98; // -
|
||||
int DADD = 99; // -
|
||||
int ISUB = 100; // -
|
||||
int LSUB = 101; // -
|
||||
int FSUB = 102; // -
|
||||
int DSUB = 103; // -
|
||||
int IMUL = 104; // -
|
||||
int LMUL = 105; // -
|
||||
int FMUL = 106; // -
|
||||
int DMUL = 107; // -
|
||||
int IDIV = 108; // -
|
||||
int LDIV = 109; // -
|
||||
int FDIV = 110; // -
|
||||
int DDIV = 111; // -
|
||||
int IREM = 112; // -
|
||||
int LREM = 113; // -
|
||||
int FREM = 114; // -
|
||||
int DREM = 115; // -
|
||||
int INEG = 116; // -
|
||||
int LNEG = 117; // -
|
||||
int FNEG = 118; // -
|
||||
int DNEG = 119; // -
|
||||
int ISHL = 120; // -
|
||||
int LSHL = 121; // -
|
||||
int ISHR = 122; // -
|
||||
int LSHR = 123; // -
|
||||
int IUSHR = 124; // -
|
||||
int LUSHR = 125; // -
|
||||
int IAND = 126; // -
|
||||
int LAND = 127; // -
|
||||
int IOR = 128; // -
|
||||
int LOR = 129; // -
|
||||
int IXOR = 130; // -
|
||||
int LXOR = 131; // -
|
||||
int IINC = 132; // visitIincInsn
|
||||
int I2L = 133; // visitInsn
|
||||
int I2F = 134; // -
|
||||
int I2D = 135; // -
|
||||
int L2I = 136; // -
|
||||
int L2F = 137; // -
|
||||
int L2D = 138; // -
|
||||
int F2I = 139; // -
|
||||
int F2L = 140; // -
|
||||
int F2D = 141; // -
|
||||
int D2I = 142; // -
|
||||
int D2L = 143; // -
|
||||
int D2F = 144; // -
|
||||
int I2B = 145; // -
|
||||
int I2C = 146; // -
|
||||
int I2S = 147; // -
|
||||
int LCMP = 148; // -
|
||||
int FCMPL = 149; // -
|
||||
int FCMPG = 150; // -
|
||||
int DCMPL = 151; // -
|
||||
int DCMPG = 152; // -
|
||||
int IFEQ = 153; // visitJumpInsn
|
||||
int IFNE = 154; // -
|
||||
int IFLT = 155; // -
|
||||
int IFGE = 156; // -
|
||||
int IFGT = 157; // -
|
||||
int IFLE = 158; // -
|
||||
int IF_ICMPEQ = 159; // -
|
||||
int IF_ICMPNE = 160; // -
|
||||
int IF_ICMPLT = 161; // -
|
||||
int IF_ICMPGE = 162; // -
|
||||
int IF_ICMPGT = 163; // -
|
||||
int IF_ICMPLE = 164; // -
|
||||
int IF_ACMPEQ = 165; // -
|
||||
int IF_ACMPNE = 166; // -
|
||||
int GOTO = 167; // -
|
||||
int JSR = 168; // -
|
||||
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; // -
|
||||
Integer TOP = Frame.ITEM_TOP;
|
||||
Integer INTEGER = Frame.ITEM_INTEGER;
|
||||
Integer FLOAT = Frame.ITEM_FLOAT;
|
||||
Integer DOUBLE = Frame.ITEM_DOUBLE;
|
||||
Integer LONG = Frame.ITEM_LONG;
|
||||
Integer NULL = Frame.ITEM_NULL;
|
||||
Integer UNINITIALIZED_THIS = Frame.ITEM_UNINITIALIZED_THIS;
|
||||
|
||||
// The JVM opcode values (with the MethodVisitor method name used to visit them in comment, and
|
||||
// where '-' means 'same method name as on the previous line').
|
||||
// See https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-6.html.
|
||||
|
||||
int NOP = 0; // visitInsn
|
||||
int ACONST_NULL = 1; // -
|
||||
int ICONST_M1 = 2; // -
|
||||
int ICONST_0 = 3; // -
|
||||
int ICONST_1 = 4; // -
|
||||
int ICONST_2 = 5; // -
|
||||
int ICONST_3 = 6; // -
|
||||
int ICONST_4 = 7; // -
|
||||
int ICONST_5 = 8; // -
|
||||
int LCONST_0 = 9; // -
|
||||
int LCONST_1 = 10; // -
|
||||
int FCONST_0 = 11; // -
|
||||
int FCONST_1 = 12; // -
|
||||
int FCONST_2 = 13; // -
|
||||
int DCONST_0 = 14; // -
|
||||
int DCONST_1 = 15; // -
|
||||
int BIPUSH = 16; // visitIntInsn
|
||||
int SIPUSH = 17; // -
|
||||
int LDC = 18; // visitLdcInsn
|
||||
int ILOAD = 21; // visitVarInsn
|
||||
int LLOAD = 22; // -
|
||||
int FLOAD = 23; // -
|
||||
int DLOAD = 24; // -
|
||||
int ALOAD = 25; // -
|
||||
int IALOAD = 46; // visitInsn
|
||||
int LALOAD = 47; // -
|
||||
int FALOAD = 48; // -
|
||||
int DALOAD = 49; // -
|
||||
int AALOAD = 50; // -
|
||||
int BALOAD = 51; // -
|
||||
int CALOAD = 52; // -
|
||||
int SALOAD = 53; // -
|
||||
int ISTORE = 54; // visitVarInsn
|
||||
int LSTORE = 55; // -
|
||||
int FSTORE = 56; // -
|
||||
int DSTORE = 57; // -
|
||||
int ASTORE = 58; // -
|
||||
int IASTORE = 79; // visitInsn
|
||||
int LASTORE = 80; // -
|
||||
int FASTORE = 81; // -
|
||||
int DASTORE = 82; // -
|
||||
int AASTORE = 83; // -
|
||||
int BASTORE = 84; // -
|
||||
int CASTORE = 85; // -
|
||||
int SASTORE = 86; // -
|
||||
int POP = 87; // -
|
||||
int POP2 = 88; // -
|
||||
int DUP = 89; // -
|
||||
int DUP_X1 = 90; // -
|
||||
int DUP_X2 = 91; // -
|
||||
int DUP2 = 92; // -
|
||||
int DUP2_X1 = 93; // -
|
||||
int DUP2_X2 = 94; // -
|
||||
int SWAP = 95; // -
|
||||
int IADD = 96; // -
|
||||
int LADD = 97; // -
|
||||
int FADD = 98; // -
|
||||
int DADD = 99; // -
|
||||
int ISUB = 100; // -
|
||||
int LSUB = 101; // -
|
||||
int FSUB = 102; // -
|
||||
int DSUB = 103; // -
|
||||
int IMUL = 104; // -
|
||||
int LMUL = 105; // -
|
||||
int FMUL = 106; // -
|
||||
int DMUL = 107; // -
|
||||
int IDIV = 108; // -
|
||||
int LDIV = 109; // -
|
||||
int FDIV = 110; // -
|
||||
int DDIV = 111; // -
|
||||
int IREM = 112; // -
|
||||
int LREM = 113; // -
|
||||
int FREM = 114; // -
|
||||
int DREM = 115; // -
|
||||
int INEG = 116; // -
|
||||
int LNEG = 117; // -
|
||||
int FNEG = 118; // -
|
||||
int DNEG = 119; // -
|
||||
int ISHL = 120; // -
|
||||
int LSHL = 121; // -
|
||||
int ISHR = 122; // -
|
||||
int LSHR = 123; // -
|
||||
int IUSHR = 124; // -
|
||||
int LUSHR = 125; // -
|
||||
int IAND = 126; // -
|
||||
int LAND = 127; // -
|
||||
int IOR = 128; // -
|
||||
int LOR = 129; // -
|
||||
int IXOR = 130; // -
|
||||
int LXOR = 131; // -
|
||||
int IINC = 132; // visitIincInsn
|
||||
int I2L = 133; // visitInsn
|
||||
int I2F = 134; // -
|
||||
int I2D = 135; // -
|
||||
int L2I = 136; // -
|
||||
int L2F = 137; // -
|
||||
int L2D = 138; // -
|
||||
int F2I = 139; // -
|
||||
int F2L = 140; // -
|
||||
int F2D = 141; // -
|
||||
int D2I = 142; // -
|
||||
int D2L = 143; // -
|
||||
int D2F = 144; // -
|
||||
int I2B = 145; // -
|
||||
int I2C = 146; // -
|
||||
int I2S = 147; // -
|
||||
int LCMP = 148; // -
|
||||
int FCMPL = 149; // -
|
||||
int FCMPG = 150; // -
|
||||
int DCMPL = 151; // -
|
||||
int DCMPG = 152; // -
|
||||
int IFEQ = 153; // visitJumpInsn
|
||||
int IFNE = 154; // -
|
||||
int IFLT = 155; // -
|
||||
int IFGE = 156; // -
|
||||
int IFGT = 157; // -
|
||||
int IFLE = 158; // -
|
||||
int IF_ICMPEQ = 159; // -
|
||||
int IF_ICMPNE = 160; // -
|
||||
int IF_ICMPLT = 161; // -
|
||||
int IF_ICMPGE = 162; // -
|
||||
int IF_ICMPGT = 163; // -
|
||||
int IF_ICMPLE = 164; // -
|
||||
int IF_ACMPEQ = 165; // -
|
||||
int IF_ACMPNE = 166; // -
|
||||
int GOTO = 167; // -
|
||||
int JSR = 168; // -
|
||||
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 MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
|
||||
int IFNULL = 198; // visitJumpInsn
|
||||
int IFNONNULL = 199; // -
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
* 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
|
||||
* 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
|
||||
* information on {@code org.springframework.asm}.
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -1,196 +1,201 @@
|
|||
/***
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2013 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.
|
||||
*/
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* The path to a type argument, wildcard bound, array element type, or static
|
||||
* inner type within an enclosing type.
|
||||
*
|
||||
* The path to a type argument, wildcard bound, array element type, or static inner type within an
|
||||
* enclosing type.
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class TypePath {
|
||||
|
||||
/**
|
||||
* A type path step that steps into the element type of an array type. See
|
||||
* {@link #getStep getStep}.
|
||||
*/
|
||||
public static final int ARRAY_ELEMENT = 0;
|
||||
/** A type path step that steps into the element type of an array type. See {@link #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 getStep}.
|
||||
*/
|
||||
public static final int INNER_TYPE = 1;
|
||||
/** A type path step that steps into the nested type of a class type. See {@link #getStep}. */
|
||||
public static final int INNER_TYPE = 1;
|
||||
|
||||
/**
|
||||
* A type path step that steps into the bound of a wildcard type. See
|
||||
* {@link #getStep getStep}.
|
||||
*/
|
||||
public static final int WILDCARD_BOUND = 2;
|
||||
/** A type path step that steps into the bound of a wildcard type. See {@link #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 getStep}.
|
||||
*/
|
||||
public static final int TYPE_ARGUMENT = 3;
|
||||
/** A type path step that steps into a type argument of a generic type. See {@link #getStep}. */
|
||||
public static final int TYPE_ARGUMENT = 3;
|
||||
|
||||
/**
|
||||
* The byte array where the path is stored, in Java class file format.
|
||||
*/
|
||||
byte[] b;
|
||||
/**
|
||||
* 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
|
||||
* 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 in 'b'.
|
||||
*/
|
||||
int offset;
|
||||
/** The offset of the first byte of the type_path JVMS structure in {@link #typePathContainer}. */
|
||||
private final int typePathOffset;
|
||||
|
||||
/**
|
||||
* Creates a new type path.
|
||||
*
|
||||
* @param b
|
||||
* the byte array containing the type path in Java class file
|
||||
* format.
|
||||
* @param offset
|
||||
* the offset of the first byte of the type path in 'b'.
|
||||
*/
|
||||
TypePath(byte[] b, int offset) {
|
||||
this.b = b;
|
||||
this.offset = offset;
|
||||
/**
|
||||
* Constructs a new TypePath.
|
||||
*
|
||||
* @param typePathContainer a byte array containing a type_path JVMS structure.
|
||||
* @param typePathOffset the offset of the first byte of the type_path structure in
|
||||
* typePathContainer.
|
||||
*/
|
||||
TypePath(final byte[] typePathContainer, final int typePathOffset) {
|
||||
this.typePathContainer = typePathContainer;
|
||||
this.typePathOffset = typePathOffset;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length of this path.
|
||||
*
|
||||
* @return the length of this path.
|
||||
*/
|
||||
public int getLength() {
|
||||
return b[offset];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the given step of this path.
|
||||
*
|
||||
* @param index
|
||||
* an index between 0 and {@link #getLength()}, exclusive.
|
||||
* @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE
|
||||
* INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or
|
||||
* {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
|
||||
*/
|
||||
public int getStep(int index) {
|
||||
return b[offset + 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 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 typePathLength = typePath.length();
|
||||
ByteVector output = new ByteVector(typePathLength);
|
||||
output.putByte(0);
|
||||
int typePathIndex = 0;
|
||||
while (typePathIndex < typePathLength) {
|
||||
char c = typePath.charAt(typePathIndex++);
|
||||
if (c == '[') {
|
||||
output.put11(ARRAY_ELEMENT, 0);
|
||||
} else if (c == '.') {
|
||||
output.put11(INNER_TYPE, 0);
|
||||
} else if (c == '*') {
|
||||
output.put11(WILDCARD_BOUND, 0);
|
||||
} else if (c >= '0' && c <= '9') {
|
||||
int typeArg = c - '0';
|
||||
while (typePathIndex < typePathLength) {
|
||||
c = typePath.charAt(typePathIndex++);
|
||||
if (c >= '0' && c <= '9') {
|
||||
typeArg = typeArg * 10 + c - '0';
|
||||
} else if (c == ';') {
|
||||
break;
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
int n = typePath.length();
|
||||
ByteVector out = new ByteVector(n);
|
||||
out.putByte(0);
|
||||
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.put11(TYPE_ARGUMENT, typeArg);
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
output.data[0] = (byte) (output.length / 2);
|
||||
return new TypePath(output.data, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this type path. {@link #ARRAY_ELEMENT
|
||||
* ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE
|
||||
* INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps
|
||||
* with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type
|
||||
* argument index in decimal form followed by ';'.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
int length = getLength();
|
||||
StringBuilder result = new StringBuilder(length * 2);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
switch (getStep(i)) {
|
||||
case ARRAY_ELEMENT:
|
||||
result.append('[');
|
||||
break;
|
||||
case INNER_TYPE:
|
||||
result.append('.');
|
||||
break;
|
||||
case WILDCARD_BOUND:
|
||||
result.append('*');
|
||||
break;
|
||||
case TYPE_ARGUMENT:
|
||||
result.append(getStepArgument(i)).append(';');
|
||||
break;
|
||||
default:
|
||||
result.append('_');
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
/**
|
||||
* Returns a string representation of this type path. {@link #ARRAY_ELEMENT} steps are represented
|
||||
* with '[', {@link #INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND} steps with '*' and {@link
|
||||
* #TYPE_ARGUMENT} steps with their type argument index in decimal form followed by ';'.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
int length = getLength();
|
||||
StringBuilder result = new StringBuilder(length * 2);
|
||||
for (int i = 0; i < length; ++i) {
|
||||
switch (getStep(i)) {
|
||||
case ARRAY_ELEMENT:
|
||||
result.append('[');
|
||||
break;
|
||||
case INNER_TYPE:
|
||||
result.append('.');
|
||||
break;
|
||||
case WILDCARD_BOUND:
|
||||
result.append('*');
|
||||
break;
|
||||
case TYPE_ARGUMENT:
|
||||
result.append(getStepArgument(i)).append(';');
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError();
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,452 +1,436 @@
|
|||
/***
|
||||
* ASM: a very small and fast Java bytecode manipulation framework
|
||||
* Copyright (c) 2000-2013 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.
|
||||
*/
|
||||
// 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 reference to a type appearing in a class, field or method declaration, or
|
||||
* on an instruction. Such a reference designates the part of the class where
|
||||
* the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws'
|
||||
* clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable
|
||||
* declaration, etc).
|
||||
*
|
||||
* A reference to a type appearing in a class, field or method declaration, or on an instruction.
|
||||
* Such a reference designates the part of the class where the referenced type is appearing (e.g. an
|
||||
* 'extends', 'implements' or 'throws' clause, a 'new' instruction, a 'catch' clause, a type cast, a
|
||||
* local variable declaration, etc).
|
||||
*
|
||||
* @author Eric Bruneton
|
||||
*/
|
||||
public class TypeReference {
|
||||
|
||||
/**
|
||||
* The sort of type references that target a type parameter of a generic
|
||||
* class. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int CLASS_TYPE_PARAMETER = 0x00;
|
||||
/**
|
||||
* The sort of type references that target a type parameter of a generic class. See {@link
|
||||
* #getSort}.
|
||||
*/
|
||||
public static final int CLASS_TYPE_PARAMETER = 0x00;
|
||||
|
||||
/**
|
||||
* The sort of type references that target a type parameter of a generic
|
||||
* method. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int METHOD_TYPE_PARAMETER = 0x01;
|
||||
/**
|
||||
* The sort of type references that target a type parameter of a generic method. See {@link
|
||||
* #getSort}.
|
||||
*/
|
||||
public static final int METHOD_TYPE_PARAMETER = 0x01;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the super class of a class or one
|
||||
* of the interfaces it implements. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int CLASS_EXTENDS = 0x10;
|
||||
/**
|
||||
* The sort of type references that target the super class of a class or one of the interfaces it
|
||||
* implements. See {@link #getSort}.
|
||||
*/
|
||||
public static final int CLASS_EXTENDS = 0x10;
|
||||
|
||||
/**
|
||||
* The sort of type references that target a bound of a type parameter of a
|
||||
* generic class. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11;
|
||||
/**
|
||||
* The sort of type references that target a bound of a type parameter of a generic class. See
|
||||
* {@link #getSort}.
|
||||
*/
|
||||
public static final int CLASS_TYPE_PARAMETER_BOUND = 0x11;
|
||||
|
||||
/**
|
||||
* The sort of type references that target a bound of a type parameter of a
|
||||
* generic method. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12;
|
||||
/**
|
||||
* The sort of type references that target a bound of a type parameter of a generic method. See
|
||||
* {@link #getSort}.
|
||||
*/
|
||||
public static final int METHOD_TYPE_PARAMETER_BOUND = 0x12;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the type of a field. See
|
||||
* {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int FIELD = 0x13;
|
||||
/** The sort of type references that target the type of a field. See {@link #getSort}. */
|
||||
public static final int FIELD = 0x13;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the return type of a method. See
|
||||
* {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int METHOD_RETURN = 0x14;
|
||||
/** The sort of type references that target the return type of a method. See {@link #getSort}. */
|
||||
public static final int METHOD_RETURN = 0x14;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the receiver type of a method.
|
||||
* See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int METHOD_RECEIVER = 0x15;
|
||||
/**
|
||||
* The sort of type references that target the receiver type of a method. See {@link #getSort}.
|
||||
*/
|
||||
public static final int METHOD_RECEIVER = 0x15;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the type of a formal parameter of
|
||||
* a method. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int METHOD_FORMAL_PARAMETER = 0x16;
|
||||
/**
|
||||
* The sort of type references that target the type of a formal parameter of a method. See {@link
|
||||
* #getSort}.
|
||||
*/
|
||||
public static final int METHOD_FORMAL_PARAMETER = 0x16;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the type of an exception declared
|
||||
* in the throws clause of a method. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int THROWS = 0x17;
|
||||
/**
|
||||
* The sort of type references that target the type of an exception declared in the throws clause
|
||||
* of a method. See {@link #getSort}.
|
||||
*/
|
||||
public static final int THROWS = 0x17;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the type of a local variable in a
|
||||
* method. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int LOCAL_VARIABLE = 0x40;
|
||||
/**
|
||||
* The sort of type references that target the type of a local variable in a method. See {@link
|
||||
* #getSort}.
|
||||
*/
|
||||
public static final int LOCAL_VARIABLE = 0x40;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the type of a resource variable
|
||||
* in a method. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int RESOURCE_VARIABLE = 0x41;
|
||||
/**
|
||||
* The sort of type references that target the type of a resource variable in a method. See {@link
|
||||
* #getSort}.
|
||||
*/
|
||||
public static final int RESOURCE_VARIABLE = 0x41;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the type of the exception of a
|
||||
* 'catch' clause in a method. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int EXCEPTION_PARAMETER = 0x42;
|
||||
/**
|
||||
* The sort of type references that target the type of the exception of a 'catch' clause in a
|
||||
* method. See {@link #getSort}.
|
||||
*/
|
||||
public static final int EXCEPTION_PARAMETER = 0x42;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the type declared in an
|
||||
* 'instanceof' instruction. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int INSTANCEOF = 0x43;
|
||||
/**
|
||||
* The sort of type references that target the type declared in an 'instanceof' instruction. See
|
||||
* {@link #getSort}.
|
||||
*/
|
||||
public static final int INSTANCEOF = 0x43;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the type of the object created by
|
||||
* a 'new' instruction. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int NEW = 0x44;
|
||||
/**
|
||||
* The sort of type references that target the type of the object created by a 'new' instruction.
|
||||
* See {@link #getSort}.
|
||||
*/
|
||||
public static final int NEW = 0x44;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the receiver type of a
|
||||
* constructor reference. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int CONSTRUCTOR_REFERENCE = 0x45;
|
||||
/**
|
||||
* The sort of type references that target the receiver type of a constructor reference. See
|
||||
* {@link #getSort}.
|
||||
*/
|
||||
public static final int CONSTRUCTOR_REFERENCE = 0x45;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the receiver type of a method
|
||||
* reference. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int METHOD_REFERENCE = 0x46;
|
||||
/**
|
||||
* The sort of type references that target the receiver type of a method reference. See {@link
|
||||
* #getSort}.
|
||||
*/
|
||||
public static final int METHOD_REFERENCE = 0x46;
|
||||
|
||||
/**
|
||||
* The sort of type references that target the type declared in an explicit
|
||||
* or implicit cast instruction. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int CAST = 0x47;
|
||||
/**
|
||||
* The sort of type references that target the type declared in an explicit or implicit cast
|
||||
* instruction. See {@link #getSort}.
|
||||
*/
|
||||
public static final int CAST = 0x47;
|
||||
|
||||
/**
|
||||
* The sort of type references that target a type parameter of a generic
|
||||
* constructor in a constructor call. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
|
||||
/**
|
||||
* The sort of type references that target a type parameter of a generic constructor in a
|
||||
* constructor call. See {@link #getSort}.
|
||||
*/
|
||||
public static final int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
|
||||
|
||||
/**
|
||||
* The sort of type references that target a type parameter of a generic
|
||||
* method in a method call. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
|
||||
/**
|
||||
* The sort of type references that target a type parameter of a generic method in a method call.
|
||||
* See {@link #getSort}.
|
||||
*/
|
||||
public static final int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
|
||||
|
||||
/**
|
||||
* The sort of type references that target a type parameter of a generic
|
||||
* constructor in a constructor reference. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
|
||||
/**
|
||||
* The sort of type references that target a type parameter of a generic constructor in a
|
||||
* constructor reference. See {@link #getSort}.
|
||||
*/
|
||||
public static final int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
|
||||
|
||||
/**
|
||||
* The sort of type references that target a type parameter of a generic
|
||||
* method in a method reference. See {@link #getSort getSort}.
|
||||
*/
|
||||
public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
|
||||
/**
|
||||
* The sort of type references that target a type parameter of a generic method in a method
|
||||
* reference. See {@link #getSort}.
|
||||
*/
|
||||
public static final int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
|
||||
|
||||
/**
|
||||
* The type reference value in Java class file format.
|
||||
*/
|
||||
private int value;
|
||||
/**
|
||||
* 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
|
||||
* 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.
|
||||
*
|
||||
* @param typeRef
|
||||
* the int encoded value of the type reference, as received in a
|
||||
* visit method related to type annotations, like
|
||||
* visitTypeAnnotation.
|
||||
*/
|
||||
public TypeReference(int typeRef) {
|
||||
this.value = typeRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a type reference of the given sort.
|
||||
*
|
||||
* @param sort
|
||||
* {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
|
||||
* {@link #METHOD_RECEIVER METHOD_RECEIVER},
|
||||
* {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
|
||||
* {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
|
||||
* {@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.
|
||||
*/
|
||||
public static TypeReference newTypeReference(int sort) {
|
||||
return new TypeReference(sort << 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to a type parameter of a generic class or method.
|
||||
*
|
||||
* @param sort
|
||||
* {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
|
||||
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
|
||||
* @param paramIndex
|
||||
* the type parameter index.
|
||||
* @return a reference to the given generic class or method type parameter.
|
||||
*/
|
||||
public static TypeReference newTypeParameterReference(int sort,
|
||||
int paramIndex) {
|
||||
return new TypeReference((sort << 24) | (paramIndex << 16));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to a type parameter bound of a generic class or
|
||||
* method.
|
||||
*
|
||||
* @param sort
|
||||
* {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
|
||||
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
|
||||
* @param paramIndex
|
||||
* the type parameter index.
|
||||
* @param boundIndex
|
||||
* the type bound index within the above type parameters.
|
||||
* @return a reference to the given generic class or method type parameter
|
||||
* bound.
|
||||
*/
|
||||
public static TypeReference newTypeParameterBoundReference(int sort,
|
||||
int paramIndex, int boundIndex) {
|
||||
return new TypeReference((sort << 24) | (paramIndex << 16)
|
||||
| (boundIndex << 8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the super class or to an interface of the
|
||||
* 'implements' clause of a class.
|
||||
*
|
||||
* @param itfIndex
|
||||
* the index of an interface in the 'implements' clause of a
|
||||
* class, or -1 to reference the super class of the class.
|
||||
* @return a reference to the given super type of a class.
|
||||
*/
|
||||
public static TypeReference newSuperTypeReference(int itfIndex) {
|
||||
itfIndex &= 0xFFFF;
|
||||
return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the type of a formal parameter of a method.
|
||||
*
|
||||
* @param paramIndex
|
||||
* the formal parameter index.
|
||||
*
|
||||
* @return a reference to the type of the given method formal parameter.
|
||||
*/
|
||||
public static TypeReference newFormalParameterReference(int paramIndex) {
|
||||
return new TypeReference((METHOD_FORMAL_PARAMETER << 24)
|
||||
| (paramIndex << 16));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the type of an exception, in a 'throws' clause of
|
||||
* a method.
|
||||
*
|
||||
* @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 newExceptionReference(int exceptionIndex) {
|
||||
return new TypeReference((THROWS << 24) | (exceptionIndex << 8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the type of the exception declared in a 'catch'
|
||||
* clause of a method.
|
||||
*
|
||||
* @param tryCatchBlockIndex
|
||||
* the index of a try catch block (using the order in which they
|
||||
* are visited with visitTryCatchBlock).
|
||||
*
|
||||
* @return a reference to the type of the given exception.
|
||||
*/
|
||||
public static TypeReference newTryCatchReference(int tryCatchBlockIndex) {
|
||||
return new TypeReference((EXCEPTION_PARAMETER << 24)
|
||||
| (tryCatchBlockIndex << 8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the type of a type argument in a constructor or
|
||||
* method call or reference.
|
||||
*
|
||||
* @param sort
|
||||
* {@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}.
|
||||
* @param argIndex
|
||||
* the type argument index.
|
||||
*
|
||||
* @return a reference to the type of the given type argument.
|
||||
*/
|
||||
public static TypeReference newTypeArgumentReference(int sort, int argIndex) {
|
||||
return new TypeReference((sort << 24) | argIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sort of this type reference.
|
||||
*
|
||||
* @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
|
||||
* {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
|
||||
* {@link #CLASS_EXTENDS CLASS_EXTENDS},
|
||||
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND},
|
||||
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND},
|
||||
* {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
|
||||
* {@link #METHOD_RECEIVER METHOD_RECEIVER},
|
||||
* {@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},
|
||||
* {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
|
||||
* {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE},
|
||||
* {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@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}.
|
||||
*/
|
||||
public int getSort() {
|
||||
return value >>> 24;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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},
|
||||
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
|
||||
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
|
||||
*
|
||||
* @return a type parameter index.
|
||||
*/
|
||||
public int getTypeParameterIndex() {
|
||||
return (value & 0x00FF0000) >> 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the type parameter bound, within the type parameter
|
||||
* {@link #getTypeParameterIndex}, referenced by this type reference. This
|
||||
* method must only be used for type references whose sort is
|
||||
* {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
|
||||
* {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
|
||||
*
|
||||
* @return a type parameter bound index.
|
||||
*/
|
||||
public int getTypeParameterBoundIndex() {
|
||||
return (value & 0x0000FF00) >> 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the "super type" of a class that is referenced by
|
||||
* this type reference. This method must only be used for type references
|
||||
* whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}.
|
||||
*
|
||||
* @return the index of an interface in the 'implements' clause of a class,
|
||||
* or -1 if this type reference references the type of the super
|
||||
* class.
|
||||
*/
|
||||
public int getSuperTypeIndex() {
|
||||
return (short) ((value & 0x00FFFF00) >> 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the formal parameter whose type is referenced by
|
||||
* this type reference. This method must only be used for type references
|
||||
* whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}.
|
||||
*
|
||||
* @return a formal parameter index.
|
||||
*/
|
||||
public int getFormalParameterIndex() {
|
||||
return (value & 0x00FF0000) >> 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the exception, in a 'throws' clause of a method,
|
||||
* whose type is referenced by this type reference. This method must only be
|
||||
* used for type references whose sort is {@link #THROWS THROWS}.
|
||||
*
|
||||
* @return the index of an exception in the 'throws' clause of a method.
|
||||
*/
|
||||
public int getExceptionIndex() {
|
||||
return (value & 0x00FFFF00) >> 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the try catch block (using the order in which they
|
||||
* are visited with visitTryCatchBlock), whose 'catch' type is referenced by
|
||||
* this type reference. This method must only be used for type references
|
||||
* whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} .
|
||||
*
|
||||
* @return the index of an exception in the 'throws' clause of a method.
|
||||
*/
|
||||
public int getTryCatchBlockIndex() {
|
||||
return (value & 0x00FFFF00) >> 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* Constructs a new TypeReference.
|
||||
*
|
||||
* @param typeRef the int encoded value of the type reference, as received in a visit method
|
||||
* related to type annotations, such as {@link ClassVisitor#visitTypeAnnotation}.
|
||||
*/
|
||||
public TypeReference(final int typeRef) {
|
||||
this.targetTypeAndInfo = typeRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* #CONSTRUCTOR_REFERENCE}, or {@link #METHOD_REFERENCE}.
|
||||
* @return a type reference of the given sort.
|
||||
*/
|
||||
public static TypeReference newTypeReference(final int sort) {
|
||||
return new TypeReference(sort << 24);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to a type parameter of a generic class or method.
|
||||
*
|
||||
* @param sort one of {@link #CLASS_TYPE_PARAMETER} or {@link #METHOD_TYPE_PARAMETER}.
|
||||
* @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) {
|
||||
return new TypeReference((sort << 24) | (paramIndex << 16));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to a type parameter bound of a generic class or method.
|
||||
*
|
||||
* @param sort one of {@link #CLASS_TYPE_PARAMETER} or {@link #METHOD_TYPE_PARAMETER}.
|
||||
* @param paramIndex the type parameter index.
|
||||
* @param boundIndex the type bound index within the above type parameters.
|
||||
* @return a reference to the given generic class or method type parameter bound.
|
||||
*/
|
||||
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 the super class or to an interface of the 'implements' clause of a
|
||||
* class.
|
||||
*
|
||||
* @param itfIndex the index of an interface in the 'implements' clause of a class, or -1 to
|
||||
* reference the super class of the class.
|
||||
* @return a reference to the given super type of a class.
|
||||
*/
|
||||
public static TypeReference newSuperTypeReference(final int itfIndex) {
|
||||
return new TypeReference((CLASS_EXTENDS << 24) | ((itfIndex & 0xFFFF) << 8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the type of a formal parameter of a method.
|
||||
*
|
||||
* @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) {
|
||||
return new TypeReference((METHOD_FORMAL_PARAMETER << 24) | (paramIndex << 16));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the type of an exception, in a 'throws' clause of a method.
|
||||
*
|
||||
* @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 newExceptionReference(final int exceptionIndex) {
|
||||
return new TypeReference((THROWS << 24) | (exceptionIndex << 8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the type of the exception declared in a 'catch' clause of a method.
|
||||
*
|
||||
* @param tryCatchBlockIndex the index of a try catch block (using the order in which they are
|
||||
* visited with visitTryCatchBlock).
|
||||
* @return a reference to the type of the given exception.
|
||||
*/
|
||||
public static TypeReference newTryCatchReference(final int tryCatchBlockIndex) {
|
||||
return new TypeReference((EXCEPTION_PARAMETER << 24) | (tryCatchBlockIndex << 8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to the type of a type argument in a constructor or method call or
|
||||
* reference.
|
||||
*
|
||||
* @param sort one of {@link #CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link
|
||||
* #METHOD_INVOCATION_TYPE_ARGUMENT}, {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link
|
||||
* #METHOD_REFERENCE_TYPE_ARGUMENT}.
|
||||
* @param argIndex the type argument index.
|
||||
* @return a reference to the type of the given type argument.
|
||||
*/
|
||||
public static TypeReference newTypeArgumentReference(final int sort, final int argIndex) {
|
||||
return new TypeReference((sort << 24) | argIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sort of this type reference.
|
||||
*
|
||||
* @return one of {@link #CLASS_TYPE_PARAMETER}, {@link #METHOD_TYPE_PARAMETER}, {@link
|
||||
* #CLASS_EXTENDS}, {@link #CLASS_TYPE_PARAMETER_BOUND}, {@link #METHOD_TYPE_PARAMETER_BOUND},
|
||||
* {@link #FIELD}, {@link #METHOD_RETURN}, {@link #METHOD_RECEIVER}, {@link
|
||||
* #METHOD_FORMAL_PARAMETER}, {@link #THROWS}, {@link #LOCAL_VARIABLE}, {@link
|
||||
* #RESOURCE_VARIABLE}, {@link #EXCEPTION_PARAMETER}, {@link #INSTANCEOF}, {@link #NEW},
|
||||
* {@link #CONSTRUCTOR_REFERENCE}, {@link #METHOD_REFERENCE}, {@link #CAST}, {@link
|
||||
* #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link #METHOD_INVOCATION_TYPE_ARGUMENT}, {@link
|
||||
* #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link #METHOD_REFERENCE_TYPE_ARGUMENT}.
|
||||
*/
|
||||
public int getSort() {
|
||||
return targetTypeAndInfo >>> 24;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}, {@link
|
||||
* #METHOD_TYPE_PARAMETER}, {@link #CLASS_TYPE_PARAMETER_BOUND} or {@link
|
||||
* #METHOD_TYPE_PARAMETER_BOUND}.
|
||||
*
|
||||
* @return a type parameter index.
|
||||
*/
|
||||
public int getTypeParameterIndex() {
|
||||
return (targetTypeAndInfo & 0x00FF0000) >> 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the type parameter bound, within the type parameter {@link
|
||||
* #getTypeParameterIndex}, referenced by this type reference. This method must only be used for
|
||||
* type references whose sort is {@link #CLASS_TYPE_PARAMETER_BOUND} or {@link
|
||||
* #METHOD_TYPE_PARAMETER_BOUND}.
|
||||
*
|
||||
* @return a type parameter bound index.
|
||||
*/
|
||||
public int getTypeParameterBoundIndex() {
|
||||
return (targetTypeAndInfo & 0x0000FF00) >> 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the "super type" of a class that is referenced by this type reference.
|
||||
* This method must only be used for type references whose sort is {@link #CLASS_EXTENDS}.
|
||||
*
|
||||
* @return the index of an interface in the 'implements' clause of a class, or -1 if this type
|
||||
* reference references the type of the super class.
|
||||
*/
|
||||
public int getSuperTypeIndex() {
|
||||
return (short) ((targetTypeAndInfo & 0x00FFFF00) >> 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the formal parameter whose type is referenced by this type reference. This
|
||||
* method must only be used for type references whose sort is {@link #METHOD_FORMAL_PARAMETER}.
|
||||
*
|
||||
* @return a formal parameter index.
|
||||
*/
|
||||
public int getFormalParameterIndex() {
|
||||
return (targetTypeAndInfo & 0x00FF0000) >> 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the exception, in a 'throws' clause of a method, whose type is referenced
|
||||
* by this type reference. This method must only be used for type references whose sort is {@link
|
||||
* #THROWS}.
|
||||
*
|
||||
* @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 try catch block (using the order in which they are visited with
|
||||
* visitTryCatchBlock), whose 'catch' type is referenced by this type reference. This method must
|
||||
* only be used for type references whose sort is {@link #EXCEPTION_PARAMETER} .
|
||||
*
|
||||
* @return the index of an exception in the 'throws' clause of a method.
|
||||
*/
|
||||
public int getTryCatchBlockIndex() {
|
||||
return (targetTypeAndInfo & 0x00FFFF00) >> 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}, {@link
|
||||
* #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT}, {@link #METHOD_INVOCATION_TYPE_ARGUMENT}, {@link
|
||||
* #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or {@link #METHOD_REFERENCE_TYPE_ARGUMENT}.
|
||||
*
|
||||
* @return a type parameter index.
|
||||
*/
|
||||
public int getTypeArgumentIndex() {
|
||||
return targetTypeAndInfo & 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 targetTypeAndInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @param output where the type reference must be put.
|
||||
*/
|
||||
static void putTarget(final int targetTypeAndInfo, final ByteVector output) {
|
||||
switch (targetTypeAndInfo >>> 24) {
|
||||
case CLASS_TYPE_PARAMETER:
|
||||
case METHOD_TYPE_PARAMETER:
|
||||
case METHOD_FORMAL_PARAMETER:
|
||||
output.putShort(targetTypeAndInfo >>> 16);
|
||||
break;
|
||||
case FIELD:
|
||||
case METHOD_RETURN:
|
||||
case METHOD_RECEIVER:
|
||||
output.putByte(targetTypeAndInfo >>> 24);
|
||||
break;
|
||||
case CAST:
|
||||
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
|
||||
case METHOD_INVOCATION_TYPE_ARGUMENT:
|
||||
case CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT:
|
||||
case METHOD_REFERENCE_TYPE_ARGUMENT:
|
||||
output.putInt(targetTypeAndInfo);
|
||||
break;
|
||||
case CLASS_EXTENDS:
|
||||
case CLASS_TYPE_PARAMETER_BOUND:
|
||||
case METHOD_TYPE_PARAMETER_BOUND:
|
||||
case THROWS:
|
||||
case EXCEPTION_PARAMETER:
|
||||
case INSTANCEOF:
|
||||
case NEW:
|
||||
case CONSTRUCTOR_REFERENCE:
|
||||
case METHOD_REFERENCE:
|
||||
output.put12(targetTypeAndInfo >>> 24, (targetTypeAndInfo & 0xFFFF00) >> 8);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* 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).
|
||||
*
|
||||
* <p>This repackaging technique avoids any potential conflicts with
|
||||
|
|
|
|||
Loading…
Reference in New Issue