Производительность отражения Java - PullRequest
159 голосов
/ 12 января 2009

Приводит ли создание объекта с использованием отражения вместо вызова конструктора класса какие-либо существенные различия в производительности?

Ответы [ 14 ]

4 голосов
/ 07 сентября 2011

В doReflection () есть издержки из-за Class.forName ("misc.A") (который потребует поиска класса, потенциально сканирующего путь к классу в файловой системе), а не newInstance (), вызываемого в учебный класс. Мне интересно, как бы выглядела статистика, если Class.forName ("misc.A") выполняется только один раз за пределами цикла for, на самом деле это не нужно делать для каждого вызова цикла.

1 голос
/ 13 февраля 2009

Часто вы можете использовать Apache commons BeanUtils или PropertyUtils, которые самоанализируют (в основном они кэшируют метаданные о классах, поэтому им не всегда нужно использовать отражение).

1 голос
/ 12 января 2009

Да, всегда будет медленнее создавать объект путем отражения, потому что JVM не может оптимизировать код во время компиляции. См. Учебники Sun / Java Reflection для получения более подробной информации.

См. Этот простой тест:

public class TestSpeed {
    public static void main(String[] args) {
        long startTime = System.nanoTime();
        Object instance = new TestSpeed();
        long endTime = System.nanoTime();
        System.out.println(endTime - startTime + "ns");

        startTime = System.nanoTime();
        try {
            Object reflectionInstance = Class.forName("TestSpeed").newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        endTime = System.nanoTime();
        System.out.println(endTime - startTime + "ns");
    }
}
0 голосов
/ 10 января 2017

Я думаю, это зависит от того, насколько легким / тяжелым является целевой метод. если целевой метод очень легкий (например, метод получения / установки), он может быть в 1-3 раза медленнее. если целевой метод занимает около 1 миллисекунды или выше, производительность будет очень близка. вот тест, который я сделал с Java 8 и refleasm :

public class ReflectionTest extends TestCase {    
    @Test
    public void test_perf() {
        Profiler.run(3, 100000, 3, "m_01 by refelct", () -> Reflection.on(X.class)._new().invoke("m_01")).printResult();    
        Profiler.run(3, 100000, 3, "m_01 direct call", () -> new X().m_01()).printResult();    
        Profiler.run(3, 100000, 3, "m_02 by refelct", () -> Reflection.on(X.class)._new().invoke("m_02")).printResult();    
        Profiler.run(3, 100000, 3, "m_02 direct call", () -> new X().m_02()).printResult();    
        Profiler.run(3, 100000, 3, "m_11 by refelct", () -> Reflection.on(X.class)._new().invoke("m_11")).printResult();    
        Profiler.run(3, 100000, 3, "m_11 direct call", () -> X.m_11()).printResult();    
        Profiler.run(3, 100000, 3, "m_12 by refelct", () -> Reflection.on(X.class)._new().invoke("m_12")).printResult();    
        Profiler.run(3, 100000, 3, "m_12 direct call", () -> X.m_12()).printResult();
    }

    public static class X {
        public long m_01() {
            return m_11();
        }    
        public long m_02() {
            return m_12();
        }    
        public static long m_11() {
            long sum = IntStream.range(0, 10).sum();
            assertEquals(45, sum);
            return sum;
        }    
        public static long m_12() {
            long sum = IntStream.range(0, 10000).sum();
            assertEquals(49995000, sum);
            return sum;
        }
    }
}

Полный тестовый код доступен на GitHub: ReflectionTest.java

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...