@ghimi
2018-10-20T12:41:06.000000Z
字数 2449
阅读 1543
Java 反射
Java 反射效率到底如何,花了点时间,做了一个简单的测试.供大家参考.
| 场景 | 本机测试结果(xp,双核,2G) | 服务器测试结果(Linux,XEN虚拟机,8核) |
|---|---|---|
| 方法直接调用 | 235ms | 190ms |
| jdk Method调用 | 29188ms | 4633ms |
| jdk Method调用(稍作优化) | 5672ms | 4262ms |
| Cglib FastMethod调用 | 5390ms | 2787ms |
package top.ghimi;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import com.esotericsoftware.reflectasm.MethodAccess;public class ReflectionTest {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {long now;long sum = 0;TestClass t = new TestClass();now = System.currentTimeMillis();for (int i = 0; i < 500000; ++i) {t.setNum(i);sum += t.getNum();}System.out.println("get-set 耗时" + (System.currentTimeMillis() - now) + "ms秒,和是" + sum);sum = 0;now = System.currentTimeMillis();for (int i = 0; i < 50000; ++i) {Class<?> c = Class.forName("top.ghimi.TestClass");Class<?>[] argsType = new Class[1];argsType[0] = int.class;Method m = c.getMethod("setNum", argsType);m.invoke(t, i);sum += t.getNum();}System.out.println("标准反射 耗时" + (System.currentTimeMillis() - now) + "ms秒,和是" + sum);sum = 0;now = System.currentTimeMillis();Class<?> c = Class.forName("top.ghimi.TestClass");Class<?>[] argsType = new Class[1];argsType[0] = int.class;Method m = c.getMethod("setNum", argsType);for (int i = 0; i < 500000; ++i) {m.invoke(t, i);sum += t.getNum();}System.out.println("缓存反射 耗时" + (System.currentTimeMillis() - now) + "ms秒,和是" + sum);sum = 0;now = System.currentTimeMillis();MethodAccess ma = MethodAccess.get(TestClass.class);int index = ma.getIndex("setNum");for (int i = 0; i < 500000; ++i) {ma.invoke(t, index, i);sum += t.getNum();}System.out.println("reflectasm反射 耗时" + (System.currentTimeMillis() - now) + "ms秒,和是" + sum);}}
运行结果如下:
-------------------------------------------------------T E S T S-------------------------------------------------------Running top.ghimi.AppTestget-set 耗时20ms秒,和是124999750000标准反射 耗时107ms秒,和是1249975000缓存反射 耗时15ms秒,和是124999750000reflectasm反射 耗时30ms秒,和是124999750000Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.184 secResults :Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
从结果可以看出,标准反射的运行时间是最长的,比较以外的是缓存反射的运行时间要比正常使用 get-set 方法耗时要短,可见反射并非在任何时候都是消耗性能的.
可以看出,查找函数依然是耗时最长的部分,JDK7的优化确实很不错,由JDK6的40倍降到10倍左右,reflectasm invoke的效率比java原生invoke好,大致是直接访问的4倍时间。效率确实可以一用。