@Override
    public void generateCode(String propertyName, MethodVisitor mv, CodeFlow cf) {
      boolean isStatic = Modifier.isStatic(this.member.getModifiers());
      String descriptor = cf.lastDescriptor();
      String classDesc = this.member.getDeclaringClass().getName().replace('.', '/');

      if (!isStatic) {
        if (descriptor == null) {
          cf.loadTarget(mv);
        }
        if (descriptor == null || !classDesc.equals(descriptor.substring(1))) {
          mv.visitTypeInsn(CHECKCAST, classDesc);
        }
      } else {
        if (descriptor != null) {
          // A static field/method call will not consume what is on the stack,
          // it needs to be popped off.
          mv.visitInsn(POP);
        }
      }

      if (this.member instanceof Method) {
        mv.visitMethodInsn(
            (isStatic ? INVOKESTATIC : INVOKEVIRTUAL),
            classDesc,
            this.member.getName(),
            CodeFlow.createSignatureDescriptor((Method) this.member),
            false);
      } else {
        mv.visitFieldInsn(
            (isStatic ? GETSTATIC : GETFIELD),
            classDesc,
            this.member.getName(),
            CodeFlow.toJvmDescriptor(((Field) this.member).getType()));
      }
    }
  byte[] generateClassBytecode(
      String className, Class<? extends DataSerializable> clazz, int classId) {
    ClassWriter cw = new ClassWriter(0);

    cw.visit(
        V1_5,
        ACC_PUBLIC + ACC_SUPER,
        className,
        null,
        INSTANTIATOR_NAME,
        new String[] {SERIALIZABLE_NAME});
    FieldVisitor fv =
        cw.visitField(
            ACC_PRIVATE + ACC_FINAL + ACC_STATIC, CLASS_FIELD_NAME, CLASS_DESCRIPTOR, null, null);
    fv.visitEnd();
    fv =
        cw.visitField(
            ACC_PRIVATE + ACC_FINAL + ACC_STATIC,
            ID_FIELD_NAME,
            Type.INT_TYPE.getDescriptor(),
            null,
            Integer.valueOf(classId));
    fv.visitEnd();

    String voidNoArgMethodDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {});

    // field class loading
    MethodVisitor mv = cw.visitMethod(ACC_STATIC, CINIT, voidNoArgMethodDescriptor, null, null);
    mv.visitCode();
    mv.visitLdcInsn(Type.getType(clazz));
    mv.visitFieldInsn(PUTSTATIC, className, CLASS_FIELD_NAME, CLASS_DESCRIPTOR);
    mv.visitInsn(RETURN);
    mv.visitMaxs(1, 0);
    mv.visitEnd();

    String voidArgClassAndIntDescriptor =
        Type.getMethodDescriptor(
            Type.VOID_TYPE, new Type[] {Type.getType(Class.class), Type.INT_TYPE});

    // default constructor
    mv = cw.visitMethod(ACC_PUBLIC, INIT, voidNoArgMethodDescriptor, null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETSTATIC, className, CLASS_FIELD_NAME, CLASS_DESCRIPTOR);
    mv.visitFieldInsn(GETSTATIC, className, ID_FIELD_NAME, Type.INT_TYPE.getDescriptor());
    mv.visitMethodInsn(INVOKESPECIAL, className, INIT, voidArgClassAndIntDescriptor);
    mv.visitInsn(RETURN);
    mv.visitMaxs(3, 1);
    mv.visitEnd();

    // two-arg constructor
    mv = cw.visitMethod(ACC_PUBLIC, INIT, voidArgClassAndIntDescriptor, null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ALOAD, 1);
    mv.visitVarInsn(ILOAD, 2);
    mv.visitMethodInsn(INVOKESPECIAL, INSTANTIATOR_NAME, INIT, voidArgClassAndIntDescriptor);
    mv.visitInsn(RETURN);
    mv.visitMaxs(3, 3);
    mv.visitEnd();

    Type customClassType = Type.getType(clazz);
    String customTypeNoArgDesc = Type.getMethodDescriptor(customClassType, new Type[] {});

    // newInstance overloaded method
    mv = cw.visitMethod(ACC_PUBLIC, NEW_INSTANCE, customTypeNoArgDesc, null, null);

    mv.visitCode();
    mv.visitTypeInsn(NEW, customClassType.getInternalName());
    mv.visitInsn(DUP);
    mv.visitMethodInsn(
        INVOKESPECIAL, customClassType.getInternalName(), INIT, voidNoArgMethodDescriptor);
    mv.visitInsn(ARETURN);
    mv.visitMaxs(2, 1);
    mv.visitEnd();

    // plus original method signature
    mv =
        cw.visitMethod(
            ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, NEW_INSTANCE, NEW_INSTANCE_DESC, null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKEVIRTUAL, className, NEW_INSTANCE, customTypeNoArgDesc);
    mv.visitInsn(ARETURN);
    mv.visitMaxs(1, 1);
    mv.visitEnd();

    // end class generation
    cw.visitEnd();

    return cw.toByteArray();
  }