Alternative name for the factory method of proxy classes created by the Proxy method.
Alternative name for the factory method of proxy classes created by the Proxy method. This name is only used if the proxified method's name is equal to DefaultFactoryMethodName.
This is the default name for the factory method of a proxy class that is created by the Proxy method.
This is the default name for the factory method of a proxy class that is created by the Proxy method. If the name of the method to be proxified is equal to this name, AlternativeFactoryMethodName is used instead.
Creates a class that acts as a proxy for the specified class.
Creates a class that acts as a proxy for the specified class.
The proxy implements a single method – e.g., as defined by a so-called
"Functional Interface" - that calls the specified method;
creating a proxy for java.lang.Object's methods is not supported. Additionally,
further marker interfaces (e.g., java.io.Serializable) may be implemented.
The generated class uses the following template:
class <definingType.objectType> extends <definingType.theSuperclassType> implements <definingType.theSuperinterfaceTypes> { private final <ReceiverType> receiver; // possible additional fields for static parameters public "" ( <ReceiverType> receiver) { // the constructor this.receiver = receiver; } public <methodDescriptor.returnType> <methodName> <methodDescriptor.parameterTypes>{ return/*<= if the return type is not void*/ this.receiver.<receiverMethodName>(<parameters>) } // possibly a bridge method }
The class, the constructor and the method are public. The field which holds the receiver object is private and final unless the receiver method is static. In this case no receiver field is generated and the constructor does not take an argument of the receiver's type.
In addition to the receiver field, additional fields holding static parameters
are created if all parameters found in methodDescriptor are present, in the same
order, at the end of receiverMethodDescriptor's parameters, but
receiverMethodDescriptor has more parameters that precede the parameters found in
methodDescriptor.
E.g., given the following two descriptors:
val methodDescriptor = MethodDescriptor(IntegerType, IntegerType) val receiverMethodDescriptor = MethodDescriptor(IndexedSeq(DoubleType, IntegerType), IntegerType)
one additional field and constructor parameter of type double will be created.
This case occurs for example with Java 8 lambda expressions that capture local
variables, which are prepended to the regular parameter list.
If any of the parameters or the return type of methodDescriptor are
generic types, the generated proxy will need to create a bridge method to be valid.
Therefore, in these cases, bridgeMethodDescriptor must be specified.
It must be identical to methodDescriptor except for all occurrences of generic
types, which must be replaced with ObjectType.Object.
For example, consider the Java interface java.util.Comparator that defines the
generic type T and uses it in its int compare(T, T) method. This would require
a bridge method int compare(Object, Object). The appropriate method descriptors
for, for example, Comparator<String> would be:
// Uses "String" methodDescriptor = MethodDescriptor(IndexedSeq(ObjectType.String, ObjectType.String), IntegerType) // Uses "Object" bridgeMethodDescriptor = MethodDescriptor(IndexedSeq(ObjectType.Object, ObjectType.Object), IntegerType)
The created class will always have its synthetic access flag set, as well as the VirtualTypeFlag attribute.
the opcode of the invocation instruction
(INVOKESPECIAL.opcode,INVOKEVIRTUAL.opcode,
INVOKESTATIC.opcode,INVOKEINTERFACE.opcode)
used to call call the method on the receiver.
It is expected that methodDescriptor and receiverMethodDescriptor are
"compatible", i.e. it would be possible to have the method described by
methodDescriptor forward to receiverMethodDescriptor.
This requires that for their return types, one of the following statements holds true:
- methodDescriptor's return type is VoidType (so no returning is necessary)
- receiverMethodDescriptor's return type is assignable to methodDescriptor's
(e.g. a "smaller" numerical type, (un)boxable, a subtype, etc)
- receiverMethodDescriptor returns Object: in this case, we assume that Object
stands for "generic return type" and expect the receiver method to return an
object of a type compatible to the forwarder method's return type
Additionally, the parameter lists must satisfy one of these conditions:
- they are identical
- the descriptors have the same numbers of parameters and methodDescriptor's
parameter types can be widened/boxed/unboxed to match receiverMethodDescriptor's
parameter types
- methodDescriptor's first parameter is of the same type as receiverType,
and the remaining parameters are compatible to receiverMethodDescriptor's
entire parameter list (this is, effectively, an explicit this and occurs for
example with references to instance methods: e.g. String::isEmpty, a zero
argument method, could be turned into the Predicate method test(String))
- the last n parameters of receiverMethodDescriptor are identical to the
parameters of methodDescriptor, where n = methodDescriptor.parametersCount
(this is the case if a lambda expression captures local variables)
- receiverMethodDescriptor's single parameter is of type Object[] (in this case,
methodDescriptor's arguments will be collected into an Object[] prior to
forwarding)
Examples of compatible method descriptors are:
// ------------- First Example methodDescriptor = MethodDescriptor(IntegerType, VoidType) receiverMethodDescriptor = MethodDescriptor(ObjectType.Integer, VoidType) // or MethodDescriptor(ObjectType.Object, ByteType) // ------------- Second Example methodDescriptor = MethodDescriptor(ObjectType.String, BooleanType) receiverMethodDescriptor = MethodDescriptor.JustReturnsBoolean // IF receiverType == ObjectType.String // ------------- Third Example methodDescriptor = MethodDescriptor(IndexedSeq(ByteType, ByteType, ObjectType.Integer), IntegerType) receiverMethodDescriptor = MethodDescriptor(ArrayType.ArrayOfObject, ObjectType.Object) // generic method // ------------- Fourth Example methodDescriptor = MethodDescriptor(IntegerType, LongType) receiverMethodDescriptor = MethodDescriptor(IndexedSeq(ByteType, ByteType, IntegerType), IntegerType),
The used class file version is 49.0 (Java 5) (Using this version, we are not required to create the stack map table attribute to create a valid class file.)
Name used to store the final receiver object in generated proxy classes.
Returns the instructions necessary to perform a call to the constructor of the given superclass.
Creates an array of instructions that populates the given fields in declaringType
from local variables (constructor parameters).
Creates an array of instructions that populates the given fields in declaringType
from local variables (constructor parameters).
This method assumes that it creates instructions for a constructor whose parameter
list matches the given fields in terms of order and field types.
It further assumes that none of the fields provided as arguments are
static fields, as it would make little sense to initialize static fields through
the constructor.
Creates a bridge method using the given method descriptors, name, and type.
Creates a bridge method using the given method descriptors, name, and type.
The bridge method's parameter list and return type are dictated by
bridgeMethodDescriptor.
This method generates bytecode that invokes the method described by methodName
and targetMethodDescriptor on declaringType. If parameters need to be cast
before invocation, the appropriate bytecode will be generated as well.
Creates a public constructor that initializes the given fields.
Creates a public constructor that initializes the given fields.
For every Field in fields the constructor will have one parameter of the same
type. The parameter list will have the same order as fields.
The generated constructor will call the superclass' default constructor; i.e.,
the type definingType.theSuperclassType has to have a default constructor.
Additionally, bytecode is generated to populate the fields from the constructor
arguments.
Creates a factory method with the appropriate instructions to create and
return an instance of typeToCreate.
Creates a factory method with the appropriate instructions to create and
return an instance of typeToCreate.
typeToCreate must have a constructor with a parameter list that exactly matches
fieldTypes. It also must not define a method named factoryMethodName with a
parameter list matching fieldTypes.
Creates a field of the specified type with the given name.
Returns true if the method invocation described by the given Opcode and method name is a "NewInvokeSpecial" invocation (i.e.
Returns true if the method invocation described by the given Opcode and method name
is a "NewInvokeSpecial" invocation (i.e. a reference to a constructor, like so:
Object::new).
Returns true if the given parameters identify a Java 8 method reference to an instance or interface method (i.e.
Returns true if the given parameters identify a Java 8 method reference to an
instance or interface method (i.e. a reference to a virtual method, like so:
ArrayList::size or List::size). In this case, the resulting functional interface's method
has one parameter more than the referenced method because the referenced method's
implicit this parameter becomes explicit.
Generates an array of instructions that fill the operand stack with all parameters
required by receiverMethodDescriptor from the parameters of
calledMethodDescriptor.
Generates an array of instructions that fill the operand stack with all parameters
required by receiverMethodDescriptor from the parameters of
calledMethodDescriptor. For that reason, it is expected that both method
descriptors have compatible parameter and return types: i.e., that
forwarderMethodDescriptor's parameters can be widened or (un)boxed to fit into
receiverMethodDescriptor's parameters, and that receiverMethodDescriptor's return
type can be widened or (un)boxed to fit into forwarderMethodDescriptor's return type.
If receiverMethodDescriptor has more parameters than forwarderMethodDescriptor,
the missing parameters must be provided in staticParameters.
Creates a proxy method with name methodName and descriptor methodDescriptor and
the bytecode instructions to execute the method receiverMethod in receiverType.
Creates a proxy method with name methodName and descriptor methodDescriptor and
the bytecode instructions to execute the method receiverMethod in receiverType.
If the methodDescriptors have to be identical in terms of parameter types and return type.
Returns the instructions that return a value of type typeToBeReturned, converting
typeOnStack to it first if necessary.
Returns the instructions that return a value of type typeToBeReturned, converting
typeOnStack to it first if necessary.
If typeOnStack is Object, it will be treated as a generic return type and
converted to the required type.
Provides helper methods to facilitate the generation of classes. In particular, functionality to create transparent proxy classes is provided.