Как большая иерархия классов влияет на производительность Java?

У меня есть класс, который расширяет другой класс, который расширяет другой класс.. и так далее.

Насколько медленный (в процентах) класс с уровнем иерархии 100 уровней будет работать, чем класс с уровнем иерархии 10 уровней?

4 ответа

Решение

"Хорошие JVM" (что бы это ни значило) кэшируют результаты разрешения метода. Следовательно, влияние на производительность должно происходить только один раз, и даже оно, вероятно, будет минимальным. Однако во время создания объекта будет создан экземпляр каждого расширенного класса, также будет вызван каждый конструктор каждого суперкласса, что может оказать большее влияние при создании большого количества объектов с большой иерархией.

Я должен согласиться с Джоном Скитом (ну, а кто нет) в том, что вопрос звучит так, как будто есть некоторые серьезные проблемы с дизайном, или генератор кода вышел из строя. Это похоже на вопрос "сколько столбцов поддерживает таблица базы данных". Если это более чем разумно, вы, вероятно, делаете это неправильно.

Давайте попробуем это:

class T1 {}
class T2 extends T1{}
class T3 extends T2{}
class T4 extends T3{}
class T5 extends T4{}
class T6 extends T5{}
class T7 extends T6{}
class T8 extends T7{}
class T9 extends T8{}
class T10 extends T9{}
class T11 extends T10{}
class T12 extends T11{}
class T13 extends T12{}
class T14 extends T13{}
class T15 extends T14{}
class T16 extends T15{}
class T17 extends T16{}
class T18 extends T17{}
class T19 extends T18{}
class T20 extends T19{}
class T21 extends T20{}
class T22 extends T21{}
class T23 extends T22{}
class T24 extends T23{}
class T25 extends T24{}
class T26 extends T25{}
class T27 extends T26{}
class T28 extends T27{}
class T29 extends T28{}
class T30 extends T29{}
class T31 extends T30{}
class T32 extends T31{}
class T33 extends T32{}
class T34 extends T33{}
class T35 extends T34{}
class T36 extends T35{}
class T37 extends T36{}
class T38 extends T37{}
class T39 extends T38{}
class T40 extends T39{}
class T41 extends T40{}
class T42 extends T41{}
class T43 extends T42{}
class T44 extends T43{}
class T45 extends T44{}
class T46 extends T45{}
class T47 extends T46{}
class T48 extends T47{}
class T49 extends T48{}
class T50 extends T49{}
class T51 extends T50{}
class T52 extends T51{}
class T53 extends T52{}
class T54 extends T53{}
class T55 extends T54{}
class T56 extends T55{}
class T57 extends T56{}
class T58 extends T57{}
class T59 extends T58{}
class T60 extends T59{}

Я смог создать экземпляр T53, но T54 выкинул ошибку StackruError.

new T54();

Exception in thread "main" java.lang.StackruError
    at java.lang.ref.Reference.<init>(Reference.java:216)
    at java.lang.ref.FinalReference.<init>(FinalReference.java:16)
    at java.lang.ref.Finalizer.<init>(Finalizer.java:66)
    at java.lang.ref.Finalizer.register(Finalizer.java:72)
    at java.lang.Object.<init>(Object.java:20)
    at java.io.InputStream.<init>(InputStream.java:28)
    at java.io.FileInputStream.<init>(FileInputStream.java:96)
    at sun.misc.URLClassPath$FileLoader$1.getInputStream(URLClassPath.java:1005)
    at sun.misc.Resource.cachedInputStream(Resource.java:61)
    at sun.misc.Resource.getByteBuffer(Resource.java:144)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:256)
    at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
    at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:248)

Это было сделано с использованием размера стека JVM по умолчанию.

Для 100-уровневой иерархии вам понадобится больший стек. (Вы можете увеличить размер стека, используя Xss.)

Это будет зависеть от вашей JVM, точных операций, которые вы выполняете, от переопределения различных методов и т. Д.

Однако я был бы гораздо больше обеспокоен влиянием дизайна и читабельности, чем влиянием на производительность. Это действительно лучший дизайн, который вы можете придумать? Какую проблему она решает, которая не может быть лучше решена другим способом?

Согласно Полному Справочнику Java2 Герберт Шилдр:

Тем не менее, вы можете наследовать любые классы, уровень наследования классов Java более 5 не более заметен. Это всегда снижает производительность.

Я также согласен с ответом Джона Скита.

Другие вопросы по тегам