反射工具包ReflectASM使用
待反射的类 SomeClass.java
public class SomeClass {
private String name;
public void foo(String name) {
this.name = name;
}
}
测试类 ReflectasmClient.java
import java.lang.reflect.Method;
import com.esotericsoftware.reflectasm.MethodAccess;
public class ReflectasmClient {
public static void main(String[] args) throws Exception {
testJdkReflect();
// testReflectAsm();
}
public static void testJdkReflect() throws Exception {
SomeClass someObject = new SomeClass();
for (int i = 0; i < 5; i++) {
long begin = System.currentTimeMillis();
for (int j = 0; j < 100000000; j++) {
Method method = SomeClass.class.getMethod("foo", String.class);
method.invoke(someObject, "Unmi");
}
System.out.print(System.currentTimeMillis() - begin +" ");
}
}
public static void testReflectAsm() {
SomeClass someObject = new SomeClass();
for (int i = 0; i < 5; i++) {
long begin = System.currentTimeMillis();
for (int j = 0; j < 100000000; j++) {
MethodAccess access = MethodAccess.get(SomeClass.class);
access.invoke(someObject, "foo", "Unmi");
}
System.out.print(System.currentTimeMillis() - begin + " ");
}
}
}
分别运行 testJdkReflect() 和 testReflectAsm 得出各自的运行时间数据,如下:
运行 testJdkReflect(): 31473 31663 31578 31658 31552
运行 testReflectAsm(): 312814 310666 312867 311234 311792
这个数据是非常恐怖的,似乎在带领我们往相反的方向上走,用 ReflectASM 怎么反而耗时多的多,高一个数量级,为什么呢?原因是大部分的时间都耗费在了
MethodAccess access = MethodAccess.get(SomeClass.class);
上,正是生成字节码的环节上,也让你体验到 MethodAccess 是个无比耗时的操作,如果把这行放到循环之外会是什么样的结果呢,同时也把方法 testJdkReflect() 中的
Method method = SomeClass.class.getMethod("foo", String.class);
也提出去,改变后的 testJdkReflect() 和 testReflectAsm() 分别如下:
public static void testJdkReflect() throws Exception {
SomeClass someObject = new SomeClass();
Method method = SomeClass.class.getMethod("foo", String.class);
for (int i = 0; i < 5; i++) {
long begin = System.currentTimeMillis();
for (int j = 0; j < 100000000; j++) {
method.invoke(someObject, "Unmi");
}
System.out.print(System.currentTimeMillis() - begin +" ");
}
}
public static void testReflectAsm() {
SomeClass someObject = new SomeClass();
MethodAccess access = MethodAccess.get(SomeClass.class);
for (int i = 0; i < 5; i++) {
long begin = System.currentTimeMillis();
for (int j = 0; j < 100000000; j++) {
access.invoke(someObject, "foo", "Unmi");
}
System.out.print(System.currentTimeMillis() - begin + " ");
}
}
再次分别跑下 testJdkReflect() 和 testReflectAsm(),新的结果如下:
运行 testJdkReflect(): 1682 1696 1858 1774 1780 ------ 平均 1758
运行 testReflectAsm(): 327 549 520 509 514 ------ 平均 483.8
胜负十分明显,上面的实验两相一比较,用 ReflectAsm 进行方法调用节省时间是 72.48%
也因此可以得到使用 ReflectASM 时需特别注意的是,获得类似 MethodAccess 实例只做一次,或它的实例应缓存起来,才是真正用好 ReflectASM。
- ReflectASM高性能反射类
- MyEclipse Maven项目加入本地jar包
- Spring 自带工具类
- NIO Paths工具对文件操作
- NIO Files工具对文件操作
- java反射根据字段名读取值
- Java反射允许修改final属性值的方式
- FastDFS分布式文件系统封装JAVA client工具类
- Springboot使用外部Tomcat
- Elasticsearch使用索引别名
- redis连接方式推荐使用
- seaweedfs在windows上使用
- SpringMVC使用StandardServletMultipartResolver上传文件
- Elasticsearch使用searchAfter深度分页
- 使用Redis bitmap统计活跃用户