Подтвердить что ты не робот

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

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

Многие книги говорят, что многие книги говорят нет.

4b9b3361

Ответ 1

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

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

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

И, несколько более авторитетно, из sunpaperpaper, пишущие, что методы могут быть оставлены виртуальными,

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

Здесь прямая ссылка на механизм.

Ответ 2

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

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

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

Ответ 3

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

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

Ответ 4

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

Ответ 5

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

Ответ 6

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

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

Ответ 7

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

Вместо константы (ака окончательный статический var).

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

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