Class HandleUtil

java.lang.Object
com.blamejared.crafttweaker.api.util.HandleUtil

public final class HandleUtil extends Object
Holds various utilities to deal with MethodHandles and VarHandles for reflection purposes.

All handles returned by methods in this class are fully privileged, meaning that they can perform any desired operation on the target, as long as it makes sense. For example, it is allowed for a VarHandle returned by this class to alter the value of a final field in a class.

For maximum performance, it is suggested to invoke this method once and cache the result in a static final field. The JVM will then be able to inline the call and replace it with a standard opcode instruction.

Since:
9.0.0
  • Method Details

    • linkMethod

      public static MethodHandle linkMethod(Class<?> type, HandleUtil.AccessType accessType, String methodName, Class<?> returnType, Class<?>... arguments)
      Obtains a new MethodHandle to the specified method with the given HandleUtil.AccessType.

      If more than one name needs to be specified, refer to linkMethod(Class, AccessType, Names, Class, Class[]) instead.

      Mapping resolution is automatic, meaning that the deobfuscation from one mapping set to the current one is automatically attempted.

      Parameters:
      type - The Class which defines the method to invoke.
      accessType - The type of access that the method handle should attempt
      methodName - The name of the method that needs to be invoked. The name should be obfuscated.
      returnType - The Class that represents the return type of the target method.
      arguments - An array holding various Classes, each representing the type of method parameter.
      Returns:
      A MethodHandle that links to the method specified, if it exists.
      Throws:
      HandleUtil.UnableToLinkHandleException - If linkage fails due to no method found with the given name or the method was found, but it was unable to be accessed. The latter situation should never occur.
      Since:
      10.0.0
    • linkMethod

      public static MethodHandle linkMethod(Class<?> type, HandleUtil.AccessType accessType, HandleUtil.Names methodNames, Class<?> returnType, Class<?>... arguments)
      Obtains a new MethodHandle to the specified method with the given HandleUtil.AccessType.

      The various names will attempt resolution one at a time, and the first MethodHandle that links successfully will be returned.

      Mapping resolution is automatic, meaning that the deobfuscation from one mapping set to the current one is automatically attempted.

      Parameters:
      type - The Class which defines the method to invoke.
      accessType - The type of access that the method handle should attempt.
      methodNames - The various possible obfuscated names of the method that needs to be invoked.
      returnType - The Class that represents the return type of the target method.
      arguments - An array holding various Classes, each representing the type of method parameter.
      Returns:
      A MethodHandle that links to the method specified, if it exists.
      Throws:
      HandleUtil.UnableToLinkHandleException - If linkage fails due to no method found with the given names or a method was found, but it was unable to be accessed. The latter situation should never occur.
      Since:
      10.0.0
    • linkField

      public static VarHandle linkField(Class<?> owner, HandleUtil.AccessType accessType, String fieldName, Class<?> type)
      Obtains a new VarHandle to the specified field with the given HandleUtil.AccessType.

      If more than one name needs to be specified, refer to linkField(Class, AccessType, Names, Class) instead.

      Mapping resolution is automatic, meaning that the deobfuscation from one mapping set to the current one is automatically attempted.

      Parameters:
      owner - The Class which defines the field that needs to be accessed.
      accessType - The type of access that the variable handle should attempt.
      fieldName - The name of the field that needs to be accessed. The name should be obfuscated.
      type - The Class that represents the type of the field that needs to be accessed.
      Returns:
      A VarHandle that links to the field specified, if it exists.
      Throws:
      HandleUtil.UnableToLinkHandleException - If linkage fails due to no field found with the given name or the field was found, but it was unable to be accessed. The latter situation should never occur.
      Since:
      10.0.0
    • linkField

      public static VarHandle linkField(Class<?> owner, HandleUtil.AccessType accessType, HandleUtil.Names fieldNames, Class<?> type)
      Obtains a new VarHandle to the specified field with the given HandleUtil.AccessType.

      The various names will attempt resolution one at a time, and the first VarHandle that links successfully will be returned.

      Mapping resolution is automatic, meaning that the deobfuscation from one mapping set to the current one is automatically attempted.

      Parameters:
      owner - The Class which defines the field that needs to be accessed.
      accessType - The type of access that the variable handle should attempt.
      fieldNames - The various possible obfuscated names of the field that needs to be accessed.
      type - The Class that represents the type of the field that needs to be accessed.
      Returns:
      A VarHandle that links to the field specified, if it exists.
      Throws:
      HandleUtil.UnableToLinkHandleException - If linkage fails due to no field found with the given names or a field was found, but it was unable to be accessed. The latter situation should never occur.
      Since:
      10.0.0
    • invoke

      public static <R> R invoke(HandleUtil.MethodHandleInvoker<R> invoker)
      Attempts invocation of a MethodHandle which will return something, catching any exceptions.

      While the job of invoking the handle is still given to the caller, it is suggested to use this method as it automatically catches and rethrows exceptions as needed. See further in the documentation for more information on the exception contract of this method.

      If the method to invoke returns nothing (i.e. void), use invokeVoid(MethodHandleVoidInvoker) instead.

      Type Parameters:
      R - The type of the value returned by the invocation of the method handle.
      Parameters:
      invoker - The HandleUtil.MethodHandleInvoker responsible for invoking the actual handle.
      Returns:
      The result of the method invocation.
      Throws:
      HandleUtil.FailedInvocationException - If the invocation fails due to a mismatch between the invocation in the invoker and the one expected by the handle/
      RuntimeException - If any other exception occurs. Namely, if the exception is already a subclass of RuntimeException, the exception will be rethrown as is. Otherwise, it will be wrapped in a RuntimeException and rethrown.
      Since:
      9.0.0
    • invokeVoid

      public static void invokeVoid(HandleUtil.MethodHandleVoidInvoker invoker)
      Attempts invocation of a MethodHandle which does not return anything, catching any exceptions.

      While the job of invoking the handle is still given to the caller, it is suggested to use this method as it automatically catches and rethrows exceptions as needed. See further in the documentation for more information on the exception contract of this method.

      If the method to invoke returns something, use invoke(MethodHandleInvoker) instead.

      Parameters:
      invoker - The HandleUtil.MethodHandleVoidInvoker responsible for invoking the actual handle.
      Throws:
      HandleUtil.FailedInvocationException - If the invocation fails due to a mismatch between the invocation in the invoker and the one expected by the handle/
      RuntimeException - If any other exception occurs. Namely, if the exception is already a subclass of RuntimeException, the exception will be rethrown as is. Otherwise, it will be wrapped in a RuntimeException and rethrown.
      Since:
      9.0.0