java反射效率

2023-04-12


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 
   * 

    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 
   * 
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 *

  113 
       * 测试的bean

  114 
       * 简单的int Integer String类型

  115 
       * 
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 }

本文仅代表作者观点,版权归原创者所有,如需转载请在文中注明来源及作者名字。

免责声明:本文系转载编辑文章,仅作分享之用。如分享内容、图片侵犯到您的版权或非授权发布,请及时与我们联系进行审核处理或删除,您可以发送材料至邮箱:service@tojoy.com