Search in sources :

Example 1 with ClassWriter

use of com.alibaba.fastjson.asm.ClassWriter in project fastjson by alibaba.

the class ASMDeserializerFactory method createJavaBeanDeserializer.

public ObjectDeserializer createJavaBeanDeserializer(ParserConfig config, JavaBeanInfo beanInfo) throws Exception {
    Class<?> clazz = beanInfo.clazz;
    if (clazz.isPrimitive()) {
        throw new IllegalArgumentException("not support type :" + clazz.getName());
    }
    String className = "FastjsonASMDeserializer_" + seed.incrementAndGet() + "_" + clazz.getSimpleName();
    String packageName = ASMDeserializerFactory.class.getPackage().getName();
    String classNameType = packageName.replace('.', '/') + "/" + className;
    String classNameFull = packageName + "." + className;
    ClassWriter cw = new ClassWriter();
    cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, classNameType, type(JavaBeanDeserializer.class), null);
    _init(cw, new Context(classNameType, config, beanInfo, 3));
    _createInstance(cw, new Context(classNameType, config, beanInfo, 3));
    _deserialze(cw, new Context(classNameType, config, beanInfo, 5));
    _deserialzeArrayMapping(cw, new Context(classNameType, config, beanInfo, 4));
    byte[] code = cw.toByteArray();
    Class<?> exampleClass = defineClassPublic(classNameFull, code, 0, code.length);
    Constructor<?> constructor = exampleClass.getConstructor(ParserConfig.class, JavaBeanInfo.class);
    Object instance = constructor.newInstance(config, beanInfo);
    return (ObjectDeserializer) instance;
}
Also used : ParseContext(com.alibaba.fastjson.parser.ParseContext) ClassWriter(com.alibaba.fastjson.asm.ClassWriter)

Example 2 with ClassWriter

use of com.alibaba.fastjson.asm.ClassWriter in project fastjson by alibaba.

the class TestASM method test_1.

public void test_1() throws Exception {
    ClassWriter cw = new ClassWriter();
    cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, "DateSerializer", "java/lang/Object", new String[] { "com/alibaba/fastjson/serializer/ObjectSerializer" });
    MethodVisitor mw = new MethodWriter(cw, ACC_PUBLIC, "<init>", "()V", null, null);
    mw.visitVarInsn(ALOAD, 0);
    mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
    mw.visitInsn(RETURN);
    mw.visitMaxs(1, 1);
    mw.visitEnd();
    mw = new MethodWriter(cw, ACC_PUBLIC, "write", "(Lcom/alibaba/fastjson/serializer/JSONSerializer;Ljava/lang/Object;)V", null, new String[] { "java/io/IOException" });
    // serializer
    mw.visitVarInsn(ALOAD, 1);
    mw.visitMethodInsn(INVOKEVIRTUAL, "com/alibaba/fastjson/serializer/JSONSerializer", "getWriter", "()Lcom/alibaba/fastjson/serializer/SerializeWriter;");
    // out
    mw.visitVarInsn(ASTORE, 3);
    // obj
    mw.visitVarInsn(ALOAD, 2);
    // serializer
    mw.visitTypeInsn(CHECKCAST, getCastType(Entity.class));
    // obj
    mw.visitVarInsn(ASTORE, 4);
    // out
    mw.visitVarInsn(ALOAD, 3);
    mw.visitLdcInsn("{");
    mw.visitMethodInsn(INVOKEVIRTUAL, getCastType(SerializeWriter.class), "writeString", "(Ljava/lang/String;)V");
    // out
    mw.visitVarInsn(ALOAD, 3);
    mw.visitLdcInsn("\"id\":");
    mw.visitMethodInsn(INVOKEVIRTUAL, getCastType(SerializeWriter.class), "write", "(Ljava/lang/String;)V");
    // out
    mw.visitVarInsn(ALOAD, 3);
    // entity
    mw.visitVarInsn(ALOAD, 4);
    mw.visitMethodInsn(INVOKEVIRTUAL, getCastType(Entity.class), "getId", "()I");
    mw.visitMethodInsn(INVOKEVIRTUAL, getCastType(SerializeWriter.class), "writeInt", "(I)V");
    // out
    mw.visitVarInsn(ALOAD, 3);
    mw.visitLdcInsn("\",name\":");
    mw.visitMethodInsn(INVOKEVIRTUAL, getCastType(SerializeWriter.class), "write", "(Ljava/lang/String;)V");
    // out
    mw.visitVarInsn(ALOAD, 3);
    // entity
    mw.visitVarInsn(ALOAD, 4);
    mw.visitMethodInsn(INVOKEVIRTUAL, getCastType(Entity.class), "getName", "()Ljava/lang/String;");
    mw.visitMethodInsn(INVOKEVIRTUAL, getCastType(SerializeWriter.class), "writeString", "(Ljava/lang/String;)V");
    mw.visitInsn(RETURN);
    mw.visitMaxs(3, 16);
    mw.visitEnd();
    byte[] code = cw.toByteArray();
    FileOutputStream fos = new FileOutputStream("Example.class");
    fos.write(code);
    fos.close();
    MyClassLoader loader = new MyClassLoader(com.alibaba.fastjson.serializer.ObjectSerializer.class.getClassLoader());
    Class<?> exampleClass = loader.defineClassF("DateSerializer", code, 0, code.length);
    Method[] methods = exampleClass.getMethods();
    Object instance = exampleClass.newInstance();
    SerializeWriter out = new SerializeWriter();
    JSONSerializer serializer = new JSONSerializer(out);
    Entity obj = new Entity();
    methods[0].invoke(instance, serializer, obj);
    System.out.println(out.toString());
}
Also used : MethodWriter(com.alibaba.fastjson.asm.MethodWriter) Method(java.lang.reflect.Method) ClassWriter(com.alibaba.fastjson.asm.ClassWriter) MethodVisitor(com.alibaba.fastjson.asm.MethodVisitor) SerializeWriter(com.alibaba.fastjson.serializer.SerializeWriter) FileOutputStream(java.io.FileOutputStream) JSONSerializer(com.alibaba.fastjson.serializer.JSONSerializer)

Example 3 with ClassWriter

use of com.alibaba.fastjson.asm.ClassWriter in project fastjson by alibaba.

the class ASMSerializerFactory method createJavaBeanSerializer.

public JavaBeanSerializer createJavaBeanSerializer(SerializeBeanInfo beanInfo) throws Exception {
    Class<?> clazz = beanInfo.beanType;
    if (clazz.isPrimitive()) {
        throw new JSONException("unsupportd class " + clazz.getName());
    }
    JSONType jsonType = clazz.getAnnotation(JSONType.class);
    FieldInfo[] unsortedGetters = beanInfo.fields;
    ;
    for (FieldInfo fieldInfo : unsortedGetters) {
        if (//
        fieldInfo.field == null && //
        fieldInfo.method != null && fieldInfo.method.getDeclaringClass().isInterface()) {
            return new JavaBeanSerializer(clazz);
        }
    }
    FieldInfo[] getters = beanInfo.sortedFields;
    boolean nativeSorted = beanInfo.sortedFields == beanInfo.fields;
    if (getters.length > 256) {
        return new JavaBeanSerializer(clazz);
    }
    for (FieldInfo getter : getters) {
        if (!ASMUtils.checkName(getter.getMember().getName())) {
            return new JavaBeanSerializer(clazz);
        }
    }
    String className = "ASMSerializer_" + seed.incrementAndGet() + "_" + clazz.getSimpleName();
    String packageName = ASMSerializerFactory.class.getPackage().getName();
    String classNameType = packageName.replace('.', '/') + "/" + className;
    String classNameFull = packageName + "." + className;
    ClassWriter cw = new ClassWriter();
    //
    cw.visit(//
    V1_5, //
    ACC_PUBLIC + ACC_SUPER, //
    classNameType, //
    JavaBeanSerializer, //
    new String[] { ObjectSerializer });
    for (FieldInfo fieldInfo : getters) {
        if (//
        fieldInfo.fieldClass.isPrimitive() || //|| fieldInfo.fieldClass.isEnum() //
        fieldInfo.fieldClass == String.class) {
            continue;
        }
        //
        new FieldWriter(cw, ACC_PUBLIC, fieldInfo.name + "_asm_fieldType", "Ljava/lang/reflect/Type;").visitEnd();
        if (List.class.isAssignableFrom(fieldInfo.fieldClass)) {
            new FieldWriter(cw, ACC_PUBLIC, fieldInfo.name + "_asm_list_item_ser_", //
            ObjectSerializer_desc).visitEnd();
        }
        //
        new FieldWriter(cw, ACC_PUBLIC, fieldInfo.name + "_asm_ser_", ObjectSerializer_desc).visitEnd();
    }
    MethodVisitor mw = new MethodWriter(cw, ACC_PUBLIC, "<init>", "(" + desc(SerializeBeanInfo.class) + ")V", null, null);
    mw.visitVarInsn(ALOAD, 0);
    mw.visitVarInsn(ALOAD, 1);
    mw.visitMethodInsn(INVOKESPECIAL, JavaBeanSerializer, "<init>", "(" + desc(SerializeBeanInfo.class) + ")V");
    // init _asm_fieldType
    for (int i = 0; i < getters.length; ++i) {
        FieldInfo fieldInfo = getters[i];
        if (//
        fieldInfo.fieldClass.isPrimitive() || //                || fieldInfo.fieldClass.isEnum() //
        fieldInfo.fieldClass == String.class) {
            continue;
        }
        mw.visitVarInsn(ALOAD, 0);
        if (fieldInfo.method != null) {
            mw.visitLdcInsn(com.alibaba.fastjson.asm.Type.getType(desc(fieldInfo.declaringClass)));
            mw.visitLdcInsn(fieldInfo.method.getName());
            mw.visitMethodInsn(INVOKESTATIC, type(ASMUtils.class), "getMethodType", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/reflect/Type;");
        } else {
            mw.visitVarInsn(ALOAD, 0);
            mw.visitLdcInsn(i);
            mw.visitMethodInsn(INVOKESPECIAL, JavaBeanSerializer, "getFieldType", "(I)Ljava/lang/reflect/Type;");
        }
        mw.visitFieldInsn(PUTFIELD, classNameType, fieldInfo.name + "_asm_fieldType", "Ljava/lang/reflect/Type;");
    }
    mw.visitInsn(RETURN);
    mw.visitMaxs(4, 4);
    mw.visitEnd();
    boolean DisableCircularReferenceDetect = false;
    if (jsonType != null) {
        for (SerializerFeature featrues : jsonType.serialzeFeatures()) {
            if (featrues == SerializerFeature.DisableCircularReferenceDetect) {
                DisableCircularReferenceDetect = true;
                break;
            }
        }
    }
    // 2 writeNonContext
    for (int i = 0; i < 3; ++i) {
        String methodName;
        boolean nonContext = DisableCircularReferenceDetect;
        boolean writeDirect = false;
        if (i == 0) {
            methodName = "write";
            writeDirect = true;
        } else if (i == 1) {
            methodName = "writeNormal";
        } else {
            writeDirect = true;
            nonContext = true;
            methodName = "writeDirectNonContext";
        }
        Context context = new Context(getters, beanInfo, classNameType, writeDirect, nonContext);
        mw = new //
        MethodWriter(//
        cw, //
        ACC_PUBLIC, //
        methodName, "(L" + JSONSerializer + //
        ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V", //
        null, //
        new String[] { "java/io/IOException" });
        {
            Label endIf_ = new Label();
            mw.visitVarInsn(ALOAD, Context.obj);
            //serializer.writeNull();
            mw.visitJumpInsn(IFNONNULL, endIf_);
            mw.visitVarInsn(ALOAD, Context.serializer);
            mw.visitMethodInsn(INVOKEVIRTUAL, JSONSerializer, "writeNull", "()V");
            mw.visitInsn(RETURN);
            mw.visitLabel(endIf_);
        }
        mw.visitVarInsn(ALOAD, Context.serializer);
        mw.visitFieldInsn(GETFIELD, JSONSerializer, "out", SerializeWriter_desc);
        mw.visitVarInsn(ASTORE, context.var("out"));
        if (//
        (!nativeSorted) && !context.writeDirect) {
            if (jsonType == null || jsonType.alphabetic()) {
                Label _else = new Label();
                mw.visitVarInsn(ALOAD, context.var("out"));
                mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "isSortField", "()Z");
                mw.visitJumpInsn(IFNE, _else);
                mw.visitVarInsn(ALOAD, 0);
                mw.visitVarInsn(ALOAD, 1);
                mw.visitVarInsn(ALOAD, 2);
                mw.visitVarInsn(ALOAD, 3);
                mw.visitVarInsn(ALOAD, 4);
                mw.visitVarInsn(ILOAD, 5);
                mw.visitMethodInsn(INVOKEVIRTUAL, classNameType, "writeUnsorted", "(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
                mw.visitInsn(RETURN);
                mw.visitLabel(_else);
            }
        }
        // isWriteDoubleQuoteDirect
        if (context.writeDirect && !nonContext) {
            Label _direct = new Label();
            Label _directElse = new Label();
            mw.visitVarInsn(ALOAD, 0);
            mw.visitVarInsn(ALOAD, Context.serializer);
            mw.visitMethodInsn(INVOKEVIRTUAL, JavaBeanSerializer, "writeDirect", "(L" + JSONSerializer + ";)Z");
            mw.visitJumpInsn(IFNE, _directElse);
            mw.visitVarInsn(ALOAD, 0);
            mw.visitVarInsn(ALOAD, 1);
            mw.visitVarInsn(ALOAD, 2);
            mw.visitVarInsn(ALOAD, 3);
            mw.visitVarInsn(ALOAD, 4);
            mw.visitVarInsn(ILOAD, 5);
            mw.visitMethodInsn(INVOKEVIRTUAL, classNameType, "writeNormal", "(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
            mw.visitInsn(RETURN);
            mw.visitLabel(_directElse);
            mw.visitVarInsn(ALOAD, context.var("out"));
            mw.visitLdcInsn(SerializerFeature.DisableCircularReferenceDetect.mask);
            mw.visitMethodInsn(INVOKEVIRTUAL, SerializeWriter, "isEnabled", "(I)Z");
            mw.visitJumpInsn(IFEQ, _direct);
            mw.visitVarInsn(ALOAD, 0);
            mw.visitVarInsn(ALOAD, 1);
            mw.visitVarInsn(ALOAD, 2);
            mw.visitVarInsn(ALOAD, 3);
            mw.visitVarInsn(ALOAD, 4);
            mw.visitVarInsn(ILOAD, 5);
            mw.visitMethodInsn(INVOKEVIRTUAL, classNameType, "writeDirectNonContext", "(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V");
            mw.visitInsn(RETURN);
            mw.visitLabel(_direct);
        }
        // obj
        mw.visitVarInsn(ALOAD, Context.obj);
        // serializer
        mw.visitTypeInsn(CHECKCAST, type(clazz));
        // obj
        mw.visitVarInsn(ASTORE, context.var("entity"));
        generateWriteMethod(clazz, mw, getters, context);
        mw.visitInsn(RETURN);
        mw.visitMaxs(7, context.variantIndex + 2);
        mw.visitEnd();
    }
    if (!nativeSorted) {
        // sortField support
        Context context = new Context(getters, beanInfo, classNameType, false, DisableCircularReferenceDetect);
        mw = new MethodWriter(cw, ACC_PUBLIC, "writeUnsorted", "(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V", null, new String[] { "java/io/IOException" });
        mw.visitVarInsn(ALOAD, Context.serializer);
        mw.visitFieldInsn(GETFIELD, JSONSerializer, "out", SerializeWriter_desc);
        mw.visitVarInsn(ASTORE, context.var("out"));
        // obj
        mw.visitVarInsn(ALOAD, Context.obj);
        // serializer
        mw.visitTypeInsn(CHECKCAST, type(clazz));
        // obj
        mw.visitVarInsn(ASTORE, context.var("entity"));
        generateWriteMethod(clazz, mw, unsortedGetters, context);
        mw.visitInsn(RETURN);
        mw.visitMaxs(7, context.variantIndex + 2);
        mw.visitEnd();
    }
    // 2 writeAsArrayNonContext
    for (int i = 0; i < 3; ++i) {
        String methodName;
        boolean nonContext = DisableCircularReferenceDetect;
        boolean writeDirect = false;
        if (i == 0) {
            methodName = "writeAsArray";
            writeDirect = true;
        } else if (i == 1) {
            methodName = "writeAsArrayNormal";
        } else {
            writeDirect = true;
            nonContext = true;
            methodName = "writeAsArrayNonContext";
        }
        Context context = new Context(getters, beanInfo, classNameType, writeDirect, nonContext);
        mw = new MethodWriter(cw, ACC_PUBLIC, methodName, "(L" + JSONSerializer + ";Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/reflect/Type;I)V", null, new String[] { "java/io/IOException" });
        mw.visitVarInsn(ALOAD, Context.serializer);
        mw.visitFieldInsn(GETFIELD, JSONSerializer, "out", SerializeWriter_desc);
        mw.visitVarInsn(ASTORE, context.var("out"));
        // obj
        mw.visitVarInsn(ALOAD, Context.obj);
        // serializer
        mw.visitTypeInsn(CHECKCAST, type(clazz));
        // obj
        mw.visitVarInsn(ASTORE, context.var("entity"));
        generateWriteAsArray(clazz, mw, getters, context);
        mw.visitInsn(RETURN);
        mw.visitMaxs(7, context.variantIndex + 2);
        mw.visitEnd();
    }
    byte[] code = cw.toByteArray();
    Class<?> exampleClass = classLoader.defineClassPublic(classNameFull, code, 0, code.length);
    Constructor<?> constructor = exampleClass.getConstructor(SerializeBeanInfo.class);
    Object instance = constructor.newInstance(beanInfo);
    return (JavaBeanSerializer) instance;
}
Also used : MethodWriter(com.alibaba.fastjson.asm.MethodWriter) Label(com.alibaba.fastjson.asm.Label) JSONException(com.alibaba.fastjson.JSONException) ASMUtils(com.alibaba.fastjson.util.ASMUtils) ClassWriter(com.alibaba.fastjson.asm.ClassWriter) FieldWriter(com.alibaba.fastjson.asm.FieldWriter) MethodVisitor(com.alibaba.fastjson.asm.MethodVisitor) JSONType(com.alibaba.fastjson.annotation.JSONType) FieldInfo(com.alibaba.fastjson.util.FieldInfo)

Aggregations

ClassWriter (com.alibaba.fastjson.asm.ClassWriter)3 MethodVisitor (com.alibaba.fastjson.asm.MethodVisitor)2 MethodWriter (com.alibaba.fastjson.asm.MethodWriter)2 JSONException (com.alibaba.fastjson.JSONException)1 JSONType (com.alibaba.fastjson.annotation.JSONType)1 FieldWriter (com.alibaba.fastjson.asm.FieldWriter)1 Label (com.alibaba.fastjson.asm.Label)1 ParseContext (com.alibaba.fastjson.parser.ParseContext)1 JSONSerializer (com.alibaba.fastjson.serializer.JSONSerializer)1 SerializeWriter (com.alibaba.fastjson.serializer.SerializeWriter)1 ASMUtils (com.alibaba.fastjson.util.ASMUtils)1 FieldInfo (com.alibaba.fastjson.util.FieldInfo)1 FileOutputStream (java.io.FileOutputStream)1 Method (java.lang.reflect.Method)1