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 millions();
TestUser user=nullint I=0;while(i1000000){
我;
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(i1000000){
我;
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=null
class ruser class=class . for name( RefleDemo。TestUser’);int I=0;while(i1000000){
我;
user=(TestUser)ruser class . new instance();
} long end=system . current time millis();
System.out.println(通过缓存反射创建对象需要时间:(end-start) ms );
}//通过缓存反射创建一个对象耗时:41ms。其实我们从代码中可以发现,这个方法是Class.forName,它实际上是调用一个本地方法来要求JVM查找并加载指定的类。所以我们在项目中使用时,可以缓存Class.forName返回的类对象,下次使用时直接从缓存中获取,大大提高了获取类的效率。同样,当我们得到构造函数、方法和其他对象时,我们可以缓存它们以供使用,从而避免每次使用时浪费时间创建它们。
测试反射调用方法
@ test public void testReflexMethod()抛出异常{ 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(i100000000){
我;
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(i100000000){
我;
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反射的性能比较。
如何解决写爬虫IP受阻的问题?立即使用。
标签
综上所述,为了更好的使用反射,我们应该在项目启动的时候将反射所需要的相关配置及数据加载进内存中在运行时从缓存中取出这些元数据进行反射操作。你不必害怕反射。虚拟机不断得到优化。只要我们用对了方法,就没有“谣言”说的那么慢。当我们对性能有终极追求的时候,可以考虑通过三方包直接操作字节码。
相关教程:Java视频教程以上是如何提高使用Java反射效率的细节。请多关注我们的其他相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。