对各种方法实现get方法的性能进行了一个测试。

总共有5个测试,,每个测试都是执行1亿次

1. 直接通过Java的get方法

2.通过高性能的ReflectAsm库进行测试

3.通过Java Class类自带的反射获得Method测试

4.使用Java自带的Property类获取Method测试

5.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机器上跑以上测试,经过多次测量,基本在以下数值范围附近,测试数据如下:

1. directGet 100000000 times using 37 ms

2. reflectAsmGet 100000000 times using 39 ms

3. javaReflectGet 100000000 times using 222 ms

4. propertyGet 100000000 times using 335 ms

5. 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各种反射性能对比的更多相关文章

  1. 如何利用缓存机制实现JAVA类反射性能提升30倍

    一次性能提高30倍的JAVA类反射性能优化实践 文章来源:宜信技术学院 & 宜信支付结算团队技术分享第4期-支付结算部支付研发团队高级工程师陶红<JAVA类反射技术&优化> ...

  2. lua、groovy嵌入到java中的性能对比(转)

    lua和groovy都是可以嵌入到java中的脚本语言.lua以高性能著称,与C/C++在游戏开放中有较多使用,groovy是一个基于Java虚拟机(JVM)的敏捷动态语言,在jvm下有着不错的性能. ...

  3. 2017年的golang、python、php、c++、c、java、Nodejs性能对比(golang python php c++ java Nodejs Performance)

    2017年的golang.python.php.c++.c.java.Nodejs性能对比 本人在PHP/C++/Go/Py时,突发奇想,想把最近主流的编程语言性能作个简单的比较, 至于怎么比,还是不 ...

  4. 2017年的golang、python、php、c++、c、java、Nodejs性能对比[续]

    2017年的golang.python.php.c++.c.java.Nodejs性能对比[续] 最近忙,这个话题放了几天,今天来个续集.   上篇传送门: 2017年的golang.python.p ...

  5. iOS运行时编程(Runtime Programming)和Java的反射机制对比

    运行时进行编程,类似Java的反射.运行时编程和Java反射的对比如下:   1.相同点   都可以实现的功能:获取类信息.属性设置获取.类的动态加载(NSClassFromString(@“clas ...

  6. java数据库连接池性能对比

    这个测试的目的是验证当前常用数据库连接池的性能. testcase Connection conn = dataSource.getConnection(); PreparedStatement st ...

  7. [java]序列化框架性能对比(kryo、hessian、java、protostuff)

    序列化框架性能对比(kryo.hessian.java.protostuff) 简介:   优点 缺点 Kryo 速度快,序列化后体积小 跨语言支持较复杂 Hessian 默认支持跨语言 较慢 Pro ...

  8. java io读取性能对比

    背景 从最早bio的只支持阻塞的bio(同步阻塞) 到默认阻塞支持非阻塞nio(同步非阻塞+同步阻塞)(此时加入mmap类) 再到aio(异步非阻塞) 虽然这些api改变了调用模式,但真正执行效率上是 ...

  9. Java模板引擎性能对比

    模板引擎性能对比 从Github上翻到对JSP.Thymeleaf 3.Velocity 1.7.Freemarker 2.3.23几款主流模板的性能对比,总体上看,Freemarker.Veloci ...

随机推荐

  1. nodejs建站+github page 建站问题总结

    本文介绍 昨天吃晚饭的时候,在B站偶然看到一个关于搭建自己博客的视频,过程讲的很详细,于是就有了自己想尝试一下的冲动,所以,在晚上的时候,尝试了下,但是,过程并没有视频中说的那么顺利,看了网上很多帖子 ...

  2. golang map多层嵌套使用及遍历方法汇总

    原文:https://blog.csdn.net/boyhandsome7/article/details/79734847 ------------------------------------- ...

  3. ThreadPoolExecutor源码分析一

           在线程池出现之前,每次需要使用线程,都得创建一个线程.但是,在java的运行环境中,创建一个线程是非常耗费资源和时间的.是否可以把线程重复利用,减少线程的创建次数.基于此,java1.5 ...

  4. ElasticsearchException: java.io.IOException: failed to read [id:0, file:/data/elasticsearch/nodes/0/_state/global-0.st]

    from : https://www.cnblogs.com/hixiaowei/p/11213143.html 1.以前装过elasticsearch,重新安装elastic search ,报错 ...

  5. node.js----一个httpserver提交和解析get参数的例子

    前端代码 <!doctype html> <html lang="en"> <head> <meta charset="utf- ...

  6. BZOJ 2049: [Sdoi2008]Cave 洞穴勘测 (LCT维护连通性)

    直接把x设为根,然后查询y所在联通块的根是不是x就行了. CODE #include <cstdio> #include <cstring> #include <algo ...

  7. MFC 画笔CPen、画刷CBrush

    新建单个文档的MFC应用程序,类视图——View项的属性——消息,WM_PAINT,创建OnPaint()函数 dc默认有一个画笔(实心1像素宽黑线). CPen画笔非实心线像素宽必须为1,否则膨胀接 ...

  8. SP4546 ANARC08A - Tobo or not Tobo IDA*

    题意:

  9. HGOI 20191107 题解

    Problem A 树状数组 给出下列$C++$代码: 设区间加操作$modify(l,r)$为调用两次$update(r,1)$和$update(l-1,-1)$ 设$f(l,r)$表示在初始$cn ...

  10. 【csp模拟赛2】黑莲花--数据结构+数论

    没有什么能够阻挡,你对被阿的向往.天天 AK 的生涯,你的心了无牵挂. 虐过大佬的比赛,也曾装弱装逼.当你低头的瞬间,才发现旁边的人. 把你的四肢抬起来,使劲地往门上撞.盛开着永不凋零,黑莲花. —— ...