ASM在游戏服务器的使用

发表于2017-10-19
评论0 1.7k浏览

下面给大家介绍的是ASM在游戏服务器的使用,ASM 是一个 Java 字节码操控框架,它能够以二进制形式修改已有类或者动态生成类。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。ASM 从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类。


不过ASM在创建class字节码的过程中,操纵的级别是底层JVM的汇编指令级别,这要求ASM使用者要对class组织结构和JVM汇编指令有一定的了解。

而EsotericSoftware的reflectasm帮忙跨过了这个障碍,使用ASM起来非常方便。

方法级别的反射原本如下写法:

Method method=instance.getClass().getMethod("addName");  
method.setAccessible(true);   
method.invoke(instance,  "Awesome McLovin");  
method.setAccessible(false);  

用Reflectasm后,调整为如下,是不是很简单呢?
Object instance =...
MethodAccess access = MethodAccess.get(instance.getClass());
int addNameIndex = access.getIndex("addName",access.getParameterTypes());
access.invoke(someObject, addNameIndex, "Awesome McLovin");
在我们游戏服务器中,事件分发,异步任务,后台HTTP指令,玩家指令 在服务器起来的时候是分别注册好了,数据路由到这些底层功能后,处理时,本质上就是找到相应的方法method,然后invoke相应的数据,获得结果。

原先我们是用了JAVA原生的反射机制,也就是Method.invoke(Object instance, Object... args),改成了ASM后,性能得到大幅提升,主要是修改了其中的一个类实现:

public class MethodWrapper {  
    private MethodAccess access;  
    private int index;// 方法索引  
    private Object instance;  
    private Class<?> paramClazz;// 参数类型  
    private String name;  
    public MethodWrapper(Method method, Object instance) {  
        this.name=method.getName();  
        this.access = MethodAccess.get(instance.getClass());  
        this.index = access.getIndex(method.getName(), method.getParameterTypes());  
        this.instance = instance;  
        this.paramClazz = method.getParameterTypes()[0];  
    }  
    public Object invoke(Object... args) {  
        Object ret = null;  
        if (args == null) {  
            // 无参数调用  
            ret = access.invoke(instance, index);  
        } else {  
            // 有参数调用  
            ret = access.invoke(instance, index, args);  
        }  
        return ret;  
    }  
    public String getName() {  
        return name;  
    }  
    public void setName(String name) {  
        this.name = name;  
    }  
    public Class<?> getParamClazz() {  
        return paramClazz;  
    }  
    public void setParamClazz(Class<?> paramClazz) {  
        this.paramClazz = paramClazz;  
    }  
}  
进行压力测试后,对比结果如下:



耗时降低到了原先的1/3不到,效果非常好,为什么我们不选用其他的字节码操控框架呢,以下是网上的一个性能对比:

FrameworkFirst timeLater times
Javassist2575.2
BCEL4735.5
ASM62.41.1

这张表表明,ASM的性能远远超过了其他框架,不仅是第一次的运行,后续的反复执行照样表现出色。

http://blog.csdn.net/jiangguilong2000/article/details/49509425

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引