asm是一个java的字节码框架,它能被用来动态生成类或者增强既有类的功能。
一般asm的应用场景主要在aop上,比如Spring在底层就是用了asm,但asm不仅仅是只能在aop方面发挥它强大的能力,比如你现在要写一个rpc框架,可能会在序列化对象上犯难,使用java的序列化机制?有点慢;json?(比如阿里的大神搞的fastjson性能就很好),但我要序列化的对象很简单,没有嵌套对象,不需要深拷贝,并且我并不想按照json的格式来
我的计划是将对象拼成如下格式的字符串:
- fieldName1,Type1,value1;fieldName2,Type2,value2;fieldName3,Type3,value3;fieldName4,Type4,value4;...;
fieldName1,Type1,value1;fieldName2,Type2,value2;fieldName3,Type3,value3;fieldName4,Type4,value4;...;
用反射实现的代码大致是这样:
-
for (Map.Entry<String, Pair<String, Field>> iter : argFields.entrySet()) {
- fieldName = iter.getKey(); // 名
- pair = iter.getValue();
- fieldType = pair.getKey(); // 类型
- fieldValue = pair.getValue().get(event); // 值(反射)
-
if (fieldValue instanceof Date) {
- sBuilder.append(fieldName).append(",").append(fieldType).append(",").append(((Date) fieldValue).getTime()).append(";");
- } else {
- sBuilder.append(fieldName).append(",").append(fieldType).append(",").append(fieldValue).append(";");
- }
- }
for (Map.Entry<String, Pair<String, Field>> iter : argFields.entrySet()) {
fieldName = iter.getKey(); // 名
pair = iter.getValue();
fieldType = pair.getKey(); // 类型
fieldValue = pair.getValue().get(event); // 值(反射)
if (fieldValue instanceof Date) {
sBuilder.append(fieldName).append(",").append(fieldType).append(",").append(((Date) fieldValue).getTime()).append(";");
} else {
sBuilder.append(fieldName).append(",").append(fieldType).append(",").append(fieldValue).append(";");
}
}
速度还可以,不过我觉得还可以更快,于是我想到了用asm代替反射,由于我个人对字节码的指令只是略知一二(都是从《深入java虚拟机》一书来的些理论知识),所以用那200来个字节码指令直接写一个我想要的类实在有点难度,于是我先用java写了一个我想要的类,然后用
- javap -verbose XXX
javap -verbose XXX
反编译了它,然后照着反编译出来的字节码指令以及注释一步一步最后完成了一个类
下面这个类是我想要的类,我先用java完成了它
-
public StringBuilder write(Event event) throws IOException {
- GNSEvent obj = (GNSEvent) event;
- StringBuilder sBuilder = new StringBuilder(256);
- sBuilder.append("cityCode").append(",").append("java.lang.String").append(obj.getCityCode());
- // obj循环序列化obj的所有属性
-
return sBuilder;
- }
public StringBuilder write(Event event) throws IOException {
GNSEvent obj = (GNSEvent) event;
StringBuilder sBuilder = new StringBuilder(256);
sBuilder.append("cityCode").append(",").append("java.lang.String").append(obj.getCityCode());
// obj循环序列化obj的所有属性
return sBuilder;
}
用javap反编译它,得到下面有用的信息:
-
public com.futurefleet.framework.serialization.Serializer_1GNSEvent();
- Code:
- Stack=1, Locals=1, Args_size=1
-
0: aload_0
-
1: invokespecial #10;//Method java/lang/Object."<init>":()V
-
4: return
- LineNumberTable:
- line 16: 0
-
- LocalVariableTable:
- Start Length Slot Name Signature
-
0 5 0 this Lcom/futurefleet/framework/serialization/Serializer_1GNSEvent;
-
-
-
public java.lang.StringBuilder write(com.futurefleet.framework.base.event.Event)throws java.io.IOException;
- Exceptions:
-
throws java.io.IOException Code:
- Stack=3, Locals=4, Args_size=2
-
0: aload_1
-
1: checkcast #21; //class com/futurefleet/gateway/event/GNSEvent
-
4: astore_2
-
5: new #23;//class java/lang/StringBuilder
-
8: dup
-
9: sipush 256
-
12: invokespecial #25;//Method java/lang/StringBuilder."<init>":(I)V
-
15: astore_3
-
16: aload_3
-
17: ldc #28; //String cityCode
-
19: invokevirtual #30;//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
-
22: ldc #34; //String ,
-
24: invokevirtual #30;//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
-
27: ldc #36; //String java.lang.String
-
29: invokevirtual #30;//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
-
32: aload_2
-
33: invokevirtual #38;//Method com/futurefleet/gateway/event/GNSEvent.getCityCode:()Ljava/lang/String;
-
36: invokevirtual #30;//Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
-
39: pop
-
40: aload_3
-
41: areturn
fieldName = iter.getKey(); // 名
pair = iter.getValue();
fieldType = pair.getKey(); // 类型
fieldValue = pair.getValue().get(event); // 值(反射)
if (fieldValue instanceof Date) {
sBuilder.append(fieldName).append(",").append(fieldType).append(",").append(((Date) fieldValue).getTime()).append(";");
} else {
sBuilder.append(fieldName).append(",").append(fieldType).append(",").append(fieldValue).append(";");
}
}
GNSEvent obj = (GNSEvent) event;
StringBuilder sBuilder = new StringBuilder(256);
sBuilder.append("cityCode").append(",").append("java.lang.String").append(obj.getCityCode());
// obj循环序列化obj的所有属性
return sBuilder;
}