/*
 * Copyright 2014 - 2019 Rafael Winterhalter
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.bytebuddy.utility;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import net.bytebuddy.build.HashCodeAndEqualsPlugin;
import net.bytebuddy.description.enumeration.EnumerationDescription;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.description.type.TypeList;
import org.objectweb.asm.ConstantDynamic;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;

Returns a Java instance of an object that has a special meaning to the Java virtual machine and that is not available to Java in versions 6.
/** * Returns a Java instance of an object that has a special meaning to the Java virtual machine and that is not * available to Java in versions 6. */
public interface JavaConstant {
Returns the represented instance as a constant pool value.
Returns:The constant pool value in a format that can be written by ASM.
/** * Returns the represented instance as a constant pool value. * * @return The constant pool value in a format that can be written by ASM. */
Object asConstantPoolValue();
Returns a description of the type of the represented instance or at least a stub.
Returns:A description of the type of the represented instance or at least a stub.
/** * Returns a description of the type of the represented instance or at least a stub. * * @return A description of the type of the represented instance or at least a stub. */
TypeDescription getType();
Represents a java.lang.invoke.MethodType object.
/** * Represents a {@code java.lang.invoke.MethodType} object. */
class MethodType implements JavaConstant {
A dispatcher for extracting information from a java.lang.invoke.MethodType instance.
/** * A dispatcher for extracting information from a {@code java.lang.invoke.MethodType} instance. */
private static final Dispatcher DISPATCHER = AccessController.doPrivileged(Dispatcher.CreationAction.INSTANCE);
The return type of this method type.
/** * The return type of this method type. */
private final TypeDescription returnType;
The parameter types of this method type.
/** * The parameter types of this method type. */
private final List<? extends TypeDescription> parameterTypes;
Creates a method type for the given types.
Params:
  • returnType – The return type of the method type.
  • parameterTypes – The parameter types of the method type.
/** * Creates a method type for the given types. * * @param returnType The return type of the method type. * @param parameterTypes The parameter types of the method type. */
protected MethodType(TypeDescription returnType, List<? extends TypeDescription> parameterTypes) { this.returnType = returnType; this.parameterTypes = parameterTypes; }
Returns a method type representation of a loaded MethodType object.
Params:
  • methodType – A method type object to represent as a JavaConstant.
Returns:The method type represented as a MethodType.
/** * Returns a method type representation of a loaded {@code MethodType} object. * * @param methodType A method type object to represent as a {@link JavaConstant}. * @return The method type represented as a {@link MethodType}. */
public static MethodType ofLoaded(Object methodType) { if (!JavaType.METHOD_TYPE.isInstance(methodType)) { throw new IllegalArgumentException("Expected method type object: " + methodType); } return of(DISPATCHER.returnType(methodType), DISPATCHER.parameterArray(methodType)); }
Returns a method type description of the given return type and parameter types.
Params:
  • returnType – The return type to represent.
  • parameterType – The parameter types to represent.
Returns:A method type of the given return type and parameter types.
/** * Returns a method type description of the given return type and parameter types. * * @param returnType The return type to represent. * @param parameterType The parameter types to represent. * @return A method type of the given return type and parameter types. */
public static MethodType of(Class<?> returnType, Class<?>... parameterType) { return of(TypeDescription.ForLoadedType.of(returnType), new TypeList.ForLoadedTypes(parameterType)); }
Returns a method type description of the given return type and parameter types.
Params:
  • returnType – The return type to represent.
  • parameterTypes – The parameter types to represent.
Returns:A method type of the given return type and parameter types.
/** * Returns a method type description of the given return type and parameter types. * * @param returnType The return type to represent. * @param parameterTypes The parameter types to represent. * @return A method type of the given return type and parameter types. */
public static MethodType of(TypeDescription returnType, List<? extends TypeDescription> parameterTypes) { return new MethodType(returnType, parameterTypes); }
Returns a method type description of the given method.
Params:
  • method – The method to extract the method type from.
Returns:The method type of the given method.
/** * Returns a method type description of the given method. * * @param method The method to extract the method type from. * @return The method type of the given method. */
public static MethodType of(Method method) { return of(new MethodDescription.ForLoadedMethod(method)); }
Returns a method type description of the given constructor.
Params:
  • constructor – The constructor to extract the method type from.
Returns:The method type of the given constructor.
/** * Returns a method type description of the given constructor. * * @param constructor The constructor to extract the method type from. * @return The method type of the given constructor. */
public static MethodType of(Constructor<?> constructor) { return of(new MethodDescription.ForLoadedConstructor(constructor)); }
Returns a method type description of the given method.
Params:
  • methodDescription – The method to extract the method type from.
Returns:The method type of the given method.
/** * Returns a method type description of the given method. * * @param methodDescription The method to extract the method type from. * @return The method type of the given method. */
public static MethodType of(MethodDescription methodDescription) { return new MethodType(methodDescription.getReturnType().asErasure(), methodDescription.getParameters().asTypeList().asErasures()); }
Returns a method type for a setter of the given field.
Params:
  • field – The field to extract a setter type for.
Returns:The type of a setter for the given field.
/** * Returns a method type for a setter of the given field. * * @param field The field to extract a setter type for. * @return The type of a setter for the given field. */
public static MethodType ofSetter(Field field) { return ofSetter(new FieldDescription.ForLoadedField(field)); }
Returns a method type for a setter of the given field.
Params:
  • fieldDescription – The field to extract a setter type for.
Returns:The type of a setter for the given field.
/** * Returns a method type for a setter of the given field. * * @param fieldDescription The field to extract a setter type for. * @return The type of a setter for the given field. */
public static MethodType ofSetter(FieldDescription fieldDescription) { return new MethodType(TypeDescription.VOID, Collections.singletonList(fieldDescription.getType().asErasure())); }
Returns a method type for a getter of the given field.
Params:
  • field – The field to extract a getter type for.
Returns:The type of a getter for the given field.
/** * Returns a method type for a getter of the given field. * * @param field The field to extract a getter type for. * @return The type of a getter for the given field. */
public static MethodType ofGetter(Field field) { return ofGetter(new FieldDescription.ForLoadedField(field)); }
Returns a method type for a getter of the given field.
Params:
  • fieldDescription – The field to extract a getter type for.
Returns:The type of a getter for the given field.
/** * Returns a method type for a getter of the given field. * * @param fieldDescription The field to extract a getter type for. * @return The type of a getter for the given field. */
public static MethodType ofGetter(FieldDescription fieldDescription) { return new MethodType(fieldDescription.getType().asErasure(), Collections.<TypeDescription>emptyList()); }
Returns a method type for the given constant.
Params:
  • instance – The constant for which a constant method type should be created.
Returns:A method type for the given constant.
/** * Returns a method type for the given constant. * * @param instance The constant for which a constant method type should be created. * @return A method type for the given constant. */
public static MethodType ofConstant(Object instance) { return ofConstant(instance.getClass()); }
Returns a method type for the given constant type.
Params:
  • type – The constant type for which a constant method type should be created.
Returns:A method type for the given constant type.
/** * Returns a method type for the given constant type. * * @param type The constant type for which a constant method type should be created. * @return A method type for the given constant type. */
public static MethodType ofConstant(Class<?> type) { return ofConstant(TypeDescription.ForLoadedType.of(type)); }
Returns a method type for the given constant type.
Params:
  • typeDescription – The constant type for which a constant method type should be created.
Returns:A method type for the given constant type.
/** * Returns a method type for the given constant type. * * @param typeDescription The constant type for which a constant method type should be created. * @return A method type for the given constant type. */
public static MethodType ofConstant(TypeDescription typeDescription) { return new MethodType(typeDescription, Collections.<TypeDescription>emptyList()); }
Returns the return type of this method type.
Returns:The return type of this method type.
/** * Returns the return type of this method type. * * @return The return type of this method type. */
public TypeDescription getReturnType() { return returnType; }
Returns the parameter types of this method type.
Returns:The parameter types of this method type.
/** * Returns the parameter types of this method type. * * @return The parameter types of this method type. */
public TypeList getParameterTypes() { return new TypeList.Explicit(parameterTypes); }
Returns the method descriptor of this method type representation.
Returns:The method descriptor of this method type representation.
/** * Returns the method descriptor of this method type representation. * * @return The method descriptor of this method type representation. */
public String getDescriptor() { StringBuilder stringBuilder = new StringBuilder("("); for (TypeDescription parameterType : parameterTypes) { stringBuilder.append(parameterType.getDescriptor()); } return stringBuilder.append(')').append(returnType.getDescriptor()).toString(); }
{@inheritDoc}
/** * {@inheritDoc} */
public Object asConstantPoolValue() { StringBuilder stringBuilder = new StringBuilder().append('('); for (TypeDescription parameterType : getParameterTypes()) { stringBuilder.append(parameterType.getDescriptor()); } return Type.getMethodType(stringBuilder.append(')').append(getReturnType().getDescriptor()).toString()); }
{@inheritDoc}
/** * {@inheritDoc} */
public TypeDescription getType() { return JavaType.METHOD_TYPE.getTypeStub(); } @Override public int hashCode() { int result = returnType.hashCode(); result = 31 * result + parameterTypes.hashCode(); return result; } @Override public boolean equals(Object other) { if (this == other) { return true; } if (!(other instanceof MethodType)) { return false; } MethodType methodType = (MethodType) other; return parameterTypes.equals(methodType.parameterTypes) && returnType.equals(methodType.returnType); }
A dispatcher for extracting information from a java.lang.invoke.MethodType instance.
/** * A dispatcher for extracting information from a {@code java.lang.invoke.MethodType} instance. */
protected interface Dispatcher {
Extracts the return type of the supplied method type.
Params:
  • methodType – An instance of java.lang.invoke.MethodType.
Returns:The return type that is described by the supplied instance.
/** * Extracts the return type of the supplied method type. * * @param methodType An instance of {@code java.lang.invoke.MethodType}. * @return The return type that is described by the supplied instance. */
Class<?> returnType(Object methodType);
Extracts the parameter types of the supplied method type.
Params:
  • methodType – An instance of java.lang.invoke.MethodType.
Returns:The parameter types that are described by the supplied instance.
/** * Extracts the parameter types of the supplied method type. * * @param methodType An instance of {@code java.lang.invoke.MethodType}. * @return The parameter types that are described by the supplied instance. */
Class<?>[] parameterArray(Object methodType);
A creation action for a dispatcher.
/** * A creation action for a dispatcher. */
enum CreationAction implements PrivilegedAction<Dispatcher> {
The singleton instance.
/** * The singleton instance. */
INSTANCE;
{@inheritDoc}
/** * {@inheritDoc} */
@SuppressFBWarnings(value = "REC_CATCH_EXCEPTION", justification = "Exception should not be rethrown but trigger a fallback") public Dispatcher run() { try { Class<?> methodType = JavaType.METHOD_TYPE.load(); return new Dispatcher.ForJava7CapableVm(methodType.getMethod("returnType"), methodType.getMethod("parameterArray")); } catch (Exception ignored) { return Dispatcher.ForLegacyVm.INSTANCE; } } }
A dispatcher for virtual machines that are aware of the java.lang.invoke.MethodType type that was added in Java version 7.
/** * A dispatcher for virtual machines that are aware of the {@code java.lang.invoke.MethodType} type that was added in Java version 7. */
@HashCodeAndEqualsPlugin.Enhance class ForJava7CapableVm implements Dispatcher {
An empty array that can be used to indicate no arguments to avoid an allocation on a reflective call.
/** * An empty array that can be used to indicate no arguments to avoid an allocation on a reflective call. */
private static final Object[] NO_ARGUMENTS = new Object[0];
A reference to java.lang.invoke.MethodType#returnType.
/** * A reference to {@code java.lang.invoke.MethodType#returnType}. */
private final Method returnType;
A reference to java.lang.invoke.MethodType#returnType.
/** * A reference to {@code java.lang.invoke.MethodType#returnType}. */
private final Method parameterArray;
Creates a new dispatcher for a modern JVM.
Params:
  • returnType – A reference to java.lang.invoke.MethodType#returnType.
  • parameterArray – A reference to java.lang.invoke.MethodType#returnType.
/** * Creates a new dispatcher for a modern JVM. * * @param returnType A reference to {@code java.lang.invoke.MethodType#returnType}. * @param parameterArray A reference to {@code java.lang.invoke.MethodType#returnType}. */
protected ForJava7CapableVm(Method returnType, Method parameterArray) { this.returnType = returnType; this.parameterArray = parameterArray; }
{@inheritDoc}
/** * {@inheritDoc} */
public Class<?> returnType(Object methodType) { try { return (Class<?>) returnType.invoke(methodType, NO_ARGUMENTS); } catch (IllegalAccessException exception) { throw new IllegalStateException("Cannot access java.lang.invoke.MethodType#returnType", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.invoke.MethodType#returnType", exception.getCause()); } }
{@inheritDoc}
/** * {@inheritDoc} */
public Class<?>[] parameterArray(Object methodType) { try { return (Class<?>[]) parameterArray.invoke(methodType, NO_ARGUMENTS); } catch (IllegalAccessException exception) { throw new IllegalStateException("Cannot access java.lang.invoke.MethodType#parameterArray", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.invoke.MethodType#parameterArray", exception.getCause()); } } }
A dispatcher for virtual machines that are not aware of the java.lang.invoke.MethodType type that was added in Java version 7.
/** * A dispatcher for virtual machines that are <b>not</b> aware of the {@code java.lang.invoke.MethodType} type that was added in Java version 7. */
enum ForLegacyVm implements Dispatcher {
The singleton instance.
/** * The singleton instance. */
INSTANCE;
{@inheritDoc}
/** * {@inheritDoc} */
public Class<?> returnType(Object methodType) { throw new UnsupportedOperationException("Unsupported type for the current JVM: java.lang.invoke.MethodType"); }
{@inheritDoc}
/** * {@inheritDoc} */
public Class<?>[] parameterArray(Object methodType) { throw new UnsupportedOperationException("Unsupported type for the current JVM: java.lang.invoke.MethodType"); } } } }
Represents a java.lang.invoke.MethodHandle object. Note that constant MethodHandles cannot be represented within the constant pool of a Java class and can therefore not be represented as an instance of this representation order.
/** * Represents a {@code java.lang.invoke.MethodHandle} object. Note that constant {@code MethodHandle}s cannot * be represented within the constant pool of a Java class and can therefore not be represented as an instance of * this representation order. */
class MethodHandle implements JavaConstant {
A dispatcher for receiving the type information that is represented by a java.lang.invoke.MethodHandle instance.
/** * A dispatcher for receiving the type information that is represented by a {@code java.lang.invoke.MethodHandle} instance. */
private static final Dispatcher.Initializable DISPATCHER = AccessController.doPrivileged(Dispatcher.CreationAction.INSTANCE);
The handle type that is represented by this instance.
/** * The handle type that is represented by this instance. */
private final HandleType handleType;
The owner type that is represented by this instance.
/** * The owner type that is represented by this instance. */
private final TypeDescription ownerType;
The name that is represented by this instance.
/** * The name that is represented by this instance. */
private final String name;
The return type that is represented by this instance.
/** * The return type that is represented by this instance. */
private final TypeDescription returnType;
The parameter types that is represented by this instance.
/** * The parameter types that is represented by this instance. */
private final List<? extends TypeDescription> parameterTypes;
Creates a method handle representation.
Params:
  • handleType – The handle type that is represented by this instance.
  • ownerType – The owner type that is represented by this instance.
  • name – The name that is represented by this instance.
  • returnType – The return type that is represented by this instance.
  • parameterTypes – The parameter types that is represented by this instance.
/** * Creates a method handle representation. * * @param handleType The handle type that is represented by this instance. * @param ownerType The owner type that is represented by this instance. * @param name The name that is represented by this instance. * @param returnType The return type that is represented by this instance. * @param parameterTypes The parameter types that is represented by this instance. */
protected MethodHandle(HandleType handleType, TypeDescription ownerType, String name, TypeDescription returnType, List<? extends TypeDescription> parameterTypes) { this.handleType = handleType; this.ownerType = ownerType; this.name = name; this.returnType = returnType; this.parameterTypes = parameterTypes; }
Creates a method handles representation of a loaded method handle which is analyzed using a public MethodHandles.Lookup object. A method handle can only be analyzed on virtual machines that support the corresponding API (Java 7+). For virtual machines before Java 8+, a method handle instance can only be analyzed by taking advantage of private APIs what might require a access context.
Params:
  • methodHandle – The loaded method handle to represent.
Returns:A representation of the loaded method handle
/** * Creates a method handles representation of a loaded method handle which is analyzed using a public {@code MethodHandles.Lookup} object. * A method handle can only be analyzed on virtual machines that support the corresponding API (Java 7+). For virtual machines before Java 8+, * a method handle instance can only be analyzed by taking advantage of private APIs what might require a access context. * * @param methodHandle The loaded method handle to represent. * @return A representation of the loaded method handle */
public static MethodHandle ofLoaded(Object methodHandle) { return ofLoaded(methodHandle, DISPATCHER.publicLookup()); }
Creates a method handles representation of a loaded method handle which is analyzed using the given lookup context. A method handle can only be analyzed on virtual machines that support the corresponding API (Java 7+). For virtual machines before Java 8+, a method handle instance can only be analyzed by taking advantage of private APIs what might require a access context.
Params:
  • methodHandle – The loaded method handle to represent.
  • lookup – The lookup object to use for analyzing the method handle.
Returns:A representation of the loaded method handle
/** * Creates a method handles representation of a loaded method handle which is analyzed using the given lookup context. * A method handle can only be analyzed on virtual machines that support the corresponding API (Java 7+). For virtual machines before Java 8+, * a method handle instance can only be analyzed by taking advantage of private APIs what might require a access context. * * @param methodHandle The loaded method handle to represent. * @param lookup The lookup object to use for analyzing the method handle. * @return A representation of the loaded method handle */
public static MethodHandle ofLoaded(Object methodHandle, Object lookup) { if (!JavaType.METHOD_HANDLE.isInstance(methodHandle)) { throw new IllegalArgumentException("Expected method handle object: " + methodHandle); } else if (!JavaType.METHOD_HANDLES_LOOKUP.isInstance(lookup)) { throw new IllegalArgumentException("Expected method handle lookup object: " + lookup); } Dispatcher dispatcher = DISPATCHER.initialize(); Object methodHandleInfo = dispatcher.reveal(lookup, methodHandle); Object methodType = dispatcher.getMethodType(methodHandleInfo); return new MethodHandle(HandleType.of(dispatcher.getReferenceKind(methodHandleInfo)), TypeDescription.ForLoadedType.of(dispatcher.getDeclaringClass(methodHandleInfo)), dispatcher.getName(methodHandleInfo), TypeDescription.ForLoadedType.of(dispatcher.returnType(methodType)), new TypeList.ForLoadedTypes(dispatcher.parameterArray(methodType))); }
Creates a method handle representation of the given method.
Params:
  • method – The method ro represent.
Returns:A method handle representing the given method.
/** * Creates a method handle representation of the given method. * * @param method The method ro represent. * @return A method handle representing the given method. */
public static MethodHandle of(Method method) { return of(new MethodDescription.ForLoadedMethod(method)); }
Creates a method handle representation of the given constructor.
Params:
  • constructor – The constructor ro represent.
Returns:A method handle representing the given constructor.
/** * Creates a method handle representation of the given constructor. * * @param constructor The constructor ro represent. * @return A method handle representing the given constructor. */
public static MethodHandle of(Constructor<?> constructor) { return of(new MethodDescription.ForLoadedConstructor(constructor)); }
Creates a method handle representation of the given method.
Params:
  • methodDescription – The method ro represent.
Returns:A method handle representing the given method.
/** * Creates a method handle representation of the given method. * * @param methodDescription The method ro represent. * @return A method handle representing the given method. */
public static MethodHandle of(MethodDescription.InDefinedShape methodDescription) { return new MethodHandle(HandleType.of(methodDescription), methodDescription.getDeclaringType().asErasure(), methodDescription.getInternalName(), methodDescription.getReturnType().asErasure(), methodDescription.getParameters().asTypeList().asErasures()); }
Creates a method handle representation of the given method for an explicit special method invocation of an otherwise virtual method.
Params:
  • method – The method ro represent.
  • type – The type on which the method is to be invoked on as a special method invocation.
Returns:A method handle representing the given method as special method invocation.
/** * Creates a method handle representation of the given method for an explicit special method invocation of an otherwise virtual method. * * @param method The method ro represent. * @param type The type on which the method is to be invoked on as a special method invocation. * @return A method handle representing the given method as special method invocation. */
public static MethodHandle ofSpecial(Method method, Class<?> type) { return ofSpecial(new MethodDescription.ForLoadedMethod(method), TypeDescription.ForLoadedType.of(type)); }
Creates a method handle representation of the given method for an explicit special method invocation of an otherwise virtual method.
Params:
  • methodDescription – The method ro represent.
  • typeDescription – The type on which the method is to be invoked on as a special method invocation.
Returns:A method handle representing the given method as special method invocation.
/** * Creates a method handle representation of the given method for an explicit special method invocation of an otherwise virtual method. * * @param methodDescription The method ro represent. * @param typeDescription The type on which the method is to be invoked on as a special method invocation. * @return A method handle representing the given method as special method invocation. */
public static MethodHandle ofSpecial(MethodDescription.InDefinedShape methodDescription, TypeDescription typeDescription) { if (!methodDescription.isSpecializableFor(typeDescription)) { throw new IllegalArgumentException("Cannot specialize " + methodDescription + " for " + typeDescription); } return new MethodHandle(HandleType.ofSpecial(methodDescription), typeDescription, methodDescription.getInternalName(), methodDescription.getReturnType().asErasure(), methodDescription.getParameters().asTypeList().asErasures()); }
Returns a method handle for a setter of the given field.
Params:
  • field – The field to represent.
Returns:A method handle for a setter of the given field.
/** * Returns a method handle for a setter of the given field. * * @param field The field to represent. * @return A method handle for a setter of the given field. */
public static MethodHandle ofGetter(Field field) { return ofGetter(new FieldDescription.ForLoadedField(field)); }
Returns a method handle for a setter of the given field.
Params:
  • fieldDescription – The field to represent.
Returns:A method handle for a setter of the given field.
/** * Returns a method handle for a setter of the given field. * * @param fieldDescription The field to represent. * @return A method handle for a setter of the given field. */
public static MethodHandle ofGetter(FieldDescription.InDefinedShape fieldDescription) { return new MethodHandle(HandleType.ofGetter(fieldDescription), fieldDescription.getDeclaringType().asErasure(), fieldDescription.getInternalName(), fieldDescription.getType().asErasure(), Collections.<TypeDescription>emptyList()); }
Returns a method handle for a getter of the given field.
Params:
  • field – The field to represent.
Returns:A method handle for a getter of the given field.
/** * Returns a method handle for a getter of the given field. * * @param field The field to represent. * @return A method handle for a getter of the given field. */
public static MethodHandle ofSetter(Field field) { return ofSetter(new FieldDescription.ForLoadedField(field)); }
Returns a method handle for a getter of the given field.
Params:
  • fieldDescription – The field to represent.
Returns:A method handle for a getter of the given field.
/** * Returns a method handle for a getter of the given field. * * @param fieldDescription The field to represent. * @return A method handle for a getter of the given field. */
public static MethodHandle ofSetter(FieldDescription.InDefinedShape fieldDescription) { return new MethodHandle(HandleType.ofSetter(fieldDescription), fieldDescription.getDeclaringType().asErasure(), fieldDescription.getInternalName(), TypeDescription.VOID, Collections.singletonList(fieldDescription.getType().asErasure())); }
{@inheritDoc}
/** * {@inheritDoc} */
public Object asConstantPoolValue() { StringBuilder stringBuilder = new StringBuilder().append('('); for (TypeDescription parameterType : getParameterTypes()) { stringBuilder.append(parameterType.getDescriptor()); } String descriptor = stringBuilder.append(')').append(getReturnType().getDescriptor()).toString(); return new Handle(getHandleType().getIdentifier(), getOwnerType().getInternalName(), getName(), descriptor, getOwnerType().isInterface()); }
{@inheritDoc}
/** * {@inheritDoc} */
public TypeDescription getType() { return JavaType.METHOD_HANDLE.getTypeStub(); }
Returns the handle type represented by this instance.
Returns:The handle type represented by this instance.
/** * Returns the handle type represented by this instance. * * @return The handle type represented by this instance. */
public HandleType getHandleType() { return handleType; }
Returns the owner type of this instance.
Returns:The owner type of this instance.
/** * Returns the owner type of this instance. * * @return The owner type of this instance. */
public TypeDescription getOwnerType() { return ownerType; }
Returns the name represented by this instance.
Returns:The name represented by this instance.
/** * Returns the name represented by this instance. * * @return The name represented by this instance. */
public String getName() { return name; }
Returns the return type represented by this instance.
Returns:The return type represented by this instance.
/** * Returns the return type represented by this instance. * * @return The return type represented by this instance. */
public TypeDescription getReturnType() { return returnType; }
Returns the parameter types represented by this instance.
Returns:The parameter types represented by this instance.
/** * Returns the parameter types represented by this instance. * * @return The parameter types represented by this instance. */
public TypeList getParameterTypes() { return new TypeList.Explicit(parameterTypes); }
Returns the method descriptor of this method handle representation.
Returns:The method descriptor of this method handle representation.
/** * Returns the method descriptor of this method handle representation. * * @return The method descriptor of this method handle representation. */
public String getDescriptor() { StringBuilder stringBuilder = new StringBuilder().append('('); for (TypeDescription parameterType : parameterTypes) { stringBuilder.append(parameterType.getDescriptor()); } return stringBuilder.append(')').append(returnType.getDescriptor()).toString(); } @Override public int hashCode() { int result = handleType.hashCode(); result = 31 * result + ownerType.hashCode(); result = 31 * result + name.hashCode(); result = 31 * result + returnType.hashCode(); result = 31 * result + parameterTypes.hashCode(); return result; } @Override public boolean equals(Object other) { if (this == other) { return true; } else if (!(other instanceof MethodHandle)) { return false; } MethodHandle methodHandle = (MethodHandle) other; return handleType == methodHandle.handleType && name.equals(methodHandle.name) && ownerType.equals(methodHandle.ownerType) && parameterTypes.equals(methodHandle.parameterTypes) && returnType.equals(methodHandle.returnType); }
Returns the lookup type of the provided java.lang.invoke.MethodHandles$Lookup instance.
Params:
  • callerClassLookup – An instance of java.lang.invoke.MethodHandles$Lookup.
Returns:The instance's lookup type.
/** * Returns the lookup type of the provided {@code java.lang.invoke.MethodHandles$Lookup} instance. * * @param callerClassLookup An instance of {@code java.lang.invoke.MethodHandles$Lookup}. * @return The instance's lookup type. */
public static Class<?> lookupType(Object callerClassLookup) { return DISPATCHER.lookupType(callerClassLookup); }
A dispatcher for analyzing a java.lang.invoke.MethodHandle instance.
/** * A dispatcher for analyzing a {@code java.lang.invoke.MethodHandle} instance. */
protected interface Dispatcher {
Reveals a method handle's information object.
Params:
  • lookup – The lookup to be used for introspecting the instance.
  • methodHandle – The method handle to be introspected.
Returns:The java.lang.invoke.MethodHandleInfo object that describes the instance.
/** * Reveals a method handle's information object. * * @param lookup The lookup to be used for introspecting the instance. * @param methodHandle The method handle to be introspected. * @return The {@code java.lang.invoke.MethodHandleInfo} object that describes the instance. */
Object reveal(Object lookup, Object methodHandle);
Returns a method handle info's method type.
Params:
  • methodHandleInfo – The method handle info to introspect.
Returns:The java.lang.invoke.MethodType instance representing the method handle's type.
/** * Returns a method handle info's method type. * * @param methodHandleInfo The method handle info to introspect. * @return The {@code java.lang.invoke.MethodType} instance representing the method handle's type. */
Object getMethodType(Object methodHandleInfo);
Returns the reference kind of the supplied method handle info.
Params:
  • methodHandleInfo – The method handle to be introspected.
Returns:The method handle info's reference type.
/** * Returns the reference kind of the supplied method handle info. * * @param methodHandleInfo The method handle to be introspected. * @return The method handle info's reference type. */
int getReferenceKind(Object methodHandleInfo);
Returns the declaring class of the supplied method handle info.
Params:
  • methodHandleInfo – The method handle to be introspected.
Returns:The method handle info's declaring class.
/** * Returns the declaring class of the supplied method handle info. * * @param methodHandleInfo The method handle to be introspected. * @return The method handle info's declaring class. */
Class<?> getDeclaringClass(Object methodHandleInfo);
Returns the method name of the supplied method handle info.
Params:
  • methodHandleInfo – The method handle to be introspected.
Returns:The method handle info's method name.
/** * Returns the method name of the supplied method handle info. * * @param methodHandleInfo The method handle to be introspected. * @return The method handle info's method name. */
String getName(Object methodHandleInfo);
Returns the return type of the supplied method type.
Params:
  • methodType – The method type to be introspected.
Returns:The method type's return type.
/** * Returns the return type of the supplied method type. * * @param methodType The method type to be introspected. * @return The method type's return type. */
Class<?> returnType(Object methodType);
Returns the parameter types of the supplied method type.
Params:
  • methodType – The method type to be introspected.
Returns:The method type's parameter types.
/** * Returns the parameter types of the supplied method type. * * @param methodType The method type to be introspected. * @return The method type's parameter types. */
List<? extends Class<?>> parameterArray(Object methodType);
An initializable version of a dispatcher that is not yet made accessible.
/** * An initializable version of a dispatcher that is not yet made accessible. */
interface Initializable {
Initializes the dispatcher, if required.
Returns:The initialized dispatcher.
/** * Initializes the dispatcher, if required. * * @return The initialized dispatcher. */
Dispatcher initialize();
Returns a public java.lang.invoke.MethodHandles.Lookup instance.
Returns:A public java.lang.invoke.MethodHandles.Lookup instance.
/** * Returns a public {@code java.lang.invoke.MethodHandles.Lookup} instance. * * @return A public {@code java.lang.invoke.MethodHandles.Lookup} instance. */
Object publicLookup();
Returns the lookup type of a given java.lang.invoke.MethodHandles$Lookup instance.
Params:
  • lookup – A java.lang.invoke.MethodHandles$Lookup instance.
Returns:The provided instance's lookup type.
/** * Returns the lookup type of a given {@code java.lang.invoke.MethodHandles$Lookup} instance. * * @param lookup A {@code java.lang.invoke.MethodHandles$Lookup} instance. * @return The provided instance's lookup type. */
Class<?> lookupType(Object lookup); }
A creation action for a dispatcher.
/** * A creation action for a dispatcher. */
enum CreationAction implements PrivilegedAction<Initializable> {
The singleton instance.
/** * The singleton instance. */
INSTANCE;
{@inheritDoc}
/** * {@inheritDoc} */
@SuppressFBWarnings(value = "REC_CATCH_EXCEPTION", justification = "Exception should not be rethrown but trigger a fallback") public Initializable run() { try { try { return new Dispatcher.ForJava8CapableVm(Class.forName("java.lang.invoke.MethodHandles").getMethod("publicLookup"), Class.forName("java.lang.invoke.MethodHandleInfo").getMethod("getName"), Class.forName("java.lang.invoke.MethodHandleInfo").getMethod("getDeclaringClass"), Class.forName("java.lang.invoke.MethodHandleInfo").getMethod("getReferenceKind"), Class.forName("java.lang.invoke.MethodHandleInfo").getMethod("getMethodType"), JavaType.METHOD_TYPE.load().getMethod("returnType"), JavaType.METHOD_TYPE.load().getMethod("parameterArray"), JavaType.METHOD_HANDLES_LOOKUP.load().getMethod("lookupClass"), JavaType.METHOD_HANDLES_LOOKUP.load().getMethod("revealDirect", JavaType.METHOD_HANDLE.load())); } catch (Exception ignored) { return new Dispatcher.ForJava7CapableVm(Class.forName("java.lang.invoke.MethodHandles").getMethod("publicLookup"), Class.forName("java.lang.invoke.MethodHandleInfo").getMethod("getName"), Class.forName("java.lang.invoke.MethodHandleInfo").getMethod("getDeclaringClass"), Class.forName("java.lang.invoke.MethodHandleInfo").getMethod("getReferenceKind"), Class.forName("java.lang.invoke.MethodHandleInfo").getMethod("getMethodType"), JavaType.METHOD_TYPE.load().getMethod("returnType"), JavaType.METHOD_TYPE.load().getMethod("parameterArray"), JavaType.METHOD_HANDLES_LOOKUP.load().getMethod("lookupClass"), Class.forName("java.lang.invoke.MethodHandleInfo").getConstructor(JavaType.METHOD_HANDLE.load())); } } catch (Exception ignored) { return Dispatcher.ForLegacyVm.INSTANCE; } } }
An abstract base implementation of a dispatcher.
/** * An abstract base implementation of a dispatcher. */
@HashCodeAndEqualsPlugin.Enhance abstract class AbstractBase implements Dispatcher, Initializable {
An empty array that can be used to indicate no arguments to avoid an allocation on a reflective call.
/** * An empty array that can be used to indicate no arguments to avoid an allocation on a reflective call. */
private static final Object[] NO_ARGUMENTS = new Object[0];
A reference to java.lang.invoke.MethodHandles#publicLookup.
/** * A reference to {@code java.lang.invoke.MethodHandles#publicLookup}. */
protected final Method publicLookup;
A reference to java.lang.invoke.MethodHandleInfo#getName.
/** * A reference to {@code java.lang.invoke.MethodHandleInfo#getName}. */
protected final Method getName;
A reference to java.lang.invoke.MethodHandleInfo#getDeclaringClass.
/** * A reference to {@code java.lang.invoke.MethodHandleInfo#getDeclaringClass}. */
protected final Method getDeclaringClass;
A reference to java.lang.invoke.MethodHandleInfo#getReferenceKind.
/** * A reference to {@code java.lang.invoke.MethodHandleInfo#getReferenceKind}. */
protected final Method getReferenceKind;
A reference to java.lang.invoke.MethodHandleInfo#getMethodType.
/** * A reference to {@code java.lang.invoke.MethodHandleInfo#getMethodType}. */
protected final Method getMethodType;
A reference to java.lang.invoke.MethodType#returnType.
/** * A reference to {@code java.lang.invoke.MethodType#returnType}. */
protected final Method returnType;
A reference to java.lang.invoke.MethodType#parameterArray.
/** * A reference to {@code java.lang.invoke.MethodType#parameterArray}. */
protected final Method parameterArray;
A reference to java.lang.invoke.MethodHandles$Lookup#lookupClass method.
/** * A reference to {@code java.lang.invoke.MethodHandles$Lookup#lookupClass} method. */
protected final Method lookupClass;
Creates a legal dispatcher.
Params:
  • publicLookup – A reference to java.lang.invoke.MethodHandles#publicLookup.
  • getName – A reference to java.lang.invoke.MethodHandleInfo#getName.
  • getDeclaringClass – A reference to java.lang.invoke.MethodHandleInfo#getDeclaringClass.
  • getReferenceKind – A reference to java.lang.invoke.MethodHandleInfo#getReferenceKind.
  • getMethodType – A reference to java.lang.invoke.MethodHandleInfo#getMethodType.
  • returnType – A reference to java.lang.invoke.MethodType#returnType.
  • parameterArray – A reference to java.lang.invoke.MethodType#parameterArray.
  • lookupClass – A reference to java.lang.invoke.MethodHandles$Lookup#lookupClass method.
/** * Creates a legal dispatcher. * * @param publicLookup A reference to {@code java.lang.invoke.MethodHandles#publicLookup}. * @param getName A reference to {@code java.lang.invoke.MethodHandleInfo#getName}. * @param getDeclaringClass A reference to {@code java.lang.invoke.MethodHandleInfo#getDeclaringClass}. * @param getReferenceKind A reference to {@code java.lang.invoke.MethodHandleInfo#getReferenceKind}. * @param getMethodType A reference to {@code java.lang.invoke.MethodHandleInfo#getMethodType}. * @param returnType A reference to {@code java.lang.invoke.MethodType#returnType}. * @param parameterArray A reference to {@code java.lang.invoke.MethodType#parameterArray}. * @param lookupClass A reference to {@code java.lang.invoke.MethodHandles$Lookup#lookupClass} method. */
protected AbstractBase(Method publicLookup, Method getName, Method getDeclaringClass, Method getReferenceKind, Method getMethodType, Method returnType, Method parameterArray, Method lookupClass) { this.publicLookup = publicLookup; this.getName = getName; this.getDeclaringClass = getDeclaringClass; this.getReferenceKind = getReferenceKind; this.getMethodType = getMethodType; this.returnType = returnType; this.parameterArray = parameterArray; this.lookupClass = lookupClass; }
{@inheritDoc}
/** * {@inheritDoc} */
public Object publicLookup() { try { return publicLookup.invoke(null, NO_ARGUMENTS); } catch (IllegalAccessException exception) { throw new IllegalStateException("Cannot access java.lang.invoke.MethodHandles#publicLookup", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.invoke.MethodHandles#publicLookup", exception.getCause()); } }
{@inheritDoc}
/** * {@inheritDoc} */
public Object getMethodType(Object methodHandleInfo) { try { return getMethodType.invoke(methodHandleInfo, NO_ARGUMENTS); } catch (IllegalAccessException exception) { throw new IllegalStateException("Cannot access java.lang.invoke.MethodHandleInfo#getMethodType", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.invoke.MethodHandleInfo#getMethodType", exception.getCause()); } }
{@inheritDoc}
/** * {@inheritDoc} */
public int getReferenceKind(Object methodHandleInfo) { try { return (Integer) getReferenceKind.invoke(methodHandleInfo, NO_ARGUMENTS); } catch (IllegalAccessException exception) { throw new IllegalStateException("Cannot access java.lang.invoke.MethodHandleInfo#getReferenceKind", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.invoke.MethodHandleInfo#getReferenceKind", exception.getCause()); } }
{@inheritDoc}
/** * {@inheritDoc} */
public Class<?> getDeclaringClass(Object methodHandleInfo) { try { return (Class<?>) getDeclaringClass.invoke(methodHandleInfo, NO_ARGUMENTS); } catch (IllegalAccessException exception) { throw new IllegalStateException("Cannot access java.lang.invoke.MethodHandleInfo#getDeclaringClass", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.invoke.MethodHandleInfo#getDeclaringClass", exception.getCause()); } }
{@inheritDoc}
/** * {@inheritDoc} */
public String getName(Object methodHandleInfo) { try { return (String) getName.invoke(methodHandleInfo, NO_ARGUMENTS); } catch (IllegalAccessException exception) { throw new IllegalStateException("Cannot access java.lang.invoke.MethodHandleInfo#getName", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.invoke.MethodHandleInfo#getName", exception.getCause()); } }
{@inheritDoc}
/** * {@inheritDoc} */
public Class<?> returnType(Object methodType) { try { return (Class<?>) returnType.invoke(methodType, NO_ARGUMENTS); } catch (IllegalAccessException exception) { throw new IllegalStateException("Cannot access java.lang.invoke.MethodType#returnType", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.reflect.MethodType#returnType", exception.getCause()); } }
{@inheritDoc}
/** * {@inheritDoc} */
public List<? extends Class<?>> parameterArray(Object methodType) { try { return Arrays.asList((Class<?>[]) parameterArray.invoke(methodType, NO_ARGUMENTS)); } catch (IllegalAccessException exception) { throw new IllegalStateException("Cannot access java.lang.reflect.MethodType#parameterArray", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.reflect.MethodType#parameterArray", exception.getCause()); } }
{@inheritDoc}
/** * {@inheritDoc} */
public Class<?> lookupType(Object lookup) { try { return (Class<?>) lookupClass.invoke(lookup, NO_ARGUMENTS); } catch (IllegalAccessException exception) { throw new IllegalStateException("Cannot access java.lang.reflect.MethodHandles.Lookup#lookupClass", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.reflect.MethodHandles.Lookup#lookupClass", exception.getCause()); } } }
A dispatcher for introspecting a java.lang.invoke.MethodHandle instance on a virtual machine that officially supports this introspection, i.e. Java versions 8+.
/** * A dispatcher for introspecting a {@code java.lang.invoke.MethodHandle} instance on a virtual machine that officially supports this * introspection, i.e. Java versions 8+. */
@HashCodeAndEqualsPlugin.Enhance class ForJava8CapableVm extends AbstractBase {
A reference to the java.lang.invoke.MethodHandles.Lookup#revealDirect method.
/** * A reference to the {@code java.lang.invoke.MethodHandles.Lookup#revealDirect} method. */
private final Method revealDirect;
Creates a dispatcher for a modern VM.
Params:
  • publicLookup – A reference to java.lang.invoke.MethodHandles#publicLookup.
  • getName – A reference to java.lang.invoke.MethodHandleInfo#getName.
  • getDeclaringClass – A reference to java.lang.invoke.MethodHandleInfo#getDeclaringClass.
  • getReferenceKind – A reference to java.lang.invoke.MethodHandleInfo#getReferenceKind.
  • getMethodType – A reference to java.lang.invoke.MethodHandleInfo#getMethodType.
  • returnType – A reference to java.lang.invoke.MethodType#returnType.
  • parameterArray – A reference to java.lang.invoke.MethodType#parameterArray.
  • lookupClass – A reference to java.lang.invoke.MethodHandles$Lookup#lookupClass method.
  • revealDirect – A reference to the java.lang.invoke.MethodHandles.Lookup#revealDirect method.
/** * Creates a dispatcher for a modern VM. * * @param publicLookup A reference to {@code java.lang.invoke.MethodHandles#publicLookup}. * @param getName A reference to {@code java.lang.invoke.MethodHandleInfo#getName}. * @param getDeclaringClass A reference to {@code java.lang.invoke.MethodHandleInfo#getDeclaringClass}. * @param getReferenceKind A reference to {@code java.lang.invoke.MethodHandleInfo#getReferenceKind}. * @param getMethodType A reference to {@code java.lang.invoke.MethodHandleInfo#getMethodType}. * @param returnType A reference to {@code java.lang.invoke.MethodType#returnType}. * @param parameterArray A reference to {@code java.lang.invoke.MethodType#parameterArray}. * @param lookupClass A reference to {@code java.lang.invoke.MethodHandles$Lookup#lookupClass} method. * @param revealDirect A reference to the {@code java.lang.invoke.MethodHandles.Lookup#revealDirect} method. */
protected ForJava8CapableVm(Method publicLookup, Method getName, Method getDeclaringClass, Method getReferenceKind, Method getMethodType, Method returnType, Method parameterArray, Method lookupClass, Method revealDirect) { super(publicLookup, getName, getDeclaringClass, getReferenceKind, getMethodType, returnType, parameterArray, lookupClass); this.revealDirect = revealDirect; }
{@inheritDoc}
/** * {@inheritDoc} */
public Object reveal(Object lookup, Object methodHandle) { try { return revealDirect.invoke(lookup, methodHandle); } catch (IllegalAccessException exception) { throw new IllegalStateException("Cannot access java.lang.invoke.MethodHandles.Lookup#revealDirect", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.invoke.MethodHandles.Lookup#revealDirect", exception.getCause()); } }
{@inheritDoc}
/** * {@inheritDoc} */
public Dispatcher initialize() { return this; } }
A dispatcher that extracts the information of a method handle by using private APIs that are available in Java 7+.
/** * A dispatcher that extracts the information of a method handle by using private APIs that are available in Java 7+. */
@HashCodeAndEqualsPlugin.Enhance class ForJava7CapableVm extends AbstractBase implements PrivilegedAction<Dispatcher> {
A reference to the java.lang.invoke.MethodInfo constructor.
/** * A reference to the {@code java.lang.invoke.MethodInfo} constructor. */
private final Constructor<?> methodInfo;
Creates a dispatcher for an intermediate VM.
Params:
  • publicLookup – A reference to java.lang.invoke.MethodHandles#publicLookup.
  • getName – A reference to java.lang.invoke.MethodHandleInfo#getName.
  • getDeclaringClass – A reference to java.lang.invoke.MethodHandleInfo#getDeclaringClass.
  • getReferenceKind – A reference to java.lang.invoke.MethodHandleInfo#getReferenceKind.
  • getMethodType – A reference to java.lang.invoke.MethodHandleInfo#getMethodType.
  • returnType – A reference to java.lang.invoke.MethodType#returnType.
  • parameterArray – A reference to java.lang.invoke.MethodType#parameterArray.
  • lookupClass – A reference to java.lang.invoke.MethodHandles$Lookup#lookupClass method.
  • methodInfo – A reference to the java.lang.invoke.MethodInfo constructor.
/** * Creates a dispatcher for an intermediate VM. * * @param publicLookup A reference to {@code java.lang.invoke.MethodHandles#publicLookup}. * @param getName A reference to {@code java.lang.invoke.MethodHandleInfo#getName}. * @param getDeclaringClass A reference to {@code java.lang.invoke.MethodHandleInfo#getDeclaringClass}. * @param getReferenceKind A reference to {@code java.lang.invoke.MethodHandleInfo#getReferenceKind}. * @param getMethodType A reference to {@code java.lang.invoke.MethodHandleInfo#getMethodType}. * @param returnType A reference to {@code java.lang.invoke.MethodType#returnType}. * @param parameterArray A reference to {@code java.lang.invoke.MethodType#parameterArray}. * @param lookupClass A reference to {@code java.lang.invoke.MethodHandles$Lookup#lookupClass} method. * @param methodInfo A reference to the {@code java.lang.invoke.MethodInfo} constructor. */
protected ForJava7CapableVm(Method publicLookup, Method getName, Method getDeclaringClass, Method getReferenceKind, Method getMethodType, Method returnType, Method parameterArray, Method lookupClass, Constructor<?> methodInfo) { super(publicLookup, getName, getDeclaringClass, getReferenceKind, getMethodType, returnType, parameterArray, lookupClass); this.methodInfo = methodInfo; }
{@inheritDoc}
/** * {@inheritDoc} */
public Dispatcher initialize() { return AccessController.doPrivileged(this); }
{@inheritDoc}
/** * {@inheritDoc} */
public Dispatcher run() { // This is safe even in a multi-threaded environment as all threads set the instances accessible before invoking any methods. // By always setting accessibility, the security manager is always triggered if this operation was illegal. methodInfo.setAccessible(true); getName.setAccessible(true); getDeclaringClass.setAccessible(true); getReferenceKind.setAccessible(true); getMethodType.setAccessible(true); return this; }
{@inheritDoc}
/** * {@inheritDoc} */
public Object reveal(Object lookup, Object methodHandle) { try { return methodInfo.newInstance(methodHandle); } catch (IllegalAccessException exception) { throw new IllegalStateException("Cannot access java.lang.invoke.MethodInfo()", exception); } catch (InvocationTargetException exception) { throw new IllegalStateException("Error invoking java.lang.invoke.MethodInfo()", exception.getCause()); } catch (InstantiationException exception) { throw new IllegalStateException("Error constructing java.lang.invoke.MethodInfo", exception); } } }
A dispatcher that does not support method handles at all.
/** * A dispatcher that does not support method handles at all. */
enum ForLegacyVm implements Initializable {
The singleton instance.
/** * The singleton instance. */
INSTANCE;
{@inheritDoc}
/** * {@inheritDoc} */
public Dispatcher initialize() { throw new UnsupportedOperationException("Unsupported type on current JVM: java.lang.invoke.MethodHandle"); }
{@inheritDoc}
/** * {@inheritDoc} */
public Object publicLookup() { throw new UnsupportedOperationException("Unsupported type on current JVM: java.lang.invoke.MethodHandle"); }
{@inheritDoc}
/** * {@inheritDoc} */
public Class<?> lookupType(Object lookup) { throw new UnsupportedOperationException("Unsupported type on current JVM: java.lang.invoke.MethodHandle"); } } }
A representation of a method handle's type.
/** * A representation of a method handle's type. */
public enum HandleType {
A handle representing an invokevirtual invocation.
/** * A handle representing an invokevirtual invocation. */
INVOKE_VIRTUAL(Opcodes.H_INVOKEVIRTUAL),
A handle representing an invokestatic invocation.
/** * A handle representing an invokestatic invocation. */
INVOKE_STATIC(Opcodes.H_INVOKESTATIC),
A handle representing an invokespecial invocation for a non-constructor.
/** * A handle representing an invokespecial invocation for a non-constructor. */
INVOKE_SPECIAL(Opcodes.H_INVOKESPECIAL),
A handle representing an invokeinterface invocation.
/** * A handle representing an invokeinterface invocation. */
INVOKE_INTERFACE(Opcodes.H_INVOKEINTERFACE),
A handle representing an invokespecial invocation for a constructor.
/** * A handle representing an invokespecial invocation for a constructor. */
INVOKE_SPECIAL_CONSTRUCTOR(Opcodes.H_NEWINVOKESPECIAL),
A handle representing a write of a non-static field invocation.
/** * A handle representing a write of a non-static field invocation. */
PUT_FIELD(Opcodes.H_PUTFIELD),
A handle representing a read of a non-static field invocation.
/** * A handle representing a read of a non-static field invocation. */
GET_FIELD(Opcodes.H_GETFIELD),
A handle representing a write of a static field invocation.
/** * A handle representing a write of a static field invocation. */
PUT_STATIC_FIELD(Opcodes.H_PUTSTATIC),
A handle representing a read of a static field invocation.
/** * A handle representing a read of a static field invocation. */
GET_STATIC_FIELD(Opcodes.H_GETSTATIC);
The represented identifier.
/** * The represented identifier. */
private final int identifier;
Creates a new handle type.
Params:
  • identifier – The represented identifier.
/** * Creates a new handle type. * * @param identifier The represented identifier. */
HandleType(int identifier) { this.identifier = identifier; }
Extracts a handle type for invoking the given method.
Params:
  • methodDescription – The method for which a handle type should be found.
Returns:The handle type for the given method.
/** * Extracts a handle type for invoking the given method. * * @param methodDescription The method for which a handle type should be found. * @return The handle type for the given method. */
protected static HandleType of(MethodDescription.InDefinedShape methodDescription) { if (methodDescription.isStatic()) { return INVOKE_STATIC; } else if (methodDescription.isPrivate()) { return INVOKE_SPECIAL; } else if (methodDescription.isConstructor()) { return INVOKE_SPECIAL_CONSTRUCTOR; } else if (methodDescription.getDeclaringType().isInterface()) { return INVOKE_INTERFACE; } else { return INVOKE_VIRTUAL; } }
Extracts a handle type for the given identifier.
Params:
  • identifier – The identifier to extract a handle type for.
Returns:The representing handle type.
/** * Extracts a handle type for the given identifier. * * @param identifier The identifier to extract a handle type for. * @return The representing handle type. */
protected static HandleType of(int identifier) { for (HandleType handleType : HandleType.values()) { if (handleType.getIdentifier() == identifier) { return handleType; } } throw new IllegalArgumentException("Unknown handle type: " + identifier); }
Extracts a handle type for invoking the given method via invokespecial.
Params:
  • methodDescription – The method for which a handle type should be found.
Returns:The handle type for the given method.
/** * Extracts a handle type for invoking the given method via invokespecial. * * @param methodDescription The method for which a handle type should be found. * @return The handle type for the given method. */
protected static HandleType ofSpecial(MethodDescription.InDefinedShape methodDescription) { if (methodDescription.isStatic() || methodDescription.isAbstract()) { throw new IllegalArgumentException("Cannot invoke " + methodDescription + " via invokespecial"); } return methodDescription.isConstructor() ? INVOKE_SPECIAL_CONSTRUCTOR : INVOKE_SPECIAL; }
Extracts a handle type for a getter of the given field.
Params:
  • fieldDescription – The field for which to create a getter handle.
Returns:The corresponding handle type.
/** * Extracts a handle type for a getter of the given field. * * @param fieldDescription The field for which to create a getter handle. * @return The corresponding handle type. */
protected static HandleType ofGetter(FieldDescription.InDefinedShape fieldDescription) { return fieldDescription.isStatic() ? GET_STATIC_FIELD : GET_FIELD; }
Extracts a handle type for a setter of the given field.
Params:
  • fieldDescription – The field for which to create a setter handle.
Returns:The corresponding handle type.
/** * Extracts a handle type for a setter of the given field. * * @param fieldDescription The field for which to create a setter handle. * @return The corresponding handle type. */
protected static HandleType ofSetter(FieldDescription.InDefinedShape fieldDescription) { return fieldDescription.isStatic() ? PUT_STATIC_FIELD : PUT_FIELD; }
Returns the represented identifier.
Returns:The represented identifier.
/** * Returns the represented identifier. * * @return The represented identifier. */
public int getIdentifier() { return identifier; } } }
Represents a dynamically resolved constant pool entry of a class file. This feature is supported for class files in version 11 and newer.
/** * Represents a dynamically resolved constant pool entry of a class file. This feature is supported for class files in version 11 and newer. */
class Dynamic implements JavaConstant {
The java.lang.invoke.ConstantBootstraps class's internal name..
/** * The {@code java.lang.invoke.ConstantBootstraps} class's internal name.. */
private static final String CONSTANT_BOOTSTRAPS = "java/lang/invoke/ConstantBootstraps";
The represented bootstrap value.
/** * The represented bootstrap value. */
private final ConstantDynamic value;
The represented value constant.
/** * The represented value constant. */
private final TypeDescription typeDescription;
Creates a new dynamic class pool entry.
Params:
  • value – The represented bootstrap value.
  • typeDescription – The represented value constant.
/** * Creates a new dynamic class pool entry. * * @param value The represented bootstrap value. * @param typeDescription The represented value constant. */
protected Dynamic(ConstantDynamic value, TypeDescription typeDescription) { this.value = value; this.typeDescription = typeDescription; }
Returns a constant null value of type Object.
Returns:A dynamically resolved null constant.
/** * Returns a constant {@code null} value of type {@link Object}. * * @return A dynamically resolved null constant. */
public static Dynamic ofNullConstant() { return new Dynamic(new ConstantDynamic("nullConstant", TypeDescription.OBJECT.getDescriptor(), new Handle(Opcodes.H_INVOKESTATIC, CONSTANT_BOOTSTRAPS, "nullConstant", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;", false)), TypeDescription.OBJECT); }
Returns a Class constant for a primitive type.
Params:
  • type – The primitive type to represent.
Returns:A dynamically resolved primitive type constant.
/** * Returns a {@link Class} constant for a primitive type. * * @param type The primitive type to represent. * @return A dynamically resolved primitive type constant. */
public static JavaConstant ofPrimitiveType(Class<?> type) { return ofPrimitiveType(TypeDescription.ForLoadedType.of(type)); }
Returns a Class constant for a primitive type.
Params:
  • typeDescription – The primitive type to represent.
Returns:A dynamically resolved primitive type constant.
/** * Returns a {@link Class} constant for a primitive type. * * @param typeDescription The primitive type to represent. * @return A dynamically resolved primitive type constant. */
public static JavaConstant ofPrimitiveType(TypeDescription typeDescription) { if (!typeDescription.isPrimitive()) { throw new IllegalArgumentException("Not a primitive type: " + typeDescription); } return new Dynamic(new ConstantDynamic(typeDescription.getDescriptor(), TypeDescription.CLASS.getDescriptor(), new Handle(Opcodes.H_INVOKESTATIC, CONSTANT_BOOTSTRAPS, "primitiveClass", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Class;", false)), TypeDescription.CLASS); }
Returns a Enum value constant.
Params:
  • enumeration – The enumeration value to represent.
Returns:A dynamically resolved enumeration constant.
/** * Returns a {@link Enum} value constant. * * @param enumeration The enumeration value to represent. * @return A dynamically resolved enumeration constant. */
public static JavaConstant ofEnumeration(Enum<?> enumeration) { return ofEnumeration(new EnumerationDescription.ForLoadedEnumeration(enumeration)); }
Returns a Enum value constant.
Params:
  • enumerationDescription – The enumeration value to represent.
Returns:A dynamically resolved enumeration constant.
/** * Returns a {@link Enum} value constant. * * @param enumerationDescription The enumeration value to represent. * @return A dynamically resolved enumeration constant. */
public static JavaConstant ofEnumeration(EnumerationDescription enumerationDescription) { return new Dynamic(new ConstantDynamic(enumerationDescription.getValue(), enumerationDescription.getEnumerationType().getDescriptor(), new Handle(Opcodes.H_INVOKESTATIC, CONSTANT_BOOTSTRAPS, "enumConstant", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Enum;", false)), enumerationDescription.getEnumerationType()); }
Returns a static, final field constant.
Params:
  • field – The field to represent a value of.
Returns:A dynamically resolved field value constant.
/** * Returns a {@code static}, {@code final} field constant. * * @param field The field to represent a value of. * @return A dynamically resolved field value constant. */
public static Dynamic ofField(Field field) { return ofField(new FieldDescription.ForLoadedField(field)); }
Returns a static, final field constant.
Params:
  • fieldDescription – The field to represent a value of.
Returns:A dynamically resolved field value constant.
/** * Returns a {@code static}, {@code final} field constant. * * @param fieldDescription The field to represent a value of. * @return A dynamically resolved field value constant. */
public static Dynamic ofField(FieldDescription.InDefinedShape fieldDescription) { if (!fieldDescription.isStatic() || !fieldDescription.isFinal()) { throw new IllegalArgumentException("Field must be static and final: " + fieldDescription); } boolean selfDeclared = fieldDescription.getType().isPrimitive() ? fieldDescription.getType().asErasure().asBoxed().equals(fieldDescription.getType().asErasure()) : fieldDescription.getDeclaringType().equals(fieldDescription.getType().asErasure()); return new Dynamic(new ConstantDynamic(fieldDescription.getInternalName(), fieldDescription.getDescriptor(), new Handle(Opcodes.H_INVOKESTATIC, CONSTANT_BOOTSTRAPS, "getStaticFinal", selfDeclared ? "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/Object;" : "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/Object;", false), selfDeclared ? new Object[0] : new Object[]{Type.getType(fieldDescription.getDeclaringType().getDescriptor())}), fieldDescription.getType().asErasure()); }
Represents a constant that is resolved by invoking a static factory method.
Params:
  • method – The method to invoke to create the represented constant value.
  • rawArgument – The method's constant arguments.
Returns:A dynamic constant that is resolved by the supplied factory method.
/** * Represents a constant that is resolved by invoking a {@code static} factory method. * * @param method The method to invoke to create the represented constant value. * @param rawArgument The method's constant arguments. * @return A dynamic constant that is resolved by the supplied factory method. */
public static Dynamic ofInvocation(Method method, Object... rawArgument) { return ofInvocation(method, Arrays.asList(rawArgument)); }
Represents a constant that is resolved by invoking a static factory method.
Params:
  • method – The method to invoke to create the represented constant value.
  • rawArguments – The method's constant arguments.
Returns:A dynamic constant that is resolved by the supplied factory method.
/** * Represents a constant that is resolved by invoking a {@code static} factory method. * * @param method The method to invoke to create the represented constant value. * @param rawArguments The method's constant arguments. * @return A dynamic constant that is resolved by the supplied factory method. */
public static Dynamic ofInvocation(Method method, List<?> rawArguments) { return ofInvocation(new MethodDescription.ForLoadedMethod(method), rawArguments); }
Represents a constant that is resolved by invoking a constructor.
Params:
  • constructor – The constructor to invoke to create the represented constant value.
  • rawArgument – The constructor's constant arguments.
Returns:A dynamic constant that is resolved by the supplied constuctor.
/** * Represents a constant that is resolved by invoking a constructor. * * @param constructor The constructor to invoke to create the represented constant value. * @param rawArgument The constructor's constant arguments. * @return A dynamic constant that is resolved by the supplied constuctor. */
public static Dynamic ofInvocation(Constructor<?> constructor, Object... rawArgument) { return ofInvocation(constructor, Arrays.asList(rawArgument)); }
Represents a constant that is resolved by invoking a constructor.
Params:
  • constructor – The constructor to invoke to create the represented constant value.
  • rawArguments – The constructor's constant arguments.
Returns:A dynamic constant that is resolved by the supplied constuctor.
/** * Represents a constant that is resolved by invoking a constructor. * * @param constructor The constructor to invoke to create the represented constant value. * @param rawArguments The constructor's constant arguments. * @return A dynamic constant that is resolved by the supplied constuctor. */
public static Dynamic ofInvocation(Constructor<?> constructor, List<?> rawArguments) { return ofInvocation(new MethodDescription.ForLoadedConstructor(constructor), rawArguments); }
Represents a constant that is resolved by invoking a static factory method or a constructor.
Params:
  • methodDescription – The method or constructor to invoke to create the represented constant value.
  • rawArgument – The method's or constructor's constant arguments.
Returns:A dynamic constant that is resolved by the supplied factory method or constructor.
/** * Represents a constant that is resolved by invoking a {@code static} factory method or a constructor. * * @param methodDescription The method or constructor to invoke to create the represented constant value. * @param rawArgument The method's or constructor's constant arguments. * @return A dynamic constant that is resolved by the supplied factory method or constructor. */
public static Dynamic ofInvocation(MethodDescription.InDefinedShape methodDescription, Object... rawArgument) { return ofInvocation(methodDescription, Arrays.asList(rawArgument)); }
Represents a constant that is resolved by invoking a static factory method or a constructor.
Params:
  • methodDescription – The method or constructor to invoke to create the represented constant value.
  • rawArguments – The method's or constructor's constant arguments.
Returns:A dynamic constant that is resolved by the supplied factory method or constructor.
/** * Represents a constant that is resolved by invoking a {@code static} factory method or a constructor. * * @param methodDescription The method or constructor to invoke to create the represented constant value. * @param rawArguments The method's or constructor's constant arguments. * @return A dynamic constant that is resolved by the supplied factory method or constructor. */
public static Dynamic ofInvocation(MethodDescription.InDefinedShape methodDescription, List<?> rawArguments) { if (!methodDescription.isConstructor() && methodDescription.getReturnType().represents(void.class)) { throw new IllegalArgumentException("Bootstrap method is no constructor or non-void static factory: " + methodDescription); } else if (methodDescription.getParameters().size() + (methodDescription.isStatic() || methodDescription.isConstructor() ? 0 : 1) != rawArguments.size()) { throw new IllegalArgumentException("Cannot assign " + rawArguments + " to " + methodDescription); } Iterator<TypeDescription> iterator = (methodDescription.isStatic() || methodDescription.isConstructor() ? methodDescription.getParameters().asTypeList().asErasures() : CompoundList.of(methodDescription.getDeclaringType(), methodDescription.getParameters().asTypeList().asErasures())).iterator(); List<Object> arguments = new ArrayList<Object>(rawArguments.size()); for (Object argument : rawArguments) { if (argument == null) { argument = Dynamic.ofNullConstant(); } else if (argument instanceof Class) { argument = ((Class<?>) argument).isPrimitive() ? ofPrimitiveType((Class<?>) argument) : TypeDescription.ForLoadedType.of((Class<?>) argument); } else if (argument instanceof TypeDescription && ((TypeDescription) argument).isPrimitive()) { argument = ofPrimitiveType((TypeDescription) argument); } else if (JavaType.METHOD_HANDLE.isInstance(argument)) { argument = MethodHandle.ofLoaded(argument); } else if (JavaType.METHOD_TYPE.isInstance(argument)) { argument = MethodType.ofLoaded(argument); } TypeDescription targetType; if (argument instanceof JavaConstant) { targetType = ((JavaConstant) argument).getType(); } else if (argument instanceof TypeDescription) { targetType = TypeDescription.CLASS; } else { targetType = TypeDescription.ForLoadedType.of(argument.getClass()); } if (!targetType.asBoxed().isAssignableTo(iterator.next().asBoxed())) { throw new IllegalArgumentException("Cannot assign argument of type " + targetType + " to " + methodDescription); } arguments.add(argument); } Object[] asmifiedArgument = new Object[arguments.size() + 1]; asmifiedArgument[0] = new Handle(methodDescription.isConstructor() ? Opcodes.H_NEWINVOKESPECIAL : Opcodes.H_INVOKESTATIC, methodDescription.getDeclaringType().getInternalName(), methodDescription.getInternalName(), methodDescription.getDescriptor(), false); int index = 1; for (Object argument : arguments) { if (argument instanceof TypeDescription) { argument = Type.getType(((TypeDescription) argument).getDescriptor()); } else if (argument instanceof JavaConstant) { argument = ((JavaConstant) argument).asConstantPoolValue(); } asmifiedArgument[index++] = argument; } return new Dynamic(new ConstantDynamic("invoke", (methodDescription.isConstructor() ? methodDescription.getDeclaringType() : methodDescription.getReturnType().asErasure()).getDescriptor(), new Handle(Opcodes.H_INVOKESTATIC, CONSTANT_BOOTSTRAPS, "invoke", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/invoke/MethodHandle;[Ljava/lang/Object;)Ljava/lang/Object;", false), asmifiedArgument), methodDescription.isConstructor() ? methodDescription.getDeclaringType() : methodDescription.getReturnType().asErasure()); }
Resolves a var handle constant for a field.
Params:
  • field – The field to represent a var handle for.
Returns:A dynamic constant that represents the created var handle constant.
/** * Resolves a var handle constant for a field. * * @param field The field to represent a var handle for. * @return A dynamic constant that represents the created var handle constant. */
public static JavaConstant ofVarHandle(Field field) { return ofVarHandle(new FieldDescription.ForLoadedField(field)); }
Resolves a var handle constant for a field.
Params:
  • fieldDescription – The field to represent a var handle for.
Returns:A dynamic constant that represents the created var handle constant.
/** * Resolves a var handle constant for a field. * * @param fieldDescription The field to represent a var handle for. * @return A dynamic constant that represents the created var handle constant. */
public static JavaConstant ofVarHandle(FieldDescription.InDefinedShape fieldDescription) { return new Dynamic(new ConstantDynamic(fieldDescription.getInternalName(), JavaType.VAR_HANDLE.getTypeStub().getDescriptor(), new Handle(Opcodes.H_INVOKESTATIC, CONSTANT_BOOTSTRAPS, fieldDescription.isStatic() ? "staticFieldVarHandle" : "fieldVarHandle", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/invoke/VarHandle;", false), Type.getType(fieldDescription.getDeclaringType().getDescriptor()), Type.getType(fieldDescription.getType().asErasure().getDescriptor())), JavaType.VAR_HANDLE.getTypeStub()); }
Resolves a var handle constant for an array.
Params:
  • type – The array type for which the var handle is resolved.
Returns:A dynamic constant that represents the created var handle constant.
/** * Resolves a var handle constant for an array. * * @param type The array type for which the var handle is resolved. * @return A dynamic constant that represents the created var handle constant. */
public static JavaConstant ofArrayVarHandle(Class<?> type) { return ofArrayVarHandle(TypeDescription.ForLoadedType.of(type)); }
Resolves a var handle constant for an array.
Params:
  • typeDescription – The array type for which the var handle is resolved.
Returns:A dynamic constant that represents the created var handle constant.
/** * Resolves a var handle constant for an array. * * @param typeDescription The array type for which the var handle is resolved. * @return A dynamic constant that represents the created var handle constant. */
public static JavaConstant ofArrayVarHandle(TypeDescription typeDescription) { if (!typeDescription.isArray()) { throw new IllegalArgumentException("Not an array type: " + typeDescription); } return new Dynamic(new ConstantDynamic("arrayVarHandle", JavaType.VAR_HANDLE.getTypeStub().getDescriptor(), new Handle(Opcodes.H_INVOKESTATIC, CONSTANT_BOOTSTRAPS, "arrayVarHandle", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/Class;)Ljava/lang/invoke/VarHandle;", false), Type.getType(typeDescription.getDescriptor())), JavaType.VAR_HANDLE.getTypeStub()); }
Binds the supplied bootstrap method for the resolution of a dynamic constant.
Params:
  • name – The name of the bootstrap constant that is provided to the bootstrap method or constructor.
  • method – The bootstrap method to invoke.
  • rawArgument – The arguments for the bootstrap method represented as primitive wrapper types, String, TypeDescription or JavaConstant values or their loaded forms.
Returns:A dynamic constant that represents the bootstrapped method's result.
/** * Binds the supplied bootstrap method for the resolution of a dynamic constant. * * @param name The name of the bootstrap constant that is provided to the bootstrap method or constructor. * @param method The bootstrap method to invoke. * @param rawArgument The arguments for the bootstrap method represented as primitive wrapper types, * {@link String}, {@link TypeDescription} or {@link JavaConstant} values or their loaded forms. * @return A dynamic constant that represents the bootstrapped method's result. */
public static Dynamic bootstrap(String name, Method method, Object... rawArgument) { return bootstrap(name, method, Arrays.asList(rawArgument)); }
Binds the supplied bootstrap method for the resolution of a dynamic constant.
Params:
  • name – The name of the bootstrap constant that is provided to the bootstrap method or constructor.
  • method – The bootstrap method to invoke.
  • rawArguments – The arguments for the bootstrap method represented as primitive wrapper types, String, TypeDescription or JavaConstant values or their loaded forms.
Returns:A dynamic constant that represents the bootstrapped method's result.
/** * Binds the supplied bootstrap method for the resolution of a dynamic constant. * * @param name The name of the bootstrap constant that is provided to the bootstrap method or constructor. * @param method The bootstrap method to invoke. * @param rawArguments The arguments for the bootstrap method represented as primitive wrapper types, * {@link String}, {@link TypeDescription} or {@link JavaConstant} values or their loaded forms. * @return A dynamic constant that represents the bootstrapped method's result. */
public static Dynamic bootstrap(String name, Method method, List<?> rawArguments) { return bootstrap(name, new MethodDescription.ForLoadedMethod(method), rawArguments); }
Binds the supplied bootstrap constructor for the resolution of a dynamic constant.
Params:
  • name – The name of the bootstrap constant that is provided to the bootstrap method or constructor.
  • constructor – The bootstrap constructor to invoke.
  • rawArgument – The arguments for the bootstrap constructor represented as primitive wrapper types, String, TypeDescription or JavaConstant values or their loaded forms.
Returns:A dynamic constant that represents the bootstrapped constructor's result.
/** * Binds the supplied bootstrap constructor for the resolution of a dynamic constant. * * @param name The name of the bootstrap constant that is provided to the bootstrap method or constructor. * @param constructor The bootstrap constructor to invoke. * @param rawArgument The arguments for the bootstrap constructor represented as primitive wrapper types, * {@link String}, {@link TypeDescription} or {@link JavaConstant} values or their loaded forms. * @return A dynamic constant that represents the bootstrapped constructor's result. */
public static Dynamic bootstrap(String name, Constructor<?> constructor, Object... rawArgument) { return bootstrap(name, constructor, Arrays.asList(rawArgument)); }
Binds the supplied bootstrap constructor for the resolution of a dynamic constant.
Params:
  • name – The name of the bootstrap constant that is provided to the bootstrap method or constructor.
  • constructor – The bootstrap constructor to invoke.
  • rawArguments – The arguments for the bootstrap constructor represented as primitive wrapper types, String, TypeDescription or JavaConstant values or their loaded forms.
Returns:A dynamic constant that represents the bootstrapped constructor's result.
/** * Binds the supplied bootstrap constructor for the resolution of a dynamic constant. * * @param name The name of the bootstrap constant that is provided to the bootstrap method or constructor. * @param constructor The bootstrap constructor to invoke. * @param rawArguments The arguments for the bootstrap constructor represented as primitive wrapper types, * {@link String}, {@link TypeDescription} or {@link JavaConstant} values or their loaded forms. * @return A dynamic constant that represents the bootstrapped constructor's result. */
public static Dynamic bootstrap(String name, Constructor<?> constructor, List<?> rawArguments) { return bootstrap(name, new MethodDescription.ForLoadedConstructor(constructor), rawArguments); }
Binds the supplied bootstrap method or constructor for the resolution of a dynamic constant.
Params:
  • name – The name of the bootstrap constant that is provided to the bootstrap method or constructor.
  • bootstrapMethod – The bootstrap method or constructor to invoke.
  • rawArgument – The arguments for the bootstrap method or constructor represented as primitive wrapper types, String, TypeDescription or JavaConstant values or their loaded forms.
Returns:A dynamic constant that represents the bootstrapped method's or constructor's result.
/** * Binds the supplied bootstrap method or constructor for the resolution of a dynamic constant. * * @param name The name of the bootstrap constant that is provided to the bootstrap method or constructor. * @param bootstrapMethod The bootstrap method or constructor to invoke. * @param rawArgument The arguments for the bootstrap method or constructor represented as primitive wrapper types, * {@link String}, {@link TypeDescription} or {@link JavaConstant} values or their loaded forms. * @return A dynamic constant that represents the bootstrapped method's or constructor's result. */
public static Dynamic bootstrap(String name, MethodDescription.InDefinedShape bootstrapMethod, Object... rawArgument) { return bootstrap(name, bootstrapMethod, Arrays.asList(rawArgument)); }
Binds the supplied bootstrap method or constructor for the resolution of a dynamic constant.
Params:
  • name – The name of the bootstrap constant that is provided to the bootstrap method or constructor.
  • bootstrapMethod – The bootstrap method or constructor to invoke.
  • rawArguments – The arguments for the bootstrap method or constructor represented as primitive wrapper types, String, TypeDescription or JavaConstant values or their loaded forms.
Returns:A dynamic constant that represents the bootstrapped method's or constructor's result.
/** * Binds the supplied bootstrap method or constructor for the resolution of a dynamic constant. * * @param name The name of the bootstrap constant that is provided to the bootstrap method or constructor. * @param bootstrapMethod The bootstrap method or constructor to invoke. * @param rawArguments The arguments for the bootstrap method or constructor represented as primitive wrapper types, * {@link String}, {@link TypeDescription} or {@link JavaConstant} values or their loaded forms. * @return A dynamic constant that represents the bootstrapped method's or constructor's result. */
public static Dynamic bootstrap(String name, MethodDescription.InDefinedShape bootstrapMethod, List<?> rawArguments) { if (name.length() == 0 || name.contains(".")) { throw new IllegalArgumentException("Not a valid field name: " + name); } List<Object> arguments = new ArrayList<Object>(rawArguments.size()); for (Object argument : rawArguments) { if (argument == null) { argument = ofNullConstant(); } else if (argument instanceof Class) { argument = ((Class<?>) argument).isPrimitive() ? ofPrimitiveType((Class<?>) argument) : TypeDescription.ForLoadedType.of((Class<?>) argument); } else if (argument instanceof TypeDescription && ((TypeDescription) argument).isPrimitive()) { argument = ofPrimitiveType((TypeDescription) argument); } else if (JavaType.METHOD_HANDLE.isInstance(argument)) { argument = MethodHandle.ofLoaded(argument); } else if (JavaType.METHOD_TYPE.isInstance(argument)) { argument = MethodType.ofLoaded(argument); } arguments.add(argument); } if (!bootstrapMethod.isConstantBootstrap(arguments)) { throw new IllegalArgumentException("Not a valid bootstrap method " + bootstrapMethod + " for " + arguments); } Object[] asmifiedArgument = new Object[arguments.size()]; int index = 0; for (Object argument : arguments) { if (argument instanceof TypeDescription) { argument = Type.getType(((TypeDescription) argument).getDescriptor()); } else if (argument instanceof JavaConstant) { argument = ((JavaConstant) argument).asConstantPoolValue(); } asmifiedArgument[index++] = argument; } return new Dynamic(new ConstantDynamic(name, (bootstrapMethod.isConstructor() ? bootstrapMethod.getDeclaringType() : bootstrapMethod.getReturnType().asErasure()).getDescriptor(), new Handle(bootstrapMethod.isConstructor() ? Opcodes.H_NEWINVOKESPECIAL : Opcodes.H_INVOKESTATIC, bootstrapMethod.getDeclaringType().getInternalName(), bootstrapMethod.getInternalName(), bootstrapMethod.getDescriptor(), false), asmifiedArgument), bootstrapMethod.isConstructor() ? bootstrapMethod.getDeclaringType() : bootstrapMethod.getReturnType().asErasure()); }
Resolves this Dynamic constant to resolve the returned instance to the supplied type. The type must be a subtype of the bootstrap method's return type. Constructors cannot be resolved to a different type.
Params:
  • type – The type to resolve the bootstrapped value to.
Returns:This dynamic constant but resolved to the supplied type.
/** * Resolves this {@link Dynamic} constant to resolve the returned instance to the supplied type. The type must be a subtype of the * bootstrap method's return type. Constructors cannot be resolved to a different type. * * @param type The type to resolve the bootstrapped value to. * @return This dynamic constant but resolved to the supplied type. */
public JavaConstant withType(Class<?> type) { return withType(TypeDescription.ForLoadedType.of(type)); }
Resolves this Dynamic constant to resolve the returned instance to the supplied type. The type must be a subtype of the bootstrap method's return type. Constructors cannot be resolved to a different type.
Params:
  • typeDescription – The type to resolve the bootstrapped value to.
Returns:This dynamic constant but resolved to the supplied type.
/** * Resolves this {@link Dynamic} constant to resolve the returned instance to the supplied type. The type must be a subtype of the * bootstrap method's return type. Constructors cannot be resolved to a different type. * * @param typeDescription The type to resolve the bootstrapped value to. * @return This dynamic constant but resolved to the supplied type. */
public JavaConstant withType(TypeDescription typeDescription) { if (typeDescription.represents(void.class)) { throw new IllegalArgumentException("Constant value cannot represent void"); } else if (value.getBootstrapMethod().getName().equals(MethodDescription.CONSTRUCTOR_INTERNAL_NAME) ? !this.typeDescription.isAssignableTo(typeDescription) : (!typeDescription.asBoxed().isInHierarchyWith(this.typeDescription.asBoxed()))) { throw new IllegalArgumentException(typeDescription + " is not compatible with bootstrapped type " + this.typeDescription); } Object[] bootstrapMethodArgument = new Object[value.getBootstrapMethodArgumentCount()]; for (int index = 0; index < value.getBootstrapMethodArgumentCount(); index++) { bootstrapMethodArgument[index] = value.getBootstrapMethodArgument(index); } return new Dynamic(new ConstantDynamic(value.getName(), typeDescription.getDescriptor(), value.getBootstrapMethod(), bootstrapMethodArgument), typeDescription); }
{@inheritDoc}
/** * {@inheritDoc} */
public Object asConstantPoolValue() { return value; }
{@inheritDoc}
/** * {@inheritDoc} */
public TypeDescription getType() { return typeDescription; } @Override public int hashCode() { int result = value.hashCode(); result = 31 * result + typeDescription.hashCode(); return result; } @Override public boolean equals(Object other) { if (this == other) { return true; } else if (other == null || getClass() != other.getClass()) { return false; } Dynamic dynamic = (Dynamic) other; return value.equals(dynamic.value) && typeDescription.equals(dynamic.typeDescription); } } }