@Override
 public Size apply(
     MethodVisitor methodVisitor,
     Context implementationContext,
     MethodDescription instrumentedMethod) {
   StackManipulation thisReference =
       MethodVariableAccess.forType(instrumentedType).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, FieldAccess.forField(fieldDescription).getter());
   }
   StackManipulation.Size stackSize =
       new StackManipulation.Compound(
               new StackManipulation.Compound(fieldLoading),
               MethodInvocation.invoke(accessorMethod),
               assigner.assign(
                   accessorMethod.getReturnType().asErasure(),
                   instrumentedMethod.getReturnType().asErasure(),
                   Assigner.Typing.DYNAMIC),
               MethodReturn.returning(instrumentedMethod.getReturnType().asErasure()))
           .apply(methodVisitor, implementationContext);
   return new Size(stackSize.getMaximalSize(), instrumentedMethod.getStackSize());
 }
 @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());
 }
  public Size apply(
      MethodVisitor methodVisitor,
      Implementation.Context implementationContext,
      MethodDescription instrumentedMethod) {

    checkMethodSignature(instrumentedMethod);

    try {
      StackManipulation stack = buildStack();
      StackManipulation.Size finalStackSize = stack.apply(methodVisitor, implementationContext);

      return new Size(
          finalStackSize.getMaximalSize(),
          instrumentedMethod.getStackSize() + 2); // 2 stack slots for a single local variable

    } catch (NoSuchMethodException | NoSuchFieldException e) {
      throw new RuntimeException(e);
    }
  }
 /**
  * Blueprint method that for applying the actual implementation.
  *
  * @param methodVisitor The method visitor to which the implementation is applied to.
  * @param implementationContext The implementation context for the given implementation.
  * @param instrumentedMethod The instrumented method that is target of the implementation.
  * @param fixedValueType A description of the type of the fixed value that is loaded by the {@code
  *     valueLoadingInstruction}.
  * @param valueLoadingInstruction A stack manipulation that represents the loading of the fixed
  *     value onto the operand stack.
  * @return A representation of the stack and variable array sized that are required for this
  *     implementation.
  */
 protected ByteCodeAppender.Size apply(
     MethodVisitor methodVisitor,
     Context implementationContext,
     MethodDescription instrumentedMethod,
     TypeDescription.Generic fixedValueType,
     StackManipulation valueLoadingInstruction) {
   StackManipulation assignment =
       assigner.assign(fixedValueType, instrumentedMethod.getReturnType(), typing);
   if (!assignment.isValid()) {
     throw new IllegalArgumentException(
         "Cannot return value of type " + fixedValueType + " for " + instrumentedMethod);
   }
   StackManipulation.Size stackSize =
       new StackManipulation.Compound(
               valueLoadingInstruction,
               assignment,
               MethodReturn.returning(instrumentedMethod.getReturnType().asErasure()))
           .apply(methodVisitor, implementationContext);
   return new ByteCodeAppender.Size(stackSize.getMaximalSize(), instrumentedMethod.getStackSize());
 }