Java反射性能


Answers:


169

是的,一点没错。通过反射查找课程,从数量上讲,更昂贵。

引用Java的反射文档

由于反射涉及动态解析的类型,因此无法执行某些Java虚拟机优化。因此,反射操作的性能要比非反射操作慢,因此应该避免在对性能敏感的应用程序中经常调用的代码段中。

这是一个简单的测试,我在运行Sun JRE 6u10的计算机上用5分钟的时间破解了它:

public class Main {

    public static void main(String[] args) throws Exception
    {
        doRegular();
        doReflection();
    }

    public static void doRegular() throws Exception
    {
        long start = System.currentTimeMillis();
        for (int i=0; i<1000000; i++)
        {
            A a = new A();
            a.doSomeThing();
        }
        System.out.println(System.currentTimeMillis() - start);
    }

    public static void doReflection() throws Exception
    {
        long start = System.currentTimeMillis();
        for (int i=0; i<1000000; i++)
        {
            A a = (A) Class.forName("misc.A").newInstance();
            a.doSomeThing();
        }
        System.out.println(System.currentTimeMillis() - start);
    }
}

结果如下:

35 // no reflection
465 // using reflection

请记住,查找和实例化是一起完成的,在某些情况下,可以重构查找,但这只是一个基本示例。

即使您实例化了,您仍然会受到性能影响:

30 // no reflection
47 // reflection using one lookup, only instantiating

再次,YMMV。


5
在我的计算机上,只有一个Class.forName()调用的.newInstance()得分为30左右。根据VM版本的不同,差异可能会比使用适当的缓存策略时所想的要近。
肖恩·赖利

56
下面的@Peter Lawrey指出,此测试完全无效,因为编译器正在优化非反射解决方案(它甚至可以证明什么都不做,并且可以优化for循环)。需要进行重新处理,并且可能应该从SO中删除这些不良/误导性信息。在两种情况下都将创建的对象缓存在数组中,以防止优化器对其进行优化。(它不能在反射情况下执行此操作,因为它不能证明构造函数没有副作用)
Bill K

6
@Bill K-让我们不要被迷住。是的,由于优化,该数字不可用。不,测试并非完全无效。我添加了一个调用,该调用消除了任何使结果倾斜的可能性,并且数字仍在堆叠以防反射。无论如何,请记住,这是一个非常粗糙的微基准,仅表明反射总是会产生一定的开销
Yuval Adam

4
这可能是无用的基准。取决于doSomething的功能。如果它没有任何明显的副作用,则您的基准测试仅运行无效代码。
nes1983

9
我只是目睹了JVM优化反射35倍。循环运行测试是测试优化代码的方式。第一次迭代:3045ms,第二次迭代:2941ms,第三次迭代:90ms,第四次迭代:83ms。代码:c.newInstance(i)。c是构造函数。非反射代码:新的A(i),产生13、4、3 .. ms毫秒的时间。所以是的,这种情况下的反射很慢,但没有人得出的结论慢很多,因为我看到的每个测试都只是运行了一次测试,而没有给JVM机会用机器替换字节码码。
Mike
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.