Java不同的反射方式性能对比
2018-01-06 22:46
405 查看
转载自:https://www.cnblogs.com/Frank-Hao/p/5839096.html#top
对各种方法实现get方法的性能进行了一个测试。
总共有5个测试,,每个测试都是执行1亿次
直接通过Java的get方法
通过高性能的ReflectAsm库进行测试
通过Java Class类自带的反射获得Method测试
使用Java自带的Property类获取Method测试
BeanUtils的getProperty测试
1.测试用Bean类
测试定义了如下一个bean类。
注意定义要严格遵守JavaBean规范,否则在使用和反射相关工具时会出现NoSuchMethodException异常,或者导致性能非常差,JavaBean规范中最重要的几点如下:
1.类必须是public, 拥有public无参构造器,这样能够通过反射newInstance()动态构建对象.
2.因为反射newInstance使用的是无参构造器, 所以对象实例化和配置是分开的
3.每一个property都有一个public的getter和setter方法, 命名方式是get/set+首字母大写的property名
经测试在SimpleBean为public时,1亿次调用method.invoke方法:
javaReflectGet 100000000 times using 218 ms
而SimpleBean为默认包可见时,1一亿次调用method.invoke方法:
javaReflectGet 100000000 times using 12955 ms
2.测试代码
3.测试结果
在4核i5-4590@3.30GHz机器上跑以上测试,经过多次测量,基本在以下数值范围附近,测试数据如下:
directGet 100000000 times using 37 ms
reflectAsmGet 100000000 times using 39 ms
javaReflectGet 100000000 times using 222 ms
propertyGet 100000000 times using 335 ms
beanUtilsGet 100000000 times using 20066 ms
4.结果分析
1.使用reflectAsm库的性能能和直接调用get方法持平
2.Java自带的反射性能大致为直接get的1/6和1/9.
3.BeanUtils的getProperty非常的慢,为直接get性能的1/500,为Java自带反射性能的1/100和1/60.
为什么BeanUtils的getProperty方法性能这么慢?
对各种方法实现get方法的性能进行了一个测试。
总共有5个测试,,每个测试都是执行1亿次
直接通过Java的get方法
通过高性能的ReflectAsm库进行测试
通过Java Class类自带的反射获得Method测试
使用Java自带的Property类获取Method测试
BeanUtils的getProperty测试
1.测试用Bean类
测试定义了如下一个bean类。
public class SimpleBean { private String name; public String getName() { return name; } public SimpleBean setName(String name) { this.name = name; } }
注意定义要严格遵守JavaBean规范,否则在使用和反射相关工具时会出现NoSuchMethodException异常,或者导致性能非常差,JavaBean规范中最重要的几点如下:
1.类必须是public, 拥有public无参构造器,这样能够通过反射newInstance()动态构建对象.
String className = ...; Class beanClass = Class.forName(className); Object beanInstance = beanClass.newInstance();
2.因为反射newInstance使用的是无参构造器, 所以对象实例化和配置是分开的
3.每一个property都有一个public的getter和setter方法, 命名方式是get/set+首字母大写的property名
经测试在SimpleBean为public时,1亿次调用method.invoke方法:
javaReflectGet 100000000 times using 218 ms
而SimpleBean为默认包可见时,1一亿次调用method.invoke方法:
javaReflectGet 100000000 times using 12955 ms
2.测试代码
public class TestIterator { private long times = 100_000_000L; private SimpleBean bean; private String formatter = "%s %d times using %d ms"; @Before public void setUp() throws Exception { bean = new SimpleBean(); bean.setName("haoyifen"); } //直接通过Java的get方法 @Test public void directGet() { Stopwatch watch = Stopwatch.createStarted(); for (long i = 0; i < times; i++) { bean.getName(); } watch.stop(); String result = String.format(formatter, "directGet", times, watch.elapsed(TimeUnit.MILLISECONDS)); System.out.println(result); } //通过高性能的ReflectAsm库进行测试,仅进行一次methodAccess获取 @Test public void reflectAsmGet() { MethodAccess methodAccess = MethodAccess.get(SimpleBean.class); Stopwatch watch = Stopwatch.createStarted(); for (long i = 0; i < times; i++) { methodAccess.invoke(bean, "getName"); } watch.stop(); String result = String.format(formatter, "reflectAsmGet", times, watch.elapsed(TimeUnit.MILLISECONDS)); System.out.println(result); } //通过Java Class类自带的反射获得Method测试,仅进行一次method获取 @Test public void javaReflectGet() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { Method getName = SimpleBean.class.getMethod("getName"); Stopwatch watch = Stopwatch.createStarted(); for (long i = 0; i < times; i++) { getName.invoke(bean); } watch.stop(); String result = String.format(formatter, "javaReflectGet", times, watch.elapsed(TimeUnit.MILLISECONDS)); System.out.println(result); } //使用Java自带的Property属性获取Method测试,仅进行一次method获取 @Test public void propertyGet() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, IntrospectionException { Method method = null; BeanInfo beanInfo = Introspector.getBeanInfo(SimpleBean.class); PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { if (propertyDescriptor.getName().equals("name")) { method = propertyDescriptor.getReadMethod(); break; } } Stopwatch watch = Stopwatch.createStarted(); for (long i = 0; i < times; i++) { method.invoke(bean); } watch.stop(); String result = String.format(formatter, "propertyGet", times, watch.elapsed(TimeUnit.MILLISECONDS)); System.out.println(result); } //BeanUtils的getProperty测试 @Test public void beanUtilsGet() throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { Stopwatch watch = Stopwatch.createStarted(); for (long i = 0; i < times; i++) { BeanUtils.getProperty(bean, "name"); } watch.stop(); String result = String.format(formatter, "beanUtilsGet", times, watch.elapsed(TimeUnit.MILLISECONDS)); System.out.println(result); } }
3.测试结果
在4核i5-4590@3.30GHz机器上跑以上测试,经过多次测量,基本在以下数值范围附近,测试数据如下:
directGet 100000000 times using 37 ms
reflectAsmGet 100000000 times using 39 ms
javaReflectGet 100000000 times using 222 ms
propertyGet 100000000 times using 335 ms
beanUtilsGet 100000000 times using 20066 ms
4.结果分析
1.使用reflectAsm库的性能能和直接调用get方法持平
2.Java自带的反射性能大致为直接get的1/6和1/9.
3.BeanUtils的getProperty非常的慢,为直接get性能的1/500,为Java自带反射性能的1/100和1/60.
为什么BeanUtils的getProperty方法性能这么慢?
相关文章推荐
- Java 集合 ArrayList和LinkedList的几种循环遍历方式及性能对比分析 [ 转载 ]
- Java HashMap遍历实践,看看不同方式的性能如何
- Java HashMap循环遍历方式及其性能对比
- java各种反射性能对比
- 选择,插入,希尔,快速,堆,归并排序六种排序方式的Java 实现和性能对比(付代码)
- Java 反射与cglib.proxy与cglib.beanmap与直接赋值 性能对比
- Java --- HashMap的四种循环遍历方式及性能对比
- Java 反射与cglib.proxy与cglib.beanmap与直接赋值 性能对比
- Java的动态性支持学习四 - 反射调用的性能对比
- Java 遍历文件夹的几种方式及简单性能对比
- Java反射三种方式的效率对比
- java反射与注解方式实现通用类属性对比
- java序列化方式性能比较
- SQLServer中批量插入数据方式的性能对比
- Java学习笔记之<反射、内省、BeanUtils包操作JavaBean的对比>
- [转]Java几款性能分析工具的对比
- java创建线程的三种方式及其对比
- Java中不同的并发实现的性能比较
- Dynamics CRM2016 查询数据的三种方式的性能对比
- java反射的性能问题