@Test public void testGenericMethodWithoutGenericExceptionTypes() throws Exception { DynamicType.Unloaded<?> unloaded = new ByteBuddy() .redefine(GenericMethod.class) .method(named(BAR)) .intercept(FixedValue.nullValue()) .make(); Class<?> type = unloaded .load(ClassLoadingStrategy.BOOTSTRAP_LOADER, ClassLoadingStrategy.Default.WRAPPER) .getLoaded(); MethodDescription createdMethod = new MethodDescription.ForLoadedMethod(type.getDeclaredMethod(BAR, Object.class)); MethodDescription originalMethod = new MethodDescription.ForLoadedMethod( GenericMethod.class.getDeclaredMethod(BAR, Object.class)); assertThat(createdMethod.getTypeVariables(), is(originalMethod.getTypeVariables())); assertThat(createdMethod.getReturnType(), is(originalMethod.getReturnType())); assertThat( createdMethod.getParameters().getOnly().getType(), is(originalMethod.getParameters().getOnly().getType())); assertThat( createdMethod.getExceptionTypes().getOnly(), is(originalMethod.getExceptionTypes().getOnly())); }
@Override public Size apply( MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) { StackManipulation thisReference = MethodVariableAccess.REFERENCE.loadOffset(0); FieldList<?> fieldList = instrumentedType.getDeclaredFields(); StackManipulation[] fieldLoading = new StackManipulation[fieldList.size()]; int index = 0; for (FieldDescription fieldDescription : fieldList) { fieldLoading[index] = new StackManipulation.Compound( thisReference, MethodVariableAccess.forType(fieldDescription.getType().asErasure()) .loadOffset(instrumentedMethod.getParameters().get(index).getOffset()), FieldAccess.forField(fieldDescription).putter()); index++; } StackManipulation.Size stackSize = new StackManipulation.Compound( thisReference, MethodInvocation.invoke(ConstructorCall.INSTANCE.objectTypeDefaultConstructor), new StackManipulation.Compound(fieldLoading), MethodReturn.VOID) .apply(methodVisitor, implementationContext); return new Size(stackSize.getMaximalSize(), instrumentedMethod.getStackSize()); }
/** * 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 methodDescription) { return new MethodHandle( HandleType.of(methodDescription), methodDescription.getDeclaringType().asRawType(), methodDescription.getInternalName(), methodDescription.getReturnType().asRawType(), methodDescription.getParameters().asTypeList().asRawTypes()); }
@Override public AnnotationAppender.Target make( MethodVisitor methodVisitor, MethodDescription methodDescription) { if (parameterIndex >= methodDescription.getParameters().size()) { throw new IllegalArgumentException( "Method " + methodDescription + " has less then " + parameterIndex + " parameters"); } return new AnnotationAppender.Target.OnMethodParameter(methodVisitor, parameterIndex); }
/** * Creates a method attribute appender factory that writes all annotations of a given method, * both the method annotations themselves and all annotations that are defined for every * parameter. * * @param methodDescription The method from which to extract the annotations. * @return A method attribute appender factory for an appender that writes all annotations of * the supplied method. */ public static Factory of(MethodDescription methodDescription) { ParameterList<?> parameters = methodDescription.getParameters(); List<MethodAttributeAppender.Factory> methodAttributeAppenders = new ArrayList<MethodAttributeAppender.Factory>(parameters.size() + 1); methodAttributeAppenders.add(new Explicit(methodDescription.getDeclaredAnnotations())); for (ParameterDescription parameter : parameters) { methodAttributeAppenders.add( new Explicit(parameter.getIndex(), parameter.getDeclaredAnnotations())); } return new Factory.Compound(methodAttributeAppenders); }
/** * 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 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().asRawType(), methodDescription.getParameters().asTypeList().asRawTypes()); }
@Override @Before public void setUp() throws Exception { when(parameterList.asTypeList()).thenReturn(parameterTypes); when(instrumentedType.getSupertype()).thenReturn(superType); when(superType.getDeclaredMethods()) .thenReturn(new MethodList.Explicit(Collections.singletonList(superMethodConstructor))); when(superType.getInternalName()).thenReturn(BAR); when(superMethod.getDeclaringType()).thenReturn(superType); when(superType.getStackSize()).thenReturn(StackSize.ZERO); when(superMethod.getReturnType()).thenReturn(returnType); when(superMethod.getInternalName()).thenReturn(BAZ); when(superMethod.getDescriptor()).thenReturn(FOOBAR); when(superMethod.getParameters()).thenReturn(parameterList); when(superMethodConstructor.isConstructor()).thenReturn(true); when(superMethodConstructor.getParameters()).thenReturn(parameterList); when(superMethodConstructor.getReturnType()).thenReturn(returnType); when(superMethodConstructor.isSpecializableFor(superType)).thenReturn(true); when(superMethodConstructor.getInternalName()).thenReturn(QUXBAZ); when(superMethodConstructor.getDescriptor()).thenReturn(BAZBAR); super.setUp(); }
@Before public void setUp() throws Exception { when(methodDescription.getDeclaringType()).thenReturn(typeDescription); when(methodDescription.getReturnType()).thenReturn(returnType); when(methodDescription.getInternalName()).thenReturn(FOO); when(methodDescription.getDescriptor()).thenReturn(BAZ); when(typeDescription.getInternalName()).thenReturn(BAR); when(typeDescription.getDescriptor()).thenReturn(BAR); when(methodNameTransformer.transform(methodDescription)).thenReturn(QUX); when(otherMethodNameTransformer.transform(methodDescription)).thenReturn(FOO + BAR); when(parameterType.getStackSize()).thenReturn(StackSize.ZERO); ParameterList parameterList = ParameterList.Explicit.latent(methodDescription, Collections.singletonList(parameterType)); when(methodDescription.getParameters()).thenReturn(parameterList); }
/** * Creates a linked hash map of field names to their types where each field represents a parameter * of the method. * * @param methodDescription The method to extract into fields. * @return A map of fields in the order they need to be loaded onto the operand stack for invoking * the original method, including a reference to the instance of the instrumented type that is * invoked if applicable. */ private static LinkedHashMap<String, TypeDescription> extractFields( MethodDescription methodDescription) { ParameterList<?> parameters = methodDescription.getParameters(); LinkedHashMap<String, TypeDescription> typeDescriptions = new LinkedHashMap<String, TypeDescription>( (methodDescription.isStatic() ? 0 : 1) + parameters.size()); int currentIndex = 0; if (!methodDescription.isStatic()) { typeDescriptions.put( fieldName(currentIndex++), methodDescription.getDeclaringType().asErasure()); } for (ParameterDescription parameterDescription : parameters) { typeDescriptions.put(fieldName(currentIndex++), parameterDescription.getType().asErasure()); } return typeDescriptions; }
@Override public void apply( MethodVisitor methodVisitor, MethodDescription methodDescription, AnnotationValueFilter annotationValueFilter) { AnnotationAppender annotationAppender = new AnnotationAppender.Default(new AnnotationAppender.Target.OnMethod(methodVisitor)); annotationAppender = methodDescription .getReturnType() .accept( AnnotationAppender.ForTypeAnnotations.ofMethodReturnType( annotationAppender, annotationValueFilter)); annotationAppender = AnnotationAppender.ForTypeAnnotations.ofTypeVariable( annotationAppender, annotationValueFilter, AnnotationAppender.ForTypeAnnotations.VARIABLE_ON_INVOKEABLE, methodDescription.getTypeVariables()); for (AnnotationDescription annotation : methodDescription.getDeclaredAnnotations()) { annotationAppender = annotationAppender.append(annotation, annotationValueFilter); } for (ParameterDescription parameterDescription : methodDescription.getParameters()) { AnnotationAppender parameterAppender = new AnnotationAppender.Default( new AnnotationAppender.Target.OnMethodParameter( methodVisitor, parameterDescription.getIndex())); parameterAppender = parameterDescription .getType() .accept( AnnotationAppender.ForTypeAnnotations.ofMethodParameterType( parameterAppender, annotationValueFilter, parameterDescription.getIndex())); for (AnnotationDescription annotation : parameterDescription.getDeclaredAnnotations()) { parameterAppender = parameterAppender.append(annotation, annotationValueFilter); } } int exceptionTypeIndex = 0; for (TypeDescription.Generic exceptionType : methodDescription.getExceptionTypes()) { annotationAppender = exceptionType.accept( AnnotationAppender.ForTypeAnnotations.ofExceptionType( annotationAppender, annotationValueFilter, exceptionTypeIndex++)); } }
private void checkMethodSignature(MethodDescription instrumentedMethod) { final String errMessage = "%s must have signature `void copy(java.lang.Object, long)`"; Preconditions.checkArgument( instrumentedMethod.getReturnType().represents(void.class), errMessage, instrumentedMethod); ParameterList parameters = instrumentedMethod.getParameters(); Preconditions.checkArgument(parameters.size() == 2, errMessage, instrumentedMethod); Preconditions.checkArgument( parameters.get(0).getTypeDescription().represents(Object.class), errMessage, instrumentedMethod); Preconditions.checkArgument( parameters.get(1).getTypeDescription().represents(long.class), errMessage, instrumentedMethod); }
/** * 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().asRawType(), methodDescription.getParameters().asTypeList().asRawTypes()); }