java,反射,表现等

Kev*_*vin 14 java reflection

所以我知道之前已经完成了这个主题,例如Java Reflection Performance,但我的特殊问题是,似乎很多流行的库都是通过注释和反射来实现的(例如Gson,Jackson,Jaxb实现,hibernate搜索).许多(如果不是全部)库提供良好(或很好)的性能,即使它们使用反射.我的问题是,他们是如何做到的?是否有一些"技巧"要知道或者他们只是使用直接反射,而表演的担忧是夸大其词?

编辑:例如,当我们写:MyObject obj = new Gson().fromJson(someInputStream,MyObject.class);

我可以理解库如何在内部缓存Field对象,但在我看来,它需要每次都反射性地实例化对象,并且它需要根据json的解析值调用每个字段上的setter(反射) .或者有没有办法只在启动时支付(全部)反射成本?

我肯定注意到Gson/Jackson等具有相对较大的启动成本,之后非常快.所以很明显我想知道,如果我写一个模糊相似的图书馆,我需要了解一些技巧吗?因为看起来你无法在每次通话时远离一些反射.

Osc*_*Ryz 10

成本高昂的是方法查找,但方法调用一次非常相似.

因此,一旦找到要调用的方法,就可以保留对它的引用,并且连续调用的工作方式类似.

当然,有些情况下您希望减少每毫秒.

虽然您应该知道微基准测试,但您可以尝试这样做只是为了得到一个粗略的想法:

import java.lang.reflect.*;
class ReflectionOrNot { 
    public void run() { 
        try { 
            Thread.currentThread().sleep( 0 );
        } catch( InterruptedException ie ){}
    }

    public static void main( String ... args ) throws Exception { 

        ReflectionOrNot ron = new ReflectionOrNot();
        int max = 1000000;

        long start = System.currentTimeMillis();
        for( int i = 0 ; i < max ; i++ ) { 
            ron.run();
        }
        System.out.println( "Direct access took: " + ( System.currentTimeMillis() - start ) );


        Method m = ReflectionOrNot.class.getDeclaredMethod("run");
        start = System.currentTimeMillis();
        for( int i = 0 ; i < max ; i++ ) { 
            m.invoke( ron );
        }
        System.out.println( "Reflection    Took: " + ( System.currentTimeMillis() - start ) );


        start = System.currentTimeMillis();
        for( int i = 0 ; i < max ; i++ ) { 
             m = ReflectionOrNot.class.getDeclaredMethod("run");
            m.invoke( ron );
        }
        System.out.println( "Lookup + Reflect  : " + ( System.currentTimeMillis() - start ) );


    }
}
Run Code Online (Sandbox Code Playgroud)

用不同的方法召唤100万次让我:

C:\Users\oreyes\java>java ReflectionOrNot
Direct access took: 422
Reflection    Took: 1156
Lookup + Reflect  : 3016

C:\Users\oreyes\java>java ReflectionOrNot
Direct access took: 422
Reflection    Took: 1125
Lookup + Reflect  : 2750

C:\Users\oreyes\java>java ReflectionOrNot
Direct access took: 485
Reflection    Took: 1203
Lookup + Reflect  : 2797
Run Code Online (Sandbox Code Playgroud)


Joh*_*erg 4

一般没有什么技巧。大多数基于反射的操作都是在 上执行的application startup,因此不会影响启动后的运行时性能。整个 hibernate-annotation API 就是一个完美的例子。

有时,注释的存在需要影响应用程序的整个生命周期。这通常是使用动态代理(或例如,代理具体类时的cglib 代理)或基于初始反射读数的拦截器进行配置。