前言
上文ASM入门篇中除了对ASM
的应用做了介绍,同时也提到ASM
被应用的一些场景,其中有一项就是ASM
被用来代替Java
反射;FastJson
作为序列化工具,就应用了ASM
来代替反射的应用,进步整体的性能。
序列化
序列化就是将对象转换成Json
格局的字符串,而后用来长久化或者网络传输;FastJson
提供了接口类ObjectSerializer
:
public interface ObjectSerializer { void write(JSONSerializer serializer, // Object object, // Object fieldName, // Type fieldType, // int features) throws IOException;}
- serializer:序列化上下文;
- object:须要转换为Json的对象;
- fieldName:父对象字段名称;
- fieldType:父对象字段类型;
- features:父对象字段序列化features;
ObjectSerializer
的实现类有多种,最常见就是序列化JavaBean
的JavaBeanSerializer
,当然还有一些其余类型的序列化工具类比方:根本类型、日期类型、枚举类型、一些非凡类型等等;引入的ASM正是对JavaBeanSerializer
的优化,当然要应用ASM优化也是有条件的,满足条件的状况下会通过ASM生成JavaBeanSerializer
的子类,代替外面的反射操作;
启用条件
FastJson提供了ASM的开关,默认开启状态,同时在满足肯定的条件下能力应用ASMSerializerFactory
创立ASMSerializer
;
开关
SerializeConfig
中提供了asm开关标识:
private boolean asm = !ASMUtils.IS_ANDROID
默认安卓环境下为false
,否则为true
,所有服务端开发个别都是开启asm的;
JSONType注解
- 如果配置了
serializer
,则应用配置的序列化类:
@JSONType(serializer = JavaBeanSerializer.class)
- 如果配置了
asm
为false
,则不启用asm
:
@JSONType(asm = false)
- 如果配置了指定几种
SerializerFeature
,则不开启asm
:
@JSONType(serialzeFeatures = {SerializerFeature.WriteNonStringValueAsString,SerializerFeature.WriteEnumUsingToString,SerializerFeature.NotWriteDefaultValue,SerializerFeature.BrowserCompatible})
- 如果配置了
SerializeFilter
,则不开启asm
:
@JSONType(serialzeFilters = {})
BeanType类信息
如果类修饰符不为public
,则不开启asm
,间接应用JavaBeanSerializer
;
如果类名称字符中蕴含了<001 || >177 || ==.
的字符,则不启用asm
;
如果类是接口类则不启用asm
;
对类属性的查看,包含类型,返回值,注解等,不合乎的状况下同样不启用asm
;
创立ASMSerializer
通过ASM
为每个JavaBean
生成一个独立的JavaBeanSerializer
子类,具体步骤如下:
生成类名
创立类之前须要生成一个惟一的名称:
String className = "ASMSerializer_" + seed.incrementAndGet() + "_" + clazz.getSimpleName()
这里的seed
是一个AtomicLong
变量;以Person
为例,则生成的className
为ASMSerializer_1_Person
;
生成子类
通过ASM的ClassWriter
来生成JavaBeanSerializer
的子类,重写write
办法,JavaBeanSerializer
中的write
办法会应用反射从JavaBean
中获取相干信息,而通过ASM生成的ASMSerializer_1_Person
,是针对Person
独有的序列化工具类,能够看局部代码:
public class ASMSerializer_1_Personextends JavaBeanSerializerimplements ObjectSerializer { public ASMSerializer_1_Person(SerializeBeanInfo serializeBeanInfo) { super(serializeBeanInfo); } public void write(JSONSerializer jSONSerializer, Object object, Object object2, Type type, int n) throws IOException { if (object == null) { jSONSerializer.writeNull(); return; } SerializeWriter serializeWriter = jSONSerializer.out; if (!this.writeDirect(jSONSerializer)) { this.writeNormal(jSONSerializer, object, object2, type, n); return; } if (serializeWriter.isEnabled(32768)) { this.writeDirectNonContext(jSONSerializer, object, object2, type, n); return; } Person person = (Person)object; if (this.writeReference(jSONSerializer, object, n)) { return; } if (serializeWriter.isEnabled(0x200000)) { this.writeAsArray(jSONSerializer, object, object2, type, n); return; } SerialContext serialContext = jSONSerializer.getContext(); jSONSerializer.setContext(serialContext, object, object2, 0); int n2 = 123; String string = "email"; String string2 = person.getEmail(); if (string2 == null) { if (serializeWriter.isEnabled(132)) { serializeWriter.write(n2); serializeWriter.writeFieldNameDirect(string); serializeWriter.writeNull(0, 128); n2 = 44; } } else { serializeWriter.writeFieldValueStringWithDoubleQuoteCheck((char)n2, string, string2); n2 = 44; } string = "id"; int n3 = person.getId(); serializeWriter.writeFieldValue((char)n2, string, n3); n2 = 44; string = "name"; string2 = person.getName(); if (string2 == null) { if (serializeWriter.isEnabled(132)) { serializeWriter.write(n2); serializeWriter.writeFieldNameDirect(string); serializeWriter.writeNull(0, 128); n2 = 44; } } else { serializeWriter.writeFieldValueStringWithDoubleQuoteCheck((char)n2, string, string2); n2 = 44; } if (n2 == 123) { serializeWriter.write(123); } serializeWriter.write(125); jSONSerializer.setContext(serialContext); } ...省略...}
因为是仅是Person
的序列化工具,所有能够发现外面间接强转Object
为Person
,通过间接调用的形式获取Person
的相干信息,替换了反射的应用,咱们晓得间接调用的性能比应用反射强很多;
查看源码
通过ASM生成的JavaBeanSerializer
子类,转换成字节数组通过类加载间接加载到内存中,如果想查看主动生成的类源码能够应用如下两种形式来获取:
增加
Debug
代码
在ASMSerializerFactory
中找到createJavaBeanSerializer
办法,ASM生成的代码最终会生成字节数组,局部代码如下所示:byte[] code = cw.toByteArray();Class<?> serializerClass = classLoader.defineClassPublic(classNameFull, code, 0, code.length);
在IDEA环境下能够在第二行处加断点,而后右击
断点,抉择More
,勾选Evaluate and log
,输出如下代码:
FileOutputStream fileOutputStream = new FileOutputStream(new File("F:/ASMSerializer_1_Person.class"));fileOutputStream.write(code);fileOutputStream.close();
应用
arthas
因为咱们曾经晓得主动生成的类名,能够应用arthas
监控以后过程,而后应用jad命令获取类源码:[arthas@17916]$ jad com.alibaba.fastjson.serializer.ASMSerializer_1_PersonClassLoader:+-com.alibaba.fastjson.util.ASMClassLoader@32eebfca +-jdk.internal.loader.ClassLoaders$AppClassLoader@2437c6dc +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@3688c050Location:/D:/myRepository/com/alibaba/fastjson/1.2.70/fastjson-1.2.70.jar/* * Decompiled with CFR. * * Could not load the following classes: * com.fastjson.Person */package com.alibaba.fastjson.serializer;import com.alibaba.fastjson.serializer.JSONSerializer;import com.alibaba.fastjson.serializer.JavaBeanSerializer;import com.alibaba.fastjson.serializer.ObjectSerializer;import com.alibaba.fastjson.serializer.SerialContext;import com.alibaba.fastjson.serializer.SerializeBeanInfo;import com.alibaba.fastjson.serializer.SerializeWriter;import com.fastjson.Person;import java.io.IOException;import java.lang.reflect.Type;public class ASMSerializer_1_Personextends JavaBeanSerializerimplements ObjectSerializer { public ASMSerializer_1_Person(SerializeBeanInfo serializeBeanInfo) {
留神这里须要提供类的全名称:包名+类名
加载类
通过ASM生成的类信息,不能间接应用,还须要通过类加载加载,这里通过ASMClassLoader
来加载,加载完之后获取结构器Constructor
,而后应用newInstance
创立一个JavaBeanSerializer
的子类:
byte[] code = cw.toByteArray();Class<?> serializerClass = classLoader.defineClassPublic(classNameFull, code, 0, code.length);Constructor<?> constructor = serializerClass.getConstructor(SerializeBeanInfo.class);Object instance = constructor.newInstance(beanInfo);
反序列化
将Json
串转化成对象的过程,FastJson
提供了ObjectDeserializer
接口类:
public interface ObjectDeserializer { <T> T deserialze(DefaultJSONParser parser, Type type, Object fieldName); int getFastMatchToken();}
- parser:反序列化上下文DefaultJSONParser;
- type:要反序列化的对象的类型;
- fieldName:父对象字段名称;
同序列化过程,大抵分为以下几个过程:
生成类名
生成一个业务类的反序列化工具类名:
String className = "FastjsonASMDeserializer_" + seed.incrementAndGet() + "_" + clazz.getSimpleName();
同样以Person
为例,那么生成的className
为FastjsonASMDeserializer_1_Person
;
生成子类
同样应用ASM
的ClassWriter
生成JavaBeanDeserializer
的子类,重写其中的deserialze
办法,局部代码如下:
public class FastjsonASMDeserializer_1_Personextends JavaBeanDeserializer { public char[] name_asm_prefix__ = "\"name\":".toCharArray(); public char[] id_asm_prefix__ = "\"id\":".toCharArray(); public char[] email_asm_prefix__ = "\"email\":".toCharArray(); public ObjectDeserializer name_asm_deser__; public ObjectDeserializer email_asm_deser__; public FastjsonASMDeserializer_1_Person(ParserConfig parserConfig, JavaBeanInfo javaBeanInfo) { super(parserConfig, javaBeanInfo); } public Object createInstance(DefaultJSONParser defaultJSONParser, Type type) { return new Person(); } public Object deserialze(DefaultJSONParser defaultJSONParser, Type type, Object object, int n) { block18: { String string; int n2; String string2; int n3; Person person; block20: { ParseContext parseContext; ParseContext parseContext2; block19: { block22: { JSONLexerBase jSONLexerBase; block24: { int n4; int n5; block23: { block21: { String string3; String string4; jSONLexerBase = (JSONLexerBase)defaultJSONParser.lexer; if (jSONLexerBase.token() == 14 && jSONLexerBase.isEnabled(n, 8192)) { return this.deserialzeArrayMapping(defaultJSONParser, type, object, null); } if (!jSONLexerBase.isEnabled(512) || jSONLexerBase.scanType("com.fastjson.Person") == -1) break block18; ParseContext parseContext3 = defaultJSONParser.getContext(); n5 = 0; person = new Person(); parseContext2 = defaultJSONParser.getContext(); parseContext = defaultJSONParser.setContext(parseContext2, person, object); if (jSONLexerBase.matchStat == 4) break block19; n4 = 0; n3 = 0; boolean bl = jSONLexerBase.isEnabled(4096); if (bl) { n3 |= 1; string4 = jSONLexerBase.stringDefaultValue(); } else { string4 = null; } string2 = string4; n2 = 0; if (bl) { n3 |= 4; string3 = jSONLexerBase.stringDefaultValue(); } else { string3 = null; } string = string3; string2 = jSONLexerBase.scanFieldString(this.email_asm_prefix__); if (jSONLexerBase.matchStat > 0) { n3 |= 1; } if ((n4 = jSONLexerBase.matchStat) == -1) break block20; if (jSONLexerBase.matchStat <= 0) break block21; ++n5; if (jSONLexerBase.matchStat == 4) break block22; } n2 = jSONLexerBase.scanFieldInt(this.id_asm_prefix__); if (jSONLexerBase.matchStat > 0) { n3 |= 2; } if ((n4 = jSONLexerBase.matchStat) == -1) break block20; if (jSONLexerBase.matchStat <= 0) break block23; ++n5; if (jSONLexerBase.matchStat == 4) break block22; } string = jSONLexerBase.scanFieldString(this.name_asm_prefix__); if (jSONLexerBase.matchStat > 0) { n3 |= 4; } if ((n4 = jSONLexerBase.matchStat) == -1) break block20; if (jSONLexerBase.matchStat <= 0) break block24; ++n5; if (jSONLexerBase.matchStat == 4) break block22; } if (jSONLexerBase.matchStat != 4) break block20; } if ((n3 & 1) != 0) { person.setEmail(string2); } if ((n3 & 2) != 0) { person.setId(n2); } if ((n3 & 4) != 0) { person.setName(string); } } defaultJSONParser.setContext(parseContext2); if (parseContext != null) { parseContext.object = person; } return person; } if ((n3 & 1) != 0) { person.setEmail(string2); } if ((n3 & 2) != 0) { person.setId(n2); } if ((n3 & 4) != 0) { person.setName(string); } return (Person)this.parseRest(defaultJSONParser, type, object, person, n, new int[]{n3}); } return super.deserialze(defaultJSONParser, type, object, n); } ...省略...}
能够发现同样应用具体的业务类,代替了在JavaBeanDeserializer
应用反射操作;同样最初须要对该类信息进行加载,而后通过结构器实例化具体业务对象。
总结
本文应用ASM
代替反射只是泛滥应用场景的一种,在FastJson
中只用了ASM
的生成类性能;ASM
更强的的性能是它的转换性能,对现有类进行革新,生成新的类从而对现有类进行性能加强,当然加载的过程也不是简略的应用类加载器就行了,这时候配合Java Agent
来实现热更新;其实代替反射除了应用ASM
,在Protobuf
中也提供了一种办法,在研发阶段就把所有的业务序列化反序列化操作都筹备好,是一种动态的解决形式,而ASM
这种动静生成的形式更加人性化。