对各种方法实现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. Linux基础使用

    Linux中,日志所在的位置: /var/log/messages     系统默认的日志 /var/log/secure         记录用户的登录信息 查看日志的方法有很多 :head     ...

  2. FirstWriting

    在很久很久以前,你拥有我我拥有你 <外面的世界> 在很久很久以前我就有搞一个类似博客的东西的想法,不过一直都没有尝试着搞-- 某天(10号左右吧)刷知乎看到github和hexo可以搭建博 ...

  3. 前端自动化构建工具 Webpack——3 webpack配置文件的使用

  4. 微信小程序开发框架 Wepy 的使用

    一.github地址:https://github.com/Tencent/wepy 按照 README.md 的步骤进行操作: 1.在“介绍”中获得 wepy 的开发资源汇总:https://git ...

  5. Unity 截图选择框,中间全透明,边缘半透明

    效果:点击白色框可拖拽选择区域 代码: using System.Collections; using System.Collections.Generic; using UnityEngine; u ...

  6. IDEA Java

    目录 1 配置 2 常用快捷键 3 安装插件 4 使用Maven创建web项目 5 使用Maven导入依赖 6 Maven创建项目后缺少文件夹 7 Tomcat LocalHost Log消失 8 E ...

  7. Xilinx的IP核接口命名说明

    s_axis中的s表示:slave(从); m_axis中的m表示:master(主). axis表示AXI(一种总线协议) Signal.

  8. Luogu P5018 对称二叉树 瞎搞树&哈希

    我的天..普及组这么$hard$... 然后好像没有人用我的垃圾做法,,,好像是$O(n)$,但十分的慢,并且极其暴力$qwq$ 具体来说,就是直接$dfs$求出树高,然后想像出把原来的树补成满二叉树 ...

  9. 2019CCPC秦皇岛自我反省&部分题解

    练了一年半了,第一次打CCPC,险些把队友坑了打铁,最后也是3题危险捡了块铜. 非常水的点双连通,我居然不相信自己去相信板子,唉,结果整来整去,本来半个小时能出的题,整到了3个小时,大失误呀,不然就可 ...

  10. 【原创】洛谷 LUOGU P3379 【模板】最近公共祖先(LCA) -> 倍增

    P3379 [模板]最近公共祖先(LCA) 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询 ...