@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(); }