如何提高使用java反射的效率的方法(如何提高使用java反射的效率和效率)
如何提高使用java反射的效率的方法(如何提高使用java反射的效率和效率),本文通过数据整理汇集了如何提高使用java反射的效率的方法(如何提高使用java反射的效率和效率)相关信息,下面一起看看。
前言在我们平时的工作或者面试中,经常会遇到“反射”这个知识点。通过反射,可以动态获取对象的信息,灵活调用对象的方法等。但是在使用的同时,又出现了另一种声音,就是“反射”慢,要少用。反思真的很慢吗?比我们平时创建对象调用方法慢多少?估计很多人都没考,只是“道听途说”。让我们通过一些测试案例直接感受一下“反映”。
首先,在主体测试对象下定义一个测试类TestUser,只有id和name属性,以及它们的getter/setter方法,还有一个自定义的sayHi方法。
公共类TestUser {私有整数id;私有字符串名称;公共字符串say hi(){ return ' hi ';}公共整数getId(){ return id;} public void setId(Integer id){ this . id=id;} public String getName(){ return name;} public void set name(String name){ this . name=name;}}测试创建100万个对象//创建一个TestUser对象@ Test public void Test common(){ long start=system . current time millis();TestUser user=nullint I=0;while(I 1000000){ I;user=new TestUser();} long end=system . current time millis();System.out.println('公共对象创建需要时间:'(end-start)' ms ');}//普通对象创建耗时:10ms//通过reflection创建TestUser对象@ test public void testreflexnocache()throws exception { long start=system . current Time millis();TestUser user=nullint I=0;while(I 1000000){ I;user=(TestUser)class . for name(' reflex demo。TestUser’)。new instance();} long end=system . current time millis();System.out.println('创建没有缓存反射的对象需要时间:'(end-start)' ms ');}//创建没有缓存反射的对象耗时:926ms。在以上两种测试方法中,作者分别测量了五次,取其时间的平均值。在输出结果中,可以看到一个是10ms,一个是926ms。在创建100W对象的情况下,反射实际上慢了大约90倍。wtf?差距这么大?反思真的这么慢吗?我们换个反思的姿势,继续测试,看看结果如何。
//创建TestUser对象@ test public void testreflexwithcache()throws exception { long start=system . current time millis();TestUser user=nullclass ruser class=class . for name(' RefleDemo。TestUser’);int I=0;while(I 1000000){ I;user=(TestUser)ruser class . new instance();} long end=system . current time millis();System.out.println('通过缓存反射创建对象需要时间:'(end-start)' ms ');}//通过缓存反射创建对象耗时:41ms?这个操作只需要41ms,大大提高了反射创建对象的效率。为什么这么快?
其实通过代码我们可以发现Class.forName方法比较耗时,它实际上调用的是一个本地方法,通过这个方法要求JVM找到并加载指定的类。所以我们在项目中使用时,可以缓存Class.forName返回的类对象,下次使用时直接从缓存中获取,大大提高了获取类的效率。同样,当我们得到构造函数、方法和其他对象时,我们可以缓存它们以供使用,从而避免每次使用时浪费时间创建它们。
测试反射调用方法@ test public void testreflexmethod()throws exception { long start=system;current time millis();class testuser class=class . forname(' RefleDemo。TestUser’);TestUser TestUser=(TestUser)TestUser class . new instance();method method=testuser class . get method(' say hi ');int I=0;while(I 100000000){ I;method . invoke(testUser);} long end=system . current time millis();System.out.println('反射调用方法耗时:'(end-start)' ms ');}//通过反射调用方法耗时:330 ms @ testpublic void testreflexmethod()throws exception { long start=system . current Time millis();class testuser class=class . forname(' RefleDemo。TestUser’);TestUser TestUser=(TestUser)TestUser class . new instance();method method=testuser class . get method(' say hi ');int I=0;while(I 100000000){ I;method . set accessible(true);method . invoke(testUser);} long end=system . current time millis();系统;out . println(' set accessible=true '反映调用该方法所用的时间:'(end-start)' ms ');}//setAccessible=true反映调用方法耗时:188ms这里我们反映调用sayHi方法一亿次。调用method.setAccessible(true)后,我们发现快了将近一半。看API可以知道,jdk在设置get字段和调用方法时会进行安全访问检查,这种操作会比较耗时,所以可以通过设置setAccessible(true)关闭安全检查,从而提高反射效率。
除了以上手段,还有什么方法可以把反射用到极致?本文介绍了一个高性能的反射工具包ReflectASM。它是通过字节码生成实现的反射机制。下面是与java反射的性能比较。
所以这里就不介绍它的用法了,有兴趣的朋友可以直接发过来:200000000001
http 0 . 6352 . 468686866665
s0 . 58660 . 58686868661
://0.6177741935299914
github 0 . 54860 . 38888886861
. com 58660 . 48686868686
/深奥的软件/反射
最后总结一下,为了更好的利用反射,我们应该在项目启动时将反射所需的相关配置和数据加载到内存中,在运行阶段从缓存中取出这些元数据进行反射操作。你不必害怕反射。虚拟机不断得到优化。只要我们用对了方法,就没有“谣言”说的那么慢。当我们对性能有终极追求的时候,可以考虑通过三方包直接操作字节码。
0.6947710898076429
http 0 . 6352 . 468686866665
s0 . 58660 . 58686868661
://0.6177741935299914
github 0 . 54860 . 38888886861
. com 58660 . 48686868686
/peppalittlepg/博客-微信
推荐阅读《Java日志正确使用姿势》 《使用ConcurrentHashMap一定线程安全?》 《大白话搞懂什么是同步/异步/阻塞/非阻塞》 《论JVM爆炸的几种姿势及自救方法》
如果你有收获,请点赞。
关注《深夜的程》分享最干的干货。
更多如何提高使用java反射的效率的方法(如何提高使用java反射的效率和效率)相关信息请关注本站,本文仅仅做为展示!