@Override protected int getBaseModifiers() { return methodDescription.isStatic() ? Opcodes.ACC_STATIC : EMPTY_MASK; }
/** * {@inheritDoc} */ public List<ArgumentLoader> resolve(MethodDescription instrumentedMethod, MethodDescription invokedMethod) { if (instrumentedMethod.isStatic()) { throw new IllegalStateException(instrumentedMethod + " is static and cannot supply an invoker instance"); } return Collections.<ArgumentLoader>singletonList(this); }
/** * {@inheritDoc} */ public StackManipulation prepare(MethodDescription instrumentedMethod) { if (instrumentedMethod.isStatic() && !methodDescription.isStatic()) { throw new IllegalStateException("Cannot invoke " + methodDescription + " from " + instrumentedMethod); } return new StackManipulation.Compound(methodDescription.isStatic() ? StackManipulation.Trivial.INSTANCE : MethodVariableAccess.loadThis(), MethodInvocation.invoke(methodDescription)); }
@Override protected int copy(TypeDescription instrumentedType, MethodDescription instrumentedMethod, MethodDescription methodDescription, Object[] localVariable, Object[] translated) { int length = instrumentedMethod.getParameters().size() + (instrumentedMethod.isStatic() ? 0 : 1); System.arraycopy(localVariable, 0, translated, 0, length); return length; }
/** * Prepends a reference to the {@code this} instance to the loaded parameters if the represented method is non-static. * * @return A stack manipulation that loads all method parameters onto the operand stack while additionally loading a reference * to {@code this} if the represented is non-static. Any potential parameter transformation is preserved. */ public StackManipulation prependThisReference() { return methodDescription.isStatic() ? this : new Compound(MethodVariableAccess.loadThis(), this); }
/** * {@inheritDoc} */ public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) { if (instrumentedMethod.isStatic()) { throw new IllegalStateException("Cannot get this instance from static method: " + instrumentedMethod); } else if (!instrumentedType.isAssignableTo(typeDescription)) { throw new IllegalStateException(instrumentedType + " is not assignable to " + instrumentedType); } return new Resolved.Simple(MethodVariableAccess.loadThis(), typeDescription); }
/** * {@inheritDoc} */ public int variable(int index) { return (instrumentedMethod.isStatic() ? 0 : 1) + instrumentedMethod.getParameters().size() + (exitType.represents(void.class) ? 0 : 1) + namedTypes.size() + (enterType.represents(void.class) ? 0 : 1) + index; }
/** * {@inheritDoc} */ public int variable(int index) { return index < (instrumentedMethod.isStatic() ? 0 : 1) + instrumentedMethod.getParameters().size() ? index : index + (exitType.represents(void.class) ? 0 : 1) + StackSize.of(namedTypes.values()) + (enterType.represents(void.class) ? 0 : 1); }
/** * {@inheritDoc} */ public StackManipulation prepare(MethodDescription instrumentedMethod) { if (instrumentedMethod.isStatic() && !fieldDescription.isStatic()) { throw new IllegalStateException("Cannot read " + fieldDescription + " from " + instrumentedMethod); } return new StackManipulation.Compound(fieldDescription.isStatic() ? StackManipulation.Trivial.INSTANCE : MethodVariableAccess.loadThis(), FieldAccess.forField(fieldDescription).read()); }
/** * 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) { LinkedHashMap<String, TypeDescription> typeDescriptions = new LinkedHashMap<String, TypeDescription>(); int currentIndex = 0; if (!methodDescription.isStatic()) { typeDescriptions.put(fieldName(currentIndex++), methodDescription.getDeclaringType().asErasure()); } for (ParameterDescription parameterDescription : methodDescription.getParameters()) { typeDescriptions.put(fieldName(currentIndex++), parameterDescription.getType().asErasure()); } return typeDescriptions; }
/** * {@inheritDoc} */ public Size apply(MethodVisitor methodVisitor, Context implementationContext, MethodDescription instrumentedMethod) { if (instrumentedMethod.isStatic() || !instrumentedType.isAssignableTo(instrumentedMethod.getReturnType().asErasure())) { throw new IllegalStateException("Cannot return 'this' from " + instrumentedMethod); } return new ByteCodeAppender.Simple( MethodVariableAccess.loadThis(), MethodReturn.REFERENCE ).apply(methodVisitor, implementationContext, instrumentedMethod); } }
@Override protected int copy(TypeDescription instrumentedType, MethodDescription instrumentedMethod, MethodDescription methodDescription, Object[] localVariable, Object[] translated) { int index = 0; if (!instrumentedMethod.isStatic()) { translated[index++] = toFrame(instrumentedType); } for (TypeDescription typeDescription : instrumentedMethod.getParameters().asTypeList().asErasures()) { translated[index++] = toFrame(typeDescription); } return index; }
@Override protected int copy(TypeDescription instrumentedType, MethodDescription instrumentedMethod, MethodDescription methodDescription, Object[] localVariable, Object[] translated) { int index = 0; if (!instrumentedMethod.isStatic()) { translated[index++] = instrumentedMethod.isConstructor() ? Opcodes.UNINITIALIZED_THIS : toFrame(instrumentedType); } for (TypeDescription typeDescription : instrumentedMethod.getParameters().asTypeList().asErasures()) { translated[index++] = toFrame(typeDescription); } return index; }
/** * {@inheritDoc} */ public StackManipulation toStackManipulation(MethodDescription invokedMethod, Assigner assigner, Assigner.Typing typing) { if (!invokedMethod.isInvokableOn(fieldDescription.getType().asErasure())) { throw new IllegalStateException("Cannot invoke " + invokedMethod + " on " + fieldDescription); } StackManipulation stackManipulation = assigner.assign(fieldDescription.getType(), invokedMethod.getDeclaringType().asGenericType(), typing); if (!stackManipulation.isValid()) { throw new IllegalStateException("Cannot invoke " + invokedMethod + " on " + fieldDescription); } return new StackManipulation.Compound(invokedMethod.isStatic() || fieldDescription.isStatic() ? StackManipulation.Trivial.INSTANCE : MethodVariableAccess.loadThis(), FieldAccess.forField(fieldDescription).read(), stackManipulation); }
/** * Creates a special method invocation for the given method. * * @param resolvedMethod The rebased method to be invoked. * @param instrumentedType The instrumented type on which the method is to be invoked if it is non-static. * @param additionalArguments Any additional arguments that are to be provided to the rebased method. * @return A special method invocation of the rebased method. */ protected static Implementation.SpecialMethodInvocation of(MethodDescription resolvedMethod, TypeDescription instrumentedType, StackManipulation additionalArguments) { StackManipulation stackManipulation = resolvedMethod.isStatic() ? MethodInvocation.invoke(resolvedMethod) : MethodInvocation.invoke(resolvedMethod).special(instrumentedType); return stackManipulation.isValid() ? new RebasedMethodInvocation(resolvedMethod, instrumentedType, new Compound(additionalArguments, stackManipulation)) : Illegal.INSTANCE; }
/** * {@inheritDoc} */ public DynamicType make(String auxiliaryTypeName, ClassFileVersion classFileVersion, MethodAccessorFactory methodAccessorFactory) { return new ByteBuddy(classFileVersion) .with(TypeValidation.DISABLED) .subclass(morphingType, ConstructorStrategy.Default.NO_CONSTRUCTORS) .name(auxiliaryTypeName) .modifiers(DEFAULT_TYPE_MODIFIER) .implement(serializableProxy ? new Class<?>[]{Serializable.class} : new Class<?>[0]) .defineConstructor().withParameters(specialMethodInvocation.getMethodDescription().isStatic() ? Collections.<TypeDescription>emptyList() : Collections.singletonList(instrumentedType)) .intercept(specialMethodInvocation.getMethodDescription().isStatic() ? StaticFieldConstructor.INSTANCE : new InstanceFieldConstructor(instrumentedType)) .method(ElementMatchers.<MethodDescription>isAbstract().and(isDeclaredBy(morphingType))) .intercept(new MethodCall(methodAccessorFactory.registerAccessorFor(specialMethodInvocation, MethodAccessorFactory.AccessType.DEFAULT), assigner)) .make(); }
/** * {@inheritDoc} */ public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) { FieldLocator.Resolution resolution = fieldLocatorFactory.make(instrumentedType).locate(fieldName); if (!resolution.isResolved()) { throw new IllegalStateException("Cannot find a field " + fieldName + " for " + instrumentedType); } else if (!resolution.getField().isStatic() && instrumentedMethod.isStatic()) { throw new IllegalStateException("Cannot access non-static " + resolution.getField() + " from " + instrumentedMethod); } return doResolve(new StackManipulation.Compound(resolution.getField().isStatic() ? StackManipulation.Trivial.INSTANCE : MethodVariableAccess.loadThis(), FieldAccess.forField(resolution.getField()).read()), resolution.getField().getType(), assigner, typing); }
/** * {@inheritDoc} */ public int getOffset() { TypeList parameterType = getDeclaringMethod().getParameters().asTypeList().asErasures(); int offset = getDeclaringMethod().isStatic() ? StackSize.ZERO.getSize() : StackSize.SINGLE.getSize(); for (int i = 0; i < getIndex(); i++) { offset += parameterType.get(i).getStackSize().getSize(); } return offset; }
/** * {@inheritDoc} */ public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) { TypeDescription forwardingType = implementationContext.register(this); return new Compound( TypeCreation.of(forwardingType), Duplication.SINGLE, specialMethodInvocation.getMethodDescription().isStatic() ? Trivial.INSTANCE : MethodVariableAccess.loadThis(), MethodInvocation.invoke(forwardingType.getDeclaredMethods().filter(isConstructor()).getOnly()) ).apply(methodVisitor, implementationContext); }
/** * {@inheritDoc} */ public Resolved resolve(TypeDescription instrumentedType, MethodDescription instrumentedMethod, Assigner assigner, Assigner.Typing typing) { return new Resolved.Simple(MethodVariableAccess.allArgumentsOf(instrumentedMethod).prependThisReference(), instrumentedMethod.isStatic() ? instrumentedMethod.getParameters().asTypeList().asErasures() : CompoundList.of(instrumentedMethod.getDeclaringType().asErasure(), instrumentedMethod.getParameters().asTypeList().asErasures())); }