首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

见见java的反射效率

2012-12-28 
看看java的反射效率java反射效率到底如何,花了点时间,做了一个简单的测试.供大家参考.测试背景:1. 测试简

看看java的反射效率

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

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

测试结果:

?场景?本机测试结果(XP,双核,2G)服务器测试结果(Linux,XEN虚拟机,8核,5.5G)
方法直接调用235MS190MSJDK 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?} 1 楼 jackra 2011-10-08   使用反射不是为了效率 2 楼 i2534 2011-10-08   jackra 写道使用反射不是为了效率
赞同.
多次调用可以使用缓存,考虑空间换时间 3 楼 雅马哈大野熊 2011-10-08   反射,究竟是为了什么呢? 4 楼 Rex86lxw 2011-10-08   1楼说的不错,反射的应用就像解方程一样,有时知道了结果需要知道些逆向的数据,一般用来写底层应用 5 楼 gzdx968342 2011-10-09   反射效率低是众所周知的,想知道的是反射的妙用 6 楼 yajie 2011-10-09   gzdx968342 写道反射效率低是众所周知的,想知道的是反射的妙用
反射其实就是程序能够自检查自身信息。就像程序会照镜子反光看自己。
在程序中可以检查某个类中的方法属性等信息,并且能够动态调用。
这样可以写出很灵活的程序。
比如要把一个对象中的数据copy到另外一个对象中,规则是属性名相同就copy,
就可以用反射来做,不需要指定每个属性的名字,只要动态从类中取得信息,
再判断属性名是否相同即可。当然应用还有很多。

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

反射给Java带来了一些动态性。不过虽然很好,但毕竟还是有一定局限性的。另外ASM,cglib使用还是不放便。因此一些纯动态语言现在是一个重要发展趋势,比如ruby,python等,程序很容易动态生成。

热点排行