java reflect性能测试
针对类的成员set,get方法和创建对象进行了正常和反射的测试。
测试前提:一千万次调用的测试,cpu e5800 @3.2GHz,内存3G
测试代码如下:
Cat.java
public class Cat {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
TestInvoke.java
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class TestInvoke {
private static int testNum = 10000000;// 一千万次
public static void main(String[] args) throws Exception {
TestInvoke testInvoke = new TestInvoke();
testInvoke.testSet_reflect();
testInvoke.testSet_normal();
testInvoke.testGet_reflect();
testInvoke.testGet_normal();
testInvoke.testNew_reflect();
testInvoke.testNew_normal();
}
/**
* set方法反射方式测试
*
* @throws Exception
*/
public void testSet_reflect() throws Exception {
Map<String, Method> methodCache = new HashMap<String, Method>();
Class<Cat> classType = Cat.class;
Object object = classType.newInstance();
String methodName = "setId";
long startTime = System.currentTimeMillis();
for (int i = 0; i < testNum; i++) {
// 如果setMethod直接放在循环里面性能下降10倍。所以可以做个缓存。
Method setMethod = null;
if (methodCache.containsKey(methodName)) {
setMethod = methodCache.get(methodName);
} else {
setMethod = classType.getMethod(methodName, new Class[] {int.class});
methodCache.put(methodName, setMethod);
}
setMethod.invoke(object, 100000);
}
System.out.println("reflect invoke set method spend time:" + (System.currentTimeMillis() - startTime));
}
/**
* set方法正常方式测试
*
* @throws Exception
*/
public void testSet_normal() throws Exception {
Cat cat = new Cat();
long startTime = System.currentTimeMillis();
for (int i = 0; i < testNum; i++) {
cat.setId(100000);
}
System.out.println("normal invoke set method spend time:" + (System.currentTimeMillis() - startTime));
}
/**
* get方法反射方式测试
*
* @throws Exception
*/
public void testGet_reflect() throws Exception {
Map<String, Method> methodCache = new HashMap<String, Method>();
Class<Cat> classType = Cat.class;
Object object = classType.newInstance();
// 设置数据
Method setMethod = classType.getMethod("setId", new Class[] {int.class});
setMethod.invoke(object, 1234);
String methodName = "getId";
long startTime = System.currentTimeMillis();
for (int i = 0; i < testNum; i++) {
// 如果setMethod直接放在循环里面性能下降10倍。所以可以做个缓存。
Method getMethod = null;
if (methodCache.containsKey(methodName)) {
getMethod = methodCache.get(methodName);
} else {
getMethod = classType.getMethod(methodName);
methodCache.put(methodName, getMethod);
}
getMethod.invoke(object);
}
System.out.println("reflect invoke get method spend time:" + (System.currentTimeMillis() - startTime));
}
/**
* get方法正常方式测试
*
* @throws Exception
*/
public void testGet_normal() throws Exception {
Cat cat = new Cat();
// 设置数据
cat.setId(1234);
long startTime = System.currentTimeMillis();
for (int i = 0; i < testNum; i++) {
cat.getId();
}
System.out.println("normal invoke get method spend time:" + (System.currentTimeMillis() - startTime));
}
/**
* new方法反射方式测试
*
* @throws Exception
*/
public void testNew_reflect() throws Exception {
long startTime = System.currentTimeMillis();
Class<Cat> classType = Cat.class;
for (int i = 0; i < testNum; i++) {
Object object = classType.newInstance();
}
System.out.println("reflect invoke new spend time:" + (System.currentTimeMillis() - startTime));
}
/**
* new方法正常方式测试
*
* @throws Exception
*/
public void testNew_normal() throws Exception {
long startTime = System.currentTimeMillis();
for (int i = 0; i < testNum; i++) {
Cat cat = new Cat();
}
System.out.println("normal invoke new spend time:" + (System.currentTimeMillis() - startTime));
}
}
三次运行结果:
第一次:
reflect invoke set method spend time:1078
normal invoke set method spend time:0(经常结果0,效率真是太高了)
reflect invoke get method spend time:1000
normal invoke get method spend time:15
reflect invoke new spend time:1063
normal invoke new spend time:109
第二次:
reflect invoke set method spend time:1078
normal invoke set method spend time:16
reflect invoke get method spend time:1000
normal invoke get method spend time:0(经常结果0,效率真是太高了)
reflect invoke new spend time:1063
normal invoke new spend time:109
第三次:
reflect invoke set method spend time:1078
normal invoke set method spend time:15
reflect invoke get method spend time:985
normal invoke get method spend time:15
reflect invoke new spend time:1063
normal invoke new spend time:109
得出以下结论:
1 反射不是不能用,没有想象的那么差,只是正常调用方式效率更高,在一千次内的调用可以认为效率相当。
2 set方法效率相差大概:70到来200倍
3 get方法效率相差大概:70到来200倍
4 new方法效率相差大概:10倍