All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ui4j.bytebuddy.instrumentation.method.bytecode.bind.annotation.Origin Maven / Gradle / Ivy

There is a newer version: 2.1.0
Show newest version
package com.ui4j.bytebuddy.instrumentation.method.bytecode.bind.annotation;

import com.ui4j.bytebuddy.instrumentation.Instrumentation;
import com.ui4j.bytebuddy.instrumentation.attribute.annotation.AnnotationDescription;
import com.ui4j.bytebuddy.instrumentation.method.MethodDescription;
import com.ui4j.bytebuddy.instrumentation.method.bytecode.bind.MethodDelegationBinder;
import com.ui4j.bytebuddy.instrumentation.method.bytecode.stack.assign.Assigner;
import com.ui4j.bytebuddy.instrumentation.method.bytecode.stack.constant.*;
import com.ui4j.bytebuddy.instrumentation.type.TypeDescription;

import java.lang.annotation.*;
import java.lang.reflect.Method;

/**
 * The origin annotation provides some meta information about the source method that is bound to this method where
 * the binding is dependant of the parameter's type:
 * 
    *
  1. If the annotated parameter is of type {@link java.lang.reflect.Method}, the parameter is assigned a reference * to the method it intercepts.
  2. *
  3. If the annotated parameter is of type {@link java.lang.Class}, the parameter is assigned a reference of the * type of the instrumented type.
  4. *
  5. If the annotated parameter is of type {@link java.lang.String}, the parameter is assigned a string describing * a unique method signature of the method it intercepts. This string is a concatenation of: *
    • The method's name
    • *
    • The ( symbol
    • *
    • A list of the method's parameters' * descriptors
    • *
    • The ) symbol
    • *
    • The descriptor of the * method's return type
    * This unique signature allows the unambiguous identification of a particular class's methods while avoid the rather * expensive creation of a {@link java.lang.reflect.Method} instance. *
  6. *
  7. If the annotated type is {@code java.lang.invoke.MethodHandle}, a handle of the intercepted method is injected. * A {@code java.lang.invoke.MethodHandle} is stored in a class's constant pool and does therefore not face the same * runtime performance limitations as a {@link java.lang.reflect.Method} reference. Method handles are only supported * for byte code versions starting from Java 7.
  8. *
  9. If the annotated type is {@code java.lang.invoke.MethodType}, a description of the intercepted method's type * is injected. Method type descriptions are only supported for byte code versions starting from Java 7.
  10. *
* Any other parameter type will cause an {@link java.lang.IllegalStateException}. * * @see com.ui4j.bytebuddy.instrumentation.MethodDelegation * @see TargetMethodAnnotationDrivenBinder */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface Origin { /** * If this value is set to {@code true} and the annotated parameter is a {@link java.lang.reflect.Method} type, * the value that is assigned to this parameter is cached in a {@code static} field. Otherwise, the instance is * looked up from its defining {@link java.lang.Class} on every invocation of the intercepted method. *

 

* {@link java.lang.reflect.Method} look-ups are normally cached by its defining {@link java.lang.Class} what * makes a repeated look-up of a method little expensive. However, because {@link java.lang.reflect.Method} * instances are mutable by their {@link java.lang.reflect.AccessibleObject} contact, any looked-up instance * needs to be copied by its defining {@link java.lang.Class} before exposing it. This can cause performance * deficits when a method is for example called repeatedly in a loop. By enabling the method cache, this * performance penalty can be avoided by caching a single {@link java.lang.reflect.Method} instance for * any intercepted method as a {@code static} field in the instrumented type. * * @return {@code true} if the annotated {@link java.lang.reflect.Method} parameter should be assigned a cached * instance. For any other parameter type, this value is ignored. */ boolean cacheMethod() default false; /** * A binder for binding parameters that are annotated with * {@link com.ui4j.bytebuddy.instrumentation.method.bytecode.bind.annotation.Origin}. * * @see TargetMethodAnnotationDrivenBinder */ static enum Binder implements TargetMethodAnnotationDrivenBinder.ParameterBinder { /** * The singleton instance. */ INSTANCE; @Override public Class getHandledType() { return Origin.class; } @Override public MethodDelegationBinder.ParameterBinding bind(AnnotationDescription.Loadable annotation, int targetParameterIndex, MethodDescription source, MethodDescription target, Instrumentation.Target instrumentationTarget, Assigner assigner) { TypeDescription parameterType = target.getParameterTypes().get(targetParameterIndex); if (parameterType.represents(Class.class)) { return new MethodDelegationBinder.ParameterBinding.Anonymous(ClassConstant.of(instrumentationTarget.getOriginType())); } else if (parameterType.represents(Method.class)) { return new MethodDelegationBinder.ParameterBinding.Anonymous(annotation.loadSilent().cacheMethod() ? MethodConstant.forMethod(source).cached() : MethodConstant.forMethod(source)); } else if (parameterType.represents(String.class)) { return new MethodDelegationBinder.ParameterBinding.Anonymous(new TextConstant(source.getUniqueSignature())); } else if (MethodHandleConstant.isRepresentedBy(parameterType)) { return new MethodDelegationBinder.ParameterBinding.Anonymous(MethodHandleConstant.of(source)); } else if (MethodTypeConstant.isRepresentedBy(parameterType)) { return new MethodDelegationBinder.ParameterBinding.Anonymous(new MethodTypeConstant(source)); } else { throw new IllegalStateException("The " + target + " method's " + targetParameterIndex + " parameter is annotated with a Origin annotation with an argument not representing a Class" + " Method, String, MethodType or MethodHandle type"); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy