Java 使用反射调用方法的性能

Java 使用反射调用方法的性能,java,reflection,Java,Reflection,使用反射调用方法与直接调用方法的性能差异是什么 上下文详细信息: 我有一个类,具有一些字符串属性,对于某些属性,我必须将值设置为小写或大写(以及一些与此相关的逻辑) 我有两个选择: 复制/粘贴14个属性的代码 或者注释这14个方法并使用反射找到它们并调用它们(也使用反射) 当然有选择2。我的代码可读性更好,维护也更容易,但问题是性能。我将有数百万(大约2-3个)的实例,如果对性能的影响不超过20秒,我将使用反射选项 这里有人有这方面的经验吗 一般来说,是的,反射速度较慢。如果你所说的数百万次呼叫

使用反射调用方法与直接调用方法的性能差异是什么

上下文详细信息: 我有一个类,具有一些字符串属性,对于某些属性,我必须将值设置为小写或大写(以及一些与此相关的逻辑)

我有两个选择:

  • 复制/粘贴14个属性的代码
  • 或者注释这14个方法并使用反射找到它们并调用它们(也使用反射)
  • 当然有选择2。我的代码可读性更好,维护也更容易,但问题是性能。我将有数百万(大约2-3个)的实例,如果对性能的影响不超过20秒,我将使用反射选项


    这里有人有这方面的经验吗

    一般来说,是的,反射速度较慢。如果你所说的数百万次呼叫是指数百万次呼叫,那么是的,在某些情况下,你可能会产生超过20秒的开销。在某些情况下,您可能不会产生额外的开销,因为编译器将能够对其进行优化。您必须给出更多关于如何使用反射的详细信息,或者自己运行反射。我的直觉告诉我,在300万个电话中,你的开销不会超过20秒,但这是一种直觉。

    让我们从网络反思的一些缺点开始

    反射的缺点

    反射很强大,但不应不加区别地使用。如果是 如果可以在不使用反射的情况下执行操作,则 最好避免使用它。应保持以下关注事项 在通过反射访问代码时请记住

    性能开销,因为反射涉及 通过动态解析,某些Java虚拟机优化可以 不能执行。因此,反射操作的速度较慢 性能优于非反射型,且应 避免在中经常调用的代码段中使用 性能敏感的应用程序

    安全限制 反射需要运行时权限,该权限在运行时可能不存在 在安全经理的领导下。这是我们的一个重要考虑因素 必须在受限安全上下文中运行的代码,例如 小程序

    内部构件的暴露 因为反射允许代码执行非反射代码中非法的操作,例如 访问私有字段和方法时,可能会导致反射的使用 在意外的副作用,这可能导致代码功能失调和 可能会破坏便携性。反射代码打破了抽象和抽象 因此,可能会随着平台的升级而改变行为

    因此,您可以确信,一旦开始扩展,性能将成为一个问题。 但是,如果您能够承受性能开销,直觉告诉您,对于大写/小写操作,性能开销不应超过20秒,并且具有巨大的可伸缩性不是一个问题,那么您可以使用它。但要注意,对绩效的直觉通常都是错误的。所以你肯定想测试一下

    一定要为您想要的任务查找面向方面的编程


    我的意见是:使用AOP框架。

    很难给出一个固定的数字,因为它将取决于系统的许多方面,所以我编写了一个类来检查这一点

    结果让我惊讶,对于我的系统来说,通过反射简单调用方法与静态调用方法相比,非空方法的静态调用速度要快10000倍,空方法的静态调用速度要快1000000倍

    我使用了这两种方法,以防java编译器/vm优化掉一个空方法调用

    代码如下,也可在本要点中找到-

    import java.lang.reflect.InvocationTargetException;
    导入java.lang.reflect.Method;
    公共类测试反射{
    公共静态长INC=0;
    公共静态最终整数计数=100000000;
    私有静态类虚拟{
    公共void doSomething(字符串s1、字符串s2、字符串s3){
    INC++;
    }
    }
    公共静态void main(字符串[]args)引发NoSuchMethodException{
    虚拟对象=新虚拟对象();
    方法Method=obj.getClass().getMethod(“doSomething”,String.class,String.class,String.class);
    String s1=“string1”;
    String s2=“string2”;
    String s3=“string3”;
    //热身
    运行反射(obj,方法,s1,s2,s3,计数/10);
    运行静态(obj、s1、s2、s3、计数/10);
    ///房地产
    long reftime=System.nanoTime();
    运行反射(obj,方法,s1,s2,s3,计数);
    reftime=System.nanoTime()-reftime;
    长时间=System.nanoTime();
    运行静态(obj、s1、s2、s3、计数);
    时间=System.nanoTime()-时间;
    System.out.println(reftime);
    系统输出打印LN(时间);
    //每秒1000*1000*1000纳秒
    系统输出打印项次(参考时间/(1000*1000*1000));
    系统输出打印项次(时间/(1000*1000*1000));
    系统输出打印项次((双)参考时间/(双)时间);
    System.out.println(“使用反射降低的速度百分比:”+((双)参考时间/(双)时间)-1)*100);
    }
    私有静态void runReflection(虚拟对象、方法、字符串s1、字符串s2、字符串s3、int计数){
    for(int i=0;i
    反射成本很高。你可以找到
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    public class TestReflection {
    
        public static long INC = 0;
    
        public static final int COUNT = 100000000;
    
        private static class Dummy {
            public void doSomething(String s1, String s2, String s3) {
                INC++;
            }
        }
    
        public static void main(String[] args) throws NoSuchMethodException {
    
            Dummy obj = new Dummy();
            Method method = obj.getClass().getMethod("doSomething", String.class, String.class, String.class);
    
            String s1 = "string1";
            String s2 = "string2";
            String s3 = "string3";
    
            //warmup
            runReflection(obj, method, s1, s2, s3, COUNT / 10);
            runStatic(obj, s1, s2, s3, COUNT/10);
    
            ///realtest
    
            long reftime = System.nanoTime();
            runReflection(obj, method, s1, s2, s3, COUNT);
            reftime = System.nanoTime() - reftime;
    
            long time = System.nanoTime();
            runStatic(obj, s1, s2, s3, COUNT);
            time = System.nanoTime() - time;
    
            System.out.println(reftime);
            System.out.println(time);
    
            //1000 *1000 *1000 nanoseconds in a second
            System.out.println(reftime / (1000 *1000 *1000));
            System.out.println(time / (1000 *1000 *1000));
            System.out.println((double)reftime/ (double)time );
    
            System.out.println("percentage speed decrease from using reflection:"+(((double)reftime/(double)time)-1)*100);
    
        }
    
        private static void runReflection(Dummy obj, Method method, String s1, String s2, String s3, int count) {
            for (int i = 0; i < count; i++) {
                try {
                    method.invoke(obj, s1, s2, s3);
                } catch (IllegalArgumentException e) {
                } catch (IllegalAccessException e) {
                } catch (InvocationTargetException e) {
                }
            }
        }
    
        private static void runStatic(Dummy obj, String s1, String s2, String s3, int count) {
            for (int i = 0; i < count; i++) {
                obj.doSomething(s1,s2,s3);
            }
        }
    
    }