`
yajie
  • 浏览: 210824 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

看看java的反射效率

阅读更多

java反射效率到底如何,花了点时间,做了一个简单的测试.供大家参考.

测试背景:
1. 测试简单Bean(int,Integer,String)的set方法
2. loop 1亿次
3. 测试代码尽可能避免对象的创建,复发方法的调用,仅仅测试set方法的耗时

测试结果:

 场景  本机测试结果(XP,双核,2G) 服务器测试结果(Linux,XEN虚拟机,8核,5.5G)
方法直接调用 235MS 190MS
JDK Method调用
29188MS
4633MS
JDK Method调用(稍作优化)
5672MS
4262MS
Cglib FastMethod调用
5390MS
2787MS


得出一个感性的结果:
1.JDK反射效率是直接调用的一个数量级,差不多20倍
2.一个set方法的反射调用时间 = 4633ms / 1亿 / 3次 = 0.0154us
3.Cglib的fastmethod还是有优势的

最后,附上测试代码:

  1  /**
  2   * <pre>
  3   * 本机测试结果(XP,双核,2G):
  4   * 直接调用(LOOP=1亿):       235MS 
  5   * 反射调用(LOOP=1亿):       29188MS
  6   * 反射调用(优化)(LOOP=1亿):  5672MS
  7   * 放射调用(CGLIB)(LOOP=1亿):5390MS
  8   * 
  9   * 服务器测试结果(linux xen虚拟机,5.5G内存;8核CPU):
 10   * 直接调用(LOOP=1亿):       190MS
 11   * 反射调用(LOOP=1亿):       4633MS
 12   * 反射调用(优化)(LOOP=1亿):  4262MS
 13   * 放射调用(CGLIB)(LOOP=1亿):2787MS
 14   * </pre>
 15   * 
 16   *  @author  Stone.J 2010-9-15 上午10:07:27
 17    */
 18  public   class  ReflectionTest {
 19  
 20       private   static   final   int                       DEFAULT_INT                 =   1 ;
 21       private   static   final  Integer                  DEFAULT_INTEGER             =   1 ;
 22       private   static   final  String                   DEFAULT_STRING              =   " name " ;
 23       private   static   final  Object[]                 DEFAULT_INTS                =  {  1  };
 24       private   static   final  Object[]                 DEFAULT_INTEGERS            =   new  Integer[] {  1  };
 25       private   static   final  Object[]                 DEFAULT_STRINGS             =   new  String[] {  " name "  };
 26  
 27       private   static   final  Bean                     BEAN                        =   new  Bean();
 28  
 29       private   static   final  CachedMethod             CACHED_METHOD               =   new  CachedMethod();
 30       private   static   final  OptimizationCachedMethod OPTIMIZATION_CACHED_METHOD  =   new  OptimizationCachedMethod();
 31       private   static   final  CglibCachedMethod        CGLIB_CACHED_METHOD         =   new  CglibCachedMethod();
 32  
 33       private   static   final   long                      LOOP                        =   1   *   10000   *   10000 ;
 34  
 35       //  测试main
 36       public   static   void  main(String[] args) {
 37           if  (args.length  !=   1 ) {
 38              System.out.println( " args error. " );
 39              System.exit( 1 );
 40          }
 41           int  tc  =  Integer.valueOf(args[ 0 ]);
 42  
 43           long  start  =  System.currentTimeMillis();
 44           for  ( long  i  =   0 ; i  <  LOOP; i ++ ) {
 45               switch  (tc) {
 46                   case   1 :
 47                       //  直接调用
 48                      test();
 49                       break ;
 50                   case   2 :
 51                       //  反射调用
 52                      testReflection();
 53                       break ;
 54                   case   3 :
 55                       //  优化后反射调用
 56                      testOptimizationReflection();
 57                       break ;
 58                   case   4 :
 59                       //  cglib反射调用
 60                      testCglibReflection();
 61                       break ;
 62                   default :
 63                      System.out.println( " tc error. must be [1-4] " );
 64                       break ;
 65              }
 66          }
 67           long  dur  =  System.currentTimeMillis()  -  start;
 68          System.out.println(dur);
 69      }
 70  
 71       //  直接调用测试
 72       public   static   void  test() {
 73          BEAN.setId(DEFAULT_INT);
 74          BEAN.setCode(DEFAULT_INTEGER);
 75          BEAN.setName(DEFAULT_STRING);
 76      }
 77  
 78       //  反射调用测试
 79       public   static   void  testReflection() {
 80           try  {
 81              CACHED_METHOD.setId.invoke(BEAN, DEFAULT_INTS);
 82              CACHED_METHOD.setCode.invoke(BEAN, DEFAULT_INTEGERS);
 83              CACHED_METHOD.setName.invoke(BEAN, DEFAULT_STRINGS);
 84          }  catch  (Exception e) {
 85              e.printStackTrace();
 86          }
 87      }
 88  
 89       //  优化后反射调用测试
 90       public   static   void  testOptimizationReflection() {
 91           try  {
 92              OPTIMIZATION_CACHED_METHOD.setId.invoke(BEAN, DEFAULT_INTS);
 93              OPTIMIZATION_CACHED_METHOD.setCode.invoke(BEAN, DEFAULT_INTEGERS);
 94              OPTIMIZATION_CACHED_METHOD.setName.invoke(BEAN, DEFAULT_STRINGS);
 95          }  catch  (Exception e) {
 96              e.printStackTrace();
 97          }
 98      }
 99  
100       //  cglib反射调用测试
101       public   static   void  testCglibReflection() {
102           try  {
103              CGLIB_CACHED_METHOD.cglibSetId.invoke(BEAN, DEFAULT_INTS);
104              CGLIB_CACHED_METHOD.cglibSetCode.invoke(BEAN, DEFAULT_INTEGERS);
105              CGLIB_CACHED_METHOD.cglibSetName.invoke(BEAN, DEFAULT_STRINGS);
106          }  catch  (Exception e) {
107              e.printStackTrace();
108          }
109      }
110  
111       /**
112       * <pre>
113       * 测试的bean
114       * 简单的int Integer String类型
115       * </pre>
116       * 
117       *  @author  Stone.J 2010-9-15 上午10:40:40
118        */
119       public   static   class  Bean {
120  
121           private   int      id;
122           private  Integer code;
123           private  String  name;
124  
125           public   int  getId() {
126               return  id;
127          }
128  
129           public   void  setId( int  id) {
130               this .id  =  id;
131          }
132  
133           public  Integer getCode() {
134               return  code;
135          }
136  
137           public   void  setCode(Integer code) {
138               this .code  =  code;
139          }
140  
141           public  String getName() {
142               return  name;
143          }
144  
145           public   void  setName(String name) {
146               this .name  =  name;
147          }
148  
149      }
150  
151       /**
152       * 反射测试需要:Cached Method
153       * 
154       *  @author  Stone.J 2010-9-15 上午10:41:04
155        */
156       public   static   class  CachedMethod {
157  
158           public  Method setId;
159           public  Method setCode;
160           public  Method setName;
161  
162          {
163               try  {
164                  setId  =  Bean. class .getDeclaredMethod( " setId " int . class );
165                  setCode  =  Bean. class .getDeclaredMethod( " setCode " , Integer. class );
166                  setName  =  Bean. class .getDeclaredMethod( " setName " , String. class );
167              }  catch  (Exception e) {
168                  e.printStackTrace();
169              }
170          }
171  
172      }
173  
174       /**
175       * 反射测试需要:优化后的Cached Method
176       * 
177       *  @author  Stone.J 2010-9-15 上午10:41:21
178        */
179       public   static   class  OptimizationCachedMethod  extends  CachedMethod {
180  
181          {
182               /**  所谓的优化  */
183              setId.setAccessible( true );
184              setCode.setAccessible( true );
185              setName.setAccessible( true );
186          }
187  
188      }
189  
190       /**
191       * 反射测试需要,使用cglib的fast method
192       * 
193       *  @author  Stone.J 2010-9-15 上午10:51:53
194        */
195       public   static   class  CglibCachedMethod  extends  CachedMethod {
196  
197           public  FastMethod cglibSetId;
198           public  FastMethod cglibSetCode;
199           public  FastMethod cglibSetName;
200  
201           private  FastClass cglibBeanClass  =  FastClass.create(Bean. class );
202  
203          {
204              cglibSetId  =  cglibBeanClass.getMethod(setId);
205              cglibSetCode  =  cglibBeanClass.getMethod(setCode);
206              cglibSetName  =  cglibBeanClass.getMethod(setName);
207          }
208  
209      }
210  
211  }
3
3
分享到:
评论
6 楼 yajie 2011-10-09  
gzdx968342 写道
反射效率低是众所周知的,想知道的是反射的妙用

反射其实就是程序能够自检查自身信息。就像程序会照镜子反光看自己。
在程序中可以检查某个类中的方法属性等信息,并且能够动态调用。
这样可以写出很灵活的程序。
比如要把一个对象中的数据copy到另外一个对象中,规则是属性名相同就copy,
就可以用反射来做,不需要指定每个属性的名字,只要动态从类中取得信息,
再判断属性名是否相同即可。当然应用还有很多。

反射可以结合Java的字节码,使用ASM和cglib等库,还能动态生成类。
hibernate的延迟载入,spring的AOP都是这么实现的

反射给Java带来了一些动态性。不过虽然很好,但毕竟还是有一定局限性的。另外ASM,cglib使用还是不放便。因此一些纯动态语言现在是一个重要发展趋势,比如ruby,python等,程序很容易动态生成。
5 楼 gzdx968342 2011-10-09  
反射效率低是众所周知的,想知道的是反射的妙用
4 楼 Rex86lxw 2011-10-08  
1楼说的不错,反射的应用就像解方程一样,有时知道了结果需要知道些逆向的数据,一般用来写底层应用
3 楼 雅马哈大野熊 2011-10-08  
反射,究竟是为了什么呢?
2 楼 i2534 2011-10-08  
jackra 写道
使用反射不是为了效率

赞同.
多次调用可以使用缓存,考虑空间换时间
1 楼 jackra 2011-10-08  
使用反射不是为了效率

相关推荐

    JAVA-提高反射效率

    ### JAVA-提高反射效率 #### 一、反射技术概述 反射是Java中一项强大的功能,它允许程序在运行时检查类、接口、字段和方法的信息,并且可以动态地调用方法或修改字段值。这种能力使得Java程序具有高度的灵活性和可...

    java 反射 线程ppt

    接下来,我们来看看Java线程。Java提供了两种创建线程的方式:继承Thread类和实现Runnable接口。继承Thread类直接覆盖run()方法,而实现Runnable接口则需要重写run()方法,并通过Thread类的构造函数传入Runnable对象...

    java反射封装结果集内容到pojo

    当我们从数据库读出数据得到ResultSet或RowSet的时候,我们的做法是遍历结果集,然后封装到pojo里面,再封装到List,那么,每次封装是不是很麻烦呢,前段时间小弟看了下反射的东西,试着写了个类,目的在于方便封装...

    java基础,多线程,反射

    Java反射机制允许在运行时检查类、接口、字段和方法的信息,甚至可以在运行时动态创建对象并调用其方法。这为程序提供了极大的灵活性,特别是在框架开发和元编程中。通过`java.lang.Class`类和`java.lang.reflect`...

    java 基于泛型与反射的通用 DAO

    在Java编程语言中,泛型和反射是两个非常重要的特性,它们可以极大地提高代码的复用性和灵活性。本文将深入探讨如何结合这两种技术实现一个通用的DAO(Data Access Object)设计模式。 首先,我们来看“泛型”。...

    java 代码反射生成工具_generatorConfig

    Java反射API是Java标准库的一部分,包含在`java.lang.reflect`包中。通过反射,开发者可以在运行时获取关于类、接口、字段和方法的信息,并能够动态调用方法或访问字段。例如,`Class`类是反射的核心,可以用来获取...

    java反射例子

    首先,从标题“java反射例子”来看,这部分内容将围绕Java反射技术的具体应用展开。Java反射API提供的主要类包括java.lang.Class、java.lang.reflect.Constructor、java.lang.reflect.Method和java.lang.reflect....

    不错的java教案,可以看看

    9. **反射机制**:Java的反射机制允许在运行时检查类的信息,创建和操作类的对象,是实现动态编程的关键。 10. **泛型**:泛型是Java 5引入的特性,增强了代码的类型安全性和可读性。教案会讲述泛型的基本用法和...

    Java工程师不得不看的几千份代码

    7. **反射与动态代理**:Java的反射机制允许在运行时检查和修改类、接口、字段和方法,而动态代理则可以创建代理对象以实现额外的功能。这两者在插件开发、测试和AOP(面向切面编程)中有广泛应用。 8. **JVM内存...

    java基础知识题(学Java的可以看看)

    这份"java基础知识题(学Java的可以看看)"的资料集包含了学习Java基础知识的重要题目,对于初学者或是希望巩固基础的开发者来说,是一份非常有价值的资源。其中的"java.xls"文件很可能是一个包含各种Java题目和解答的...

    java导入导出通用模板

    Java编程语言在处理数据导入和导出时,经常会用到一些通用模板,以提高代码的复用性和...这种模板化的设计模式在Java开发中具有广泛的应用价值,尤其是在处理大量数据和多变的需求时,能显著提升开发效率和代码质量。

    java问题汇总(学习JAVA必看)

    11. **Java 8及以后的新特性**:Java 8引入了函数式编程元素,如Lambda表达式和Stream API,提高了代码的简洁性和效率。后续版本如Java 9至Java 17也引入了模块系统、局部变量类型推断(var关键字)等新特性。 以上...

    Java学习笔记(必看经典)

    这份“Java学习笔记(必看经典)”涵盖了Java语言的基础到进阶内容,对于想要深入理解Java的开发者来说是一份宝贵的资源。 首先,Java语言基础包括语法结构、数据类型、变量、运算符、流程控制等。Java支持两种主要的...

    Java必备工具包

    通过这个CHM(Compiled Help Manual)文件,开发者可以轻松查找和了解Java 5.0中的核心类库,如集合框架、多线程、I/O流、网络编程、反射等。了解API有助于写出更高效、更规范的代码。 2. **swt.CHM**: SWT...

    java多线程反射泛型及正则表达式学习笔记和源码.zip

    在Java中,多线程允许程序同时执行多个不同的任务,提高了程序的并发性和效率。Java提供了两种创建线程的方式:通过实现Runnable接口或者继承Thread类。线程间通信是多线程编程中的重要课题,包括共享变量、wait/...

    java code,很好的java代码,可以看看

    8. **反射机制**:Java反射机制允许程序在运行时动态获取类的信息并操作类的对象,增强了程序的灵活性。 9. **泛型**:自Java 5引入泛型后,可以在编译时检查类型安全,避免了类型转换的麻烦。 10. **注解...

    Java笔记-通过反射获取注解及Spring中获取某包下的所有class文件

    总结起来,Java反射和Spring提供的工具使我们能够动态地访问和操作类的注解信息,以及方便地遍历指定包下的所有类。这些功能在开发中非常实用,特别是在实现如自动扫描、配置处理和组件注册等功能时。了解并熟练运用...

    JAVA 实用教程 JDP java 源码 动态创建

    1. **反射(Reflection)**:Java反射API允许我们在程序运行时检查类、接口、字段和方法的信息,甚至可以实例化对象、调用方法和修改字段值。这是动态创建的关键部分,因为它使我们能够在运行时发现并操作类的内部...

    javaAPI中文版

    8. **反射**:`java.lang.reflect`包提供了反射API,允许程序在运行时检查和修改类、接口、字段和方法的信息,增强了代码的灵活性。 9. **日期和时间**:`java.time`包是Java 8引入的新特性,提供了更强大的日期、...

Global site tag (gtag.js) - Google Analytics