Java反射性能究竟如何?

本贴最后更新于 3141 天前,其中的信息可能已经斗转星移

以前的开发,都没有在项目中频繁使用反射的场景,我对反射的使用都局限于系统启动时,根据配置文件的内容反射来初始化某个对象。


新公司的一个项目很有意思,采用了领域驱动设计的思想设计,业务层操作的对象成为bo(business object),透明化了持久化层及持久层的实体(entity),若需要与持久层交互,则通过一个Convertor对象进行bo与entity间的转换。

例如,将一批User数据存入数据库:

		UserBo[] users = ...//一个长度为n的数组
		UserEntity[] entitys = new UserEntity[n];
		for(int i = 0;i<n;i++){
			TourGuideEntity entity = userConvertor.reverse(users[i]);
			entitys[i] = entity;
		}
		//通过hibernate持久化entitys

 

而Convertor类在编写时,由于entity中的属性较多,程序员们懒得去写一堆类似entity.SetName(bo.getName())的代码,于是通过反射直接去赋值,主要代码如下:

	//获取字段
	public static Field getField(Class<?> clazz, String fieldName) 
		for(Class<?> superClass = clazz; superClass != Object.class; superClass = superClass.getSuperclass()) {
			try {
				Field res = superClass.getDeclaredField(fieldName);
				return res;
			} catch(NoSuchFieldException e) {
				// Field不在当前类定义,继续向上转型
			}
		}
		return null;
	}
//设置字段值
public static void setField(Bo bo,Entity entity,Field f){
	Object value = f.get(bo);
	f.set(entity, value);
}</pre>


这套流程设计优雅,但性能是在是惨不忍睹。转换1.8万条数据居然花了120秒。。

用jvisualvm排查了一下,发现大量的时间消耗在了getField方法上。

简单看一下JDK的源码:

    public Field getDeclaredField(String name)
        throws NoSuchFieldException, SecurityException {
        checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
        Field field = searchFields(privateGetDeclaredFields(false), name);
        if (field == null) {
            throw new NoSuchFieldException(name);
        }
        return field;
    }
private static Field searchFields(Field[] fields, String name) {
    String internedName = name.intern();
    for (int i = 0; i &lt; fields.length; i++) {
        if (fields[i].getName() == internedName) {
            return getReflectionFactory().copyField(fields[i]);
        }
    }
    return null;
}</pre>




getField/getDeclaredField方法需要先通过privateGetDeclaredFields获取所有字段,然后遍历所有字段查找名称为name的,显然是十分低效的。

结论是,在反射中,getField方法非常耗时,set/get方法是很快的。

所以,我们应该尽量在初始化时就完成getField的工作,set/get时直接使用初始化时得到的field。

例如上面存储entity的例子,我们可以在Convertor中加一个init方法,在初始化时便通过反射去解析好bo、entity间的field,并建立其对应关系,在转换时直接使用这些对应关系即可。优化后,只需90毫秒就可完成1.8万数据的转换,速度提高了上千倍。


  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3169 引用 • 8207 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • mahengyang

    那样的话初始化岂不是非常慢?怎么开发的时候都哭死了

  • 其他回帖
  • sharmine2

    有没有想过使用 cglib? 或者使用 beanutils 的 copyproperties。当然这个解决方案也是很好的

  • someone

    cglib 是个好点子,或者干脆直接用 JDK 的动态代理?
    不过这玩意一般都是用于 service 层,在这个例子中得用到大量的 pojo 中,如何让代码简介优雅又兼顾性能还得好好设计一下[em01]。

  • huangxuan

    用反射起码的加上缓存 . 最好是用 cglib

  • 查看全部回帖

推荐标签 标签

  • ZooKeeper

    ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 HBase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

    59 引用 • 29 回帖 • 24 关注
  • MySQL

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。

    675 引用 • 535 回帖 • 1 关注
  • 链滴

    链滴是一个记录生活的地方。

    记录生活,连接点滴

    133 引用 • 3652 回帖
  • 笔记

    好记性不如烂笔头。

    305 引用 • 780 回帖
  • 职场

    找到自己的位置,萌新烦恼少。

    126 引用 • 1699 回帖
  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    82 引用 • 122 回帖 • 620 关注
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    108 引用 • 54 回帖 • 1 关注
  • 前端

    前端技术一般分为前端设计和前端开发,前端设计可以理解为网站的视觉设计,前端开发则是网站的前台代码实现,包括 HTML、CSS 以及 JavaScript 等。

    247 引用 • 1347 回帖
  • JSON

    JSON (JavaScript Object Notation)是一种轻量级的数据交换格式。易于人类阅读和编写。同时也易于机器解析和生成。

    51 引用 • 190 回帖 • 1 关注
  • Netty

    Netty 是一个基于 NIO 的客户端-服务器编程框架,使用 Netty 可以让你快速、简单地开发出一个可维护、高性能的网络应用,例如实现了某种协议的客户、服务端应用。

    49 引用 • 33 回帖 • 21 关注
  • Electron

    Electron 基于 Chromium 和 Node.js,让你可以使用 HTML、CSS 和 JavaScript 构建应用。它是一个由 GitHub 及众多贡献者组成的活跃社区共同维护的开源项目,兼容 Mac、Windows 和 Linux,它构建的应用可在这三个操作系统上面运行。

    15 引用 • 136 回帖 • 3 关注
  • JWT

    JWT(JSON Web Token)是一种用于双方之间传递信息的简洁的、安全的表述性声明规范。JWT 作为一个开放的标准(RFC 7519),定义了一种简洁的,自包含的方法用于通信双方之间以 JSON 的形式安全的传递信息。

    20 引用 • 15 回帖 • 19 关注
  • 锤子科技

    锤子科技(Smartisan)成立于 2012 年 5 月,是一家制造移动互联网终端设备的公司,公司的使命是用完美主义的工匠精神,打造用户体验一流的数码消费类产品(智能手机为主),改善人们的生活质量。

    4 引用 • 31 回帖 • 8 关注
  • RIP

    愿逝者安息!

    8 引用 • 92 回帖 • 292 关注
  • 微信

    腾讯公司 2011 年 1 月 21 日推出的一款手机通讯软件。用户可以通过摇一摇、搜索号码、扫描二维码等添加好友和关注公众平台,同时可以将自己看到的精彩内容分享到微信朋友圈。

    129 引用 • 793 回帖
  • TGIF

    Thank God It's Friday! 感谢老天,总算到星期五啦!

    284 引用 • 4481 回帖 • 656 关注
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    25 引用 • 191 回帖 • 21 关注
  • Webswing

    Webswing 是一个能将任何 Swing 应用通过纯 HTML5 运行在浏览器中的 Web 服务器,详细介绍请看 将 Java Swing 应用变成 Web 应用

    1 引用 • 15 回帖 • 635 关注
  • NGINX

    NGINX 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 NGINX 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本 0.1.0 发布于 2004 年 10 月 4 日。

    311 引用 • 546 回帖 • 32 关注
  • CloudFoundry

    Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。

    5 引用 • 18 回帖 • 153 关注
  • GitLab

    GitLab 是利用 Ruby 一个开源的版本管理系统,实现一个自托管的 Git 项目仓库,可通过 Web 界面操作公开或私有项目。

    46 引用 • 72 回帖 • 1 关注
  • ReactiveX

    ReactiveX 是一个专注于异步编程与控制可观察数据(或者事件)流的 API。它组合了观察者模式,迭代器模式和函数式编程的优秀思想。

    1 引用 • 2 回帖 • 126 关注
  • Telegram

    Telegram 是一个非盈利性、基于云端的即时消息服务。它提供了支持各大操作系统平台的开源的客户端,也提供了很多强大的 APIs 给开发者创建自己的客户端和机器人。

    5 引用 • 35 回帖
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3169 引用 • 8207 回帖
  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖 • 1 关注
  • CSDN

    CSDN (Chinese Software Developer Network) 创立于 1999 年,是中国的 IT 社区和服务平台,为中国的软件开发者和 IT 从业者提供知识传播、职业发展、软件开发等全生命周期服务,满足他们在职业发展中学习及共享知识和信息、建立职业发展社交圈、通过软件开发实现技术商业化等刚性需求。

    14 引用 • 155 回帖
  • 996
    13 引用 • 200 回帖