финальные методы встроены? - PullRequest
3 голосов
/ 09 ноября 2009

Являются ли финальные методы Java автоматически встроенными?

Многие книги говорят да, многие книги говорят нет !!!

Ответы [ 7 ]

9 голосов
/ 09 ноября 2009

Встраивание методов выполняется компилятором JIT, а не javac.

Современные JIT-компиляторы (включая Hotspot) часто могут включать даже не финальные методы, «при необходимости» отменяя оптимизацию. Они в основном очень умные.

Короче говоря: это полностью зависит от виртуальной машины. На мой взгляд, вы должны сделать ваши методы окончательными или не основанными на том, что производит чистый код, а не на производительности. Я лично фанат "дизайна для наследования или запрета", но это другое обсуждение:)

4 голосов
/ 09 ноября 2009

Интересный вопрос, побудил меня изучить его дальше. 2 интересных замечания, которые я нашел -

Вопреки подтексту многих советы, методы, объявленные как окончательные, не могут быть безопасно встроенным компилятором, потому что метод может иметь не окончательное объявление во время выполнения.

Чтобы понять почему, предположим, что компилятор выглядит в классе A и подклассе B, и подкласс C и видит окончательный метод в А, который встраивается в С. Но тогда во время выполнения версии загружаются для и В разные, и метод не окончательный в A, и переопределенный в B. Тогда C использует неправильно вставленный версия. T

И, немного более авторитетно, из sun whitepaper , написавшего, что методы можно оставить виртуальными,

Поскольку виртуальная машина Java HotSpot может автоматически выполнять подавляющее большинство вызовов виртуальных методов, это снижение производительности значительно сокращается, а во многих случаях и вовсе устраняется.

Вот еще прямая ссылка на механизм.

2 голосов
/ 09 ноября 2009

final больше относится к добавлению семантики в дизайн, чем к указанию компилятору или виртуальной машине что-то встроить. Современные виртуальные машины включают в себя гораздо больше, чем одни только конечные методы, так что это не является веской причиной для использования final или попытки слишком много предсказывать об оптимизации времени выполнения.

2 голосов
/ 09 ноября 2009

Если вы имеете в виду «они встроены во время компиляции», то нет, они не будут.

Однако статические конечные поля иногда могут быть встроены компилятором, например, примитивами и строками.

1 голос
/ 09 ноября 2009

Я думаю, это зависит от того, на какой реализации JVM вы работаете. Конечно, создание метода final дает компилятору возможность настроить такую ​​реализацию. Но может ли это быть или нет, может также зависеть от других факторов - например, что, если это огромный метод, и т.д .....

0 голосов
/ 01 марта 2013

Как сказал Джон, встраивание выполняется (когда это необходимо) JIT-компилятором, а не на уровне генерации байт-кода. Также обратите внимание, что иногда встраивание может привести к снижению производительности, потому что это может создать ситуацию, когда один и тот же код присутствует несколько раз в кэше процессора l1, освобождая место для другого кода. Пропуск кэша L1 может повлиять на производительность больше, чем переход к кешированной функции.

Константы (иначе конечная статическая переменная) вставляются взамен.

Смотрите это, чтобы проверить

public class InlineTest {
    final static int add(int x, int y) {
        return x + y;
    } 
}


public class Main {

        static final int DIVISOR = 7;

        static void main(String[] args){
            final int a = new Integer(args[0]);
            final int b = new Integer(args[1]);

            if (InlineTest.add(a, b) % DIVISOR == 0)
                System.exit(InlineTest.add(a, b));

            System.out.print("The sum is " + InlineTest.add(a, b));

        }
}

Это переведено на:

 0 new #2 <java/lang/Integer>
 3 dup
 4 aload_0
 5 iconst_0
 6 aaload
 7 invokespecial #3 <java/lang/Integer/<init>(Ljava/lang/String;)V>
10 invokevirtual #4 <java/lang/Integer/intValue()I>
13 istore_1
14 new #2 <java/lang/Integer>
17 dup
18 aload_0
19 iconst_1
20 aaload
21 invokespecial #3 <java/lang/Integer/<init>(Ljava/lang/String;)V>
24 invokevirtual #4 <java/lang/Integer/intValue()I>
27 istore_2
28 iload_1
29 iload_2
30 invokestatic #5 <com/gamasoft/InlineTest/add(II)I>
33 bipush 7
35 irem
36 ifne 47 (+11)
39 iload_1
40 iload_2
41 invokestatic #5 <com/gamasoft/InlineTest/add(II)I>
44 invokestatic #7 <java/lang/System/exit(I)V>
47 getstatic #8 <java/lang/System/out Ljava/io/PrintStream;>
50 new #9 <java/lang/StringBuilder>
53 dup
54 invokespecial #10 <java/lang/StringBuilder/<init>()V>
57 ldc #11 <The sum is >
59 invokevirtual #12 <java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;>
62 iload_1
63 iload_2
64 invokestatic #5 <com/gamasoft/InlineTest/add(II)I>
67 invokevirtual #13 <java/lang/StringBuilder/append(I)Ljava/lang/StringBuilder;>
70 invokevirtual #14 <java/lang/StringBuilder/toString()Ljava/lang/String;>
73 invokevirtual #15 <java/io/PrintStream/print(Ljava/lang/String;)V>
76 return

Вы видите, что статическая функция InlineTest.add была вызвана несколько раз с invokestatic

0 голосов
/ 09 ноября 2009

Решение Hotspot о том, стоит ли использовать inline, невероятно сложное, зависит от множества соображений, но я не думаю, что метод, помеченный как «окончательный», является одним из них. Причина в том, что он уже знает, были ли загружены несколько реализаций этого метода в ВМ, поэтому не имеет значения также знать, разрешены ли такие реализации.

В любом случае, это будут очень маленькие и простые методы, которые будут встроены, и даже не все из них.

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