void processMethods() throws IOException {

    int methodsCount = is.readUnsignedShort();
    os.writeShort(methodsCount);

    for (int i = 0; i < methodsCount; i++) {
      MethodInfo methodInfo = readMethod();
      if (methodInfo.getInterceptorClass() != null) {
        injectCode(methodInfo);
      }
      methods.add(methodInfo);
    }

    writeMethods();
  }
 private void writeMethods() throws IOException {
   for (MethodInfo method : methods) {
     os.writeShort(method.getAccessFlags());
     os.writeShort(method.getNameIndex());
     os.writeShort(method.getDescriptorIndex());
     os.writeShort(method.getAttributes().length);
     attributeFacility.writeAttributes(method.getAttributes());
   }
 }
  private void injectCode(MethodInfo methodInfo) throws IOException {
    if (methodInfo.getCode() == null) {
      return;
    }

    InterceptorConstants interceptorConstants =
        getOrInsertInterceptorConstants(methodInfo.getInterceptorClass());

    fixupSignature(methodInfo.getSignature());

    Map<String, Integer> wrapperMethods =
        getOrInsertPrimitiveWrapperMethods(methodInfo.getSignature());

    ByteArrayOutputStream codeToInject = new ByteArrayOutputStream();
    InstructionsFacility instructionsFacility =
        new InstructionsFacility(
            new DataOutputStream(codeToInject),
            methodInfo.getSignature(),
            interceptorConstants,
            wrapperMethods);

    instructionsFacility.generateInterceptorInstantiationCode();

    instructionsFacility.generateInterceptorMethodParametersCode(getObjectClassIndex());

    instructionsFacility.generateObjectArrayFillingCode();

    instructionsFacility.generateInterceptorInvocationCode(
        interceptorConstants.getInterceptorMethod());

    Code code = methodInfo.getCode();

    int originalStackSize = code.getMaxStack();
    code.setMaxStack(Math.max(originalStackSize, instructionsFacility.getStackSizeNeeded()));

    code.setInjected(codeToInject.toByteArray());
    code.refresh();
  }
  private MethodInfo readMethod() throws IOException {
    MethodInfo methodInfo = new MethodInfo();

    methodInfo.setAccessFlags(is.readUnsignedShort());
    methodInfo.setNameIndex(is.readUnsignedShort());
    methodInfo.setDescriptorIndex(is.readUnsignedShort());
    int attributesCount = is.readUnsignedShort();

    methodInfo.setAttributes(new AbstractAttribute[attributesCount]);

    for (int i = 0; i < attributesCount; i++) {
      AbstractAttribute attribute = attributeFacility.readAttribute();
      if (isInterceptorAnnotation(attribute)) {
        methodInfo.setInterceptorClass(
            ((RuntimeInvisibleAnnotations) attribute).getInterceptorClass());
      }
      methodInfo.getAttributes()[i] = attribute;
      if (attribute.getClass() == Code.class) {
        methodInfo.setCode((Code) attribute);
      }
    }

    methodInfo.setSignature(getMethodSignature(methodInfo));
    methodInfo.setMethodName(constantPool.getUtf8(methodInfo.getNameIndex()).getString());

    return methodInfo;
  }