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 
  }