反射机制的性能问题
使用反射机制调用类或调用类的方法会大大的降低程序的执行效率。一下代码测试的是在不同情况下执行同个类方法一亿次所需时间,结果是
类型 | 执行次数 | 所耗时间 |
---|---|---|
普通方法 | 一亿次 | 4ms |
反射 | 一亿次 | 217ms |
反射+跳过安全检查 | 一亿次 | 149ms |
得出的结论就是在调用反射的时候设置setAccessible(true)可以大大地提高程勋执行效率,原因在于在使用反射时,会进行安全性检查,大大降低了程序的执行效率,而setAccessible(true)就是跳过安全检查以此来提高程序的执行效率,在实际开发中可根据实际需要进行相应的取舍。
以下是测试性能程序和运行结果截图
user.java
public class User {
public void sayHello(String name) {
}
}
ReflectionPerformanceTest.java
package com.maple.reflect.demo03;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.junit.Test;
/**
* 测试反射的执行效率
*
* @author MapleSky
*
*/
public class ReflectionPerformanceTest {
private static final String PATH
= "com.maple.reflect.demo03.User";
/**
* 使用普通调用sayHello方法一亿次
*/
public static void test01() {
User u = new User();
long start = System.currentTimeMillis();
for (int i = 0; i < 100_000_000; i++) {
u.sayHello("你好");
}
long end = System.currentTimeMillis();
System.out.println("普通方法调用sayHello方法一亿次所需时间"
+ (end - start) + "ms");
}
/**
* 使用反射调用sayHello 但不跳过安全检查
*/
public static void test02() {
try {
Class<?> clazz = Class.forName(PATH);
long start = System.currentTimeMillis();
Method sayHello = clazz.getDeclaredMethod("sayHello", String.class);
User u = new User();
for (int i = 0; i < 100_000_000; i++) {
sayHello.invoke(u, "你好");
}
long end = System.currentTimeMillis();
System.out.println("反射调用sayHello方法一亿次不跳过安全检查所需时间"
+ (end - start) + "ms");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
/**
* 使用反射调用sayHello 但不跳过安全检查
*/
public static void test03() {
try {
Class<?> clazz = Class.forName(PATH);
long start = System.currentTimeMillis();
Method sayHello = clazz.getDeclaredMethod("sayHello", String.class);
User u = new User();
sayHello.setAccessible(true);// 跳过安全检查
for (int i = 0; i < 100_000_000; i++) {
sayHello.invoke(u, "你好");
}
long end = System.currentTimeMillis();
System.out.println("反射调用sayHello方法一亿次——跳过安全检查所需时间"
+ (end - start) + "ms");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
@Test
public void app() {
test01();
test02();
test03();
}
}
运行结果