对各种方法实现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. 关于pycharm database查看db.sqlites文件提示:Driver class 'org.sqlite.JDBC' not found

    系统重新安装后,启动pycharm存在各种问题,其中一个问题就是在Pycharm中的database里面不能查看sqlite数据库了: 经过一番查找终于找到了问题: 首先问题 是提示这样一个报错: 解 ...

  2. input子系统驱动

    input子系统驱动 框架分析 核心层 文件为:/drivers/input/input.c: 首先找到入口函数为**static int __init input_init(void)**,在该函数 ...

  3. asterisk搭建goip

    利用asterisk来搭建goip使用,步骤如下: 第一步:先需要搭建centos服务器并优化 搭建centos服务器就省略: 优化centos服务器,进行如下步骤: 关闭防火墙:systemctl ...

  4. String 类的常用方法都有那些?(未完成)

    String 类的常用方法都有那些?(未完成)

  5. 小A的数学题

    小A最近开始研究数论题了,这一次他随手写出来一个式子, 但是他发现他并不太会计算这个式子,你可以告诉他这个结果吗,答案可能会比较大,请模上1000000007. 输入描述: 一行两个正整数n,m一行两 ...

  6. okhttp拦截器之RetryAndFollowUpInterceptor&BridgeInterceptor分析

    在上一次[https://www.cnblogs.com/webor2006/p/9096412.html]对okhttp的拦截器有了一个初步的认识,接下来则对具体的拦截器一个个进行了解. Retry ...

  7. MAC 环境下搭建HttpRunnerManager平台

    1 . mac pycharm 创建虚拟环境 https://blog.csdn.net/qq_39806105/article/details/96908584 2. mac 环境下搭建HttpRu ...

  8. redis cluster 介绍

    介绍 1. cluster的作用 (1)自动将数据进行分片,每个master上放一部分数据 (2)提供内置的高可用支持,部分master不可用时,还是可以继续工作的 2. redis集群实现方案 关于 ...

  9. Git 命令行解决冲突

    git add filename   将本地工作区文件加入缓存区 git commit filename -m '提交文件注释' git status  查看当前工作区状态 git fetch ori ...

  10. 通俗理解数字签名,ssl数字证书和https

    前言 最近在开发关于PDF合同文档电子签章的功能,大概意思就是在一份PDF合同上签名,盖章,使其具有法律效应.签章有法律效应必须满足两个条件: 能够证明签名,盖章者是谁,无法抵赖 PDF合同在签章后不 ...