看看java的反射效率

看看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  }
原文地址:https://www.cnblogs.com/hasv/p/2207073.html