首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用反射调用方法的性能

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

Stack Overflow用户
提问于 2014-08-19 16:53:45
回答 3查看 4.6K关注 0票数 3

使用反射调用方法与直接调用方法有什么不同?

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

我有两个选择:

  1. 要么复制/粘贴这14个属性的代码。
  2. 或者注释这14个方法并使用反射,找到它们并调用它们(也使用反射)。

当然,使用选项2,我的代码将更易读和易于维护,但问题是性能问题。我将有数以百万计的实例(约2-3个),如果性能影响不超过20秒,我将使用反射选项。

这里有人对此有什么经验吗?

EN

回答 3

Stack Overflow用户

发布于 2015-02-05 11:24:26

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

结果让我感到惊讶,对于我的系统来说,简单地通过反射调用方法与静态调用方法相比,静态调用对于非空方法来说是10,000倍,对于空方法则是100,000倍。

我同时使用了这两种方法,以防java编译器/vm正在优化空方法调用。

代码在下面,也可以在这个gist - https://gist.github.com/piersy/23b4814eec806b584266中找到。

代码语言:javascript
复制
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);
        }
    }

}
票数 3
EN

Stack Overflow用户

发布于 2014-08-19 17:02:55

一般来说,是的,反射要慢一些。如果数百万实例是指数百万次呼叫,那么是的,在某些情况下,您可能会产生超过20秒的开销。在某些原因中,您可能不会产生额外的开销,因为编译器将能够优化它。您必须提供更多关于如何使用反射的详细信息,或者自己运行它。我的直觉说,在300万次通话中,你不会超过20秒的开销,然而,这在很大程度上是直觉。

票数 1
EN

Stack Overflow用户

发布于 2014-08-19 17:11:55

让我们从Oracle Docs反射的一些缺点开始

反射的缺陷 反射是强大的,但不应任意使用。如果可以不使用反射来执行操作,那么最好避免使用它。在通过反射访问代码时,应该记住以下几点。 由于反射涉及动态解析的类型,因此无法执行某些虚拟机优化。因此,反射操作的性能比它们的非反射操作要慢,在性能敏感的应用程序中经常调用的代码部分应该避免反射操作。 安全限制反射要求在安全管理器下运行时可能不存在的运行时权限。这是对必须在受限的安全上下文中运行的代码的一个重要考虑,例如在Applet中。 因为反射允许代码执行在非反射代码中非法的操作,例如访问私有字段和方法,反射的使用可能导致意外的副作用,这可能会导致代码功能失调,并可能破坏可移植性。反射代码破坏抽象,因此可能会随着平台的升级而改变行为。

因此,您可以确信,一旦开始扩展,性能就会成为一个问题。但是,如果您可以忍受性能开销(直觉说,大写/小写操作不应该超过20秒),并且具有很大的可伸缩性,那么您可以使用它。但请注意,对性能的直觉通常都是错误的。所以你肯定想测试一下。

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

我的观点是:使用AOP框架。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25388938

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档