From 8a01882bda7e19ceddeae589fafd71c35181e99e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E9=93=81?= Date: Fri, 8 Jan 2016 13:31:44 +0800 Subject: [PATCH] improve Immutable Object support using asm --- .../alibaba/fastjson/parser/ParserConfig.java | 30 +++++------------ .../deserializer/ASMDeserializerFactory.java | 32 +++++++++++++++---- .../fastjson/util/DeserializeBeanInfo.java | 2 +- 3 files changed, 34 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/alibaba/fastjson/parser/ParserConfig.java b/src/main/java/com/alibaba/fastjson/parser/ParserConfig.java index 9b56ac265..2c5991ad1 100644 --- a/src/main/java/com/alibaba/fastjson/parser/ParserConfig.java +++ b/src/main/java/com/alibaba/fastjson/parser/ParserConfig.java @@ -438,7 +438,10 @@ public class ParserConfig { public ObjectDeserializer createJavaBeanDeserializer(Class clazz, Type type) { boolean asmEnable = this.asmEnable; if (asmEnable) { - Class superClass = clazz; + Class superClass = DeserializeBeanInfo.getBuilderClass(clazz); + if (superClass == null) { + superClass = clazz; + } for (;;) { if (!Modifier.isPublic(superClass.getModifiers())) { @@ -471,9 +474,6 @@ public class ParserConfig { } DeserializeBeanInfo beanInfo = DeserializeBeanInfo.computeSetters(clazz, type); - if (beanInfo.getBuilderClass() != null) { - asmEnable = false; - } if (asmEnable && beanInfo.getFieldList().size() > 200) { asmEnable = false; @@ -539,9 +539,11 @@ public class ParserConfig { boolean asmEnable = this.asmEnable; Class clazz = beanInfo.getClazz(); - Class builderClass = beanInfo.getBuilderClass(); if (asmEnable) { - Class superClass = clazz; + Class superClass = beanInfo.getBuilderClass(); + if (superClass == null) { + superClass = clazz; + } for (;;) { if (!Modifier.isPublic(superClass.getModifiers())) { @@ -556,22 +558,6 @@ public class ParserConfig { } } - if (asmEnable && builderClass != null) { - Class superClass = builderClass; - - for (;;) { - if (!Modifier.isPublic(superClass.getModifiers())) { - asmEnable = false; - break; - } - - superClass = superClass.getSuperclass(); - if (superClass == Object.class || superClass == null) { - break; - } - } - } - if (fieldInfo.getFieldClass() == Class.class) { asmEnable = false; } diff --git a/src/main/java/com/alibaba/fastjson/parser/deserializer/ASMDeserializerFactory.java b/src/main/java/com/alibaba/fastjson/parser/deserializer/ASMDeserializerFactory.java index 26a46a362..b0d0d1c87 100755 --- a/src/main/java/com/alibaba/fastjson/parser/deserializer/ASMDeserializerFactory.java +++ b/src/main/java/com/alibaba/fastjson/parser/deserializer/ASMDeserializerFactory.java @@ -604,6 +604,13 @@ public class ASMDeserializerFactory implements Opcodes { _setContext(context, mw); mw.visitVarInsn(ALOAD, context.var("instance")); + + Method buildMethod = context.getBeanInfo().getBuildMethod(); + if (buildMethod != null) { + mw.visitMethodInsn(INVOKEVIRTUAL, getType(context.getInstClass()), buildMethod.getName(), + "()" + getDesc(buildMethod.getReturnType())); + } + mw.visitInsn(ARETURN); mw.visitLabel(reset_); @@ -646,11 +653,13 @@ public class ASMDeserializerFactory implements Opcodes { } private void _createInstance(Context context, MethodVisitor mw) { - Constructor defaultConstructor = context.getBeanInfo().getDefaultConstructor(); + DeserializeBeanInfo beanInfo = context.getBeanInfo(); + Constructor defaultConstructor = beanInfo.getDefaultConstructor(); if (Modifier.isPublic(defaultConstructor.getModifiers())) { - mw.visitTypeInsn(NEW, getType(context.getClazz())); + mw.visitTypeInsn(NEW, getType(context.getInstClass())); mw.visitInsn(DUP); - mw.visitMethodInsn(INVOKESPECIAL, getType(context.getClazz()), "", "()V"); + + mw.visitMethodInsn(INVOKESPECIAL, getType(defaultConstructor.getDeclaringClass()), "", "()V"); mw.visitVarInsn(ASTORE, context.var("instance")); } else { @@ -658,7 +667,7 @@ public class ASMDeserializerFactory implements Opcodes { mw.visitVarInsn(ALOAD, 1); mw.visitMethodInsn(INVOKESPECIAL, "com/alibaba/fastjson/parser/deserializer/ASMJavaBeanDeserializer", "createInstance", "(Lcom/alibaba/fastjson/parser/DefaultJSONParser;)Ljava/lang/Object;"); - mw.visitTypeInsn(CHECKCAST, getType(context.getClazz())); // cast + mw.visitTypeInsn(CHECKCAST, getType(context.getInstClass())); // cast mw.visitVarInsn(ASTORE, context.var("instance")); } } @@ -703,7 +712,7 @@ public class ASMDeserializerFactory implements Opcodes { mw.visitVarInsn(ALOAD, context.var("instance")); mw.visitVarInsn(LLOAD, context.var(fieldInfo.getName() + "_asm", 2)); if (fieldInfo.getMethod() != null) { - mw.visitMethodInsn(INVOKEVIRTUAL, getType(context.getClazz()), fieldInfo.getMethod().getName(), + mw.visitMethodInsn(INVOKEVIRTUAL, getType(context.getInstClass()), fieldInfo.getMethod().getName(), getDesc(fieldInfo.getMethod())); if (!fieldInfo.getMethod().getReturnType().equals(Void.TYPE)) { mw.visitInsn(POP); @@ -1245,6 +1254,15 @@ public class ASMDeserializerFactory implements Opcodes { public Class getClazz() { return clazz; } + + public Class getInstClass() { + Class instClass = beanInfo.getBuilderClass(); + if (instClass == null) { + instClass = clazz; + } + + return instClass; + } public int getVariantCount() { return variantIndex; @@ -1338,9 +1356,9 @@ public class ASMDeserializerFactory implements Opcodes { , "(Lcom/alibaba/fastjson/parser/DefaultJSONParser;Ljava/lang/reflect/Type;)Ljava/lang/Object;", null, null); - mw.visitTypeInsn(NEW, getType(context.getClazz())); + mw.visitTypeInsn(NEW, getType(context.getInstClass())); mw.visitInsn(DUP); - mw.visitMethodInsn(INVOKESPECIAL, getType(context.getClazz()), "", "()V"); + mw.visitMethodInsn(INVOKESPECIAL, getType(context.getInstClass()), "", "()V"); mw.visitInsn(ARETURN); mw.visitMaxs(3, 3); diff --git a/src/main/java/com/alibaba/fastjson/util/DeserializeBeanInfo.java b/src/main/java/com/alibaba/fastjson/util/DeserializeBeanInfo.java index 08264037a..0d2829ee5 100755 --- a/src/main/java/com/alibaba/fastjson/util/DeserializeBeanInfo.java +++ b/src/main/java/com/alibaba/fastjson/util/DeserializeBeanInfo.java @@ -557,7 +557,7 @@ public class DeserializeBeanInfo { return parserFeatures; } - private static Class getBuilderClass(Class clazz) { + public static Class getBuilderClass(Class clazz) { JSONType type = clazz.getAnnotation(JSONType.class); if (type == null) { return null;