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 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值