Есть ли в Java встроенные функции?


112

Есть ли в java концепция встроенных функций или она заменена чем-то другим? Если есть, то как его использовать? Я слышал об этом public, staticа finalметоды - это встроенные функции. Можем ли мы создать нашу собственную встроенную функцию?


4
Чтобы уточнить, вы имеете в виду en.wikipedia.org/wiki/Inline_function , а не en.wikipedia.org/wiki/Anonymous_function , верно?
JW.

3
Небольшой комментарий: преждевременная оптимизация - это корень всех зол. Без полного понимания природы public, static и final вы не сможете понять, какое влияние может иметь встраивание - и это зависит от используемой JVM. Обязательно сначала ответьте, почему вам нужно что-то встроить: почти наверняка есть оптимизации с более высокой рентабельностью инвестиций, которые вы можете сделать в другом месте.
Nathaniel Ford

Ответы:


123

В Java оптимизация обычно выполняется на уровне JVM. Во время выполнения JVM выполняет некоторый «сложный» анализ, чтобы определить, какие методы следует встроить. Он может быть агрессивным при встраивании, и JVM Hotspot фактически может встраивать неокончательные методы.

Компиляторы java почти никогда не встраивают вызов метода (JVM делает все это во время выполнения). Они делают встроенные константы времени компиляции (например, конечные статические примитивные значения). Но не методы.

Дополнительные ресурсы:

  1. Статья: Механизм производительности Java HotSpot: пример встраивания методов

  2. Wiki: встраивание в OpenJDK , заполнено не полностью, но содержит ссылки на полезные обсуждения.


15

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

Обычно такая оптимизация кода выполняется компилятором в сочетании с JVM / JIT / HotSpot для часто используемых сегментов кода. Также другие концепции оптимизации, такие как объявление параметров в регистре, не известны в java.

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

Объявление методов Java static, final или private также является подсказкой для компилятора. Стоит использовать, но никаких гарантий. Производительность Java динамическая, а не статическая. Первый вызов системы всегда выполняется медленно из-за загрузки класса. Следующие вызовы выполняются быстрее, но в зависимости от памяти и времени выполнения наиболее распространенные вызовы оптимизируются внутри работающей системы, поэтому сервер может работать быстрее во время выполнения!


3
finalне влияет на встраивание JIT
Стив Куо

1
+1, но как мы можем проверить , является ли скомпилированная версия метода встроенной?
Pacerier

@Pacerier Но зачем нам проверять, встроено ли что-то?
Арне Бурмейстер

14

Java не позволяет вручную предлагать встроить метод. Как @notnoop говорит в комментариях, встраивание обычно выполняется JVM во время выполнения.


3
Большинство компиляторов java никогда не встраивают вызовы методов. В основном это делает JVM.
notnoop

Спасибо, что разъяснили это. Я не был уверен, в какой именно фазе это произошло. Я отредактирую свой пост, чтобы отразить это.
Thomas Owens

@ThomasOwens есть, но это не публичноjdk.internal.vm.annotation.ForceInline
Eugene

4

То, что вы сказали выше, правильно. Иногда final методы создаются как встроенные, но другого способа явно создать встроенную функцию в java нет.


5
Не гарантируется, что final методы будут встроенными.
Thomas Owens

4
В HotSpot добавление finalдаже не имеет значения, является ли метод встроенным или нет.
Том Хотин - tackline

4
@Thomas - вот почему я сказал: «Иногда финальные методы ...»
GreenieMeanie

@ TomHawtin-tackline у ​​вас есть авторитетный источник для этого? Насколько мне известно, методы final могут быть встроены без использования защиты типа, а это означает, что модификатор делает встраивание метода более эффективным, чем без модификатора. Я знаю, что Jikes RVM учитывает это при принятии решения о встраивании. Вы уверены, что HotSpot не делает ничего похожего?
Jannik Jochem

2

Пример из реальной жизни:

public class Control {
    public static final long EXPIRED_ON = 1386082988202l;
    public static final boolean isExpired() {
        return (System.currentTimeMillis() > EXPIRED_ON);
    }
}

Затем в других классах я могу выйти, если срок действия кода истек. Если я ссылаюсь на переменную EXPIRED_ON из другого класса, константа встроена в байтовый код, что очень затрудняет отслеживание всех мест в коде, который проверяет дату истечения срока действия. Однако, если другие классы вызывают метод isExpired (), вызывается фактический метод, что означает, что хакер может заменить метод isExpired другим, который всегда возвращает false.

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

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

Что касается проверки того, размещен ли метод из класса управления встроенным в другой класс во время компиляции, попробуйте запустить другой класс без класса Control в пути к классам.


2

Что ж, в java есть методы, которые можно назвать "встроенными", но в зависимости от jvm. После компиляции, если машинный код метода меньше 35 байт, он будет немедленно передан во встроенный метод, если машинный код метода меньше 325 байт, он может быть передан во встроенный метод, в зависимости от jvm.


1
Это значения по умолчанию для виртуальной машины
rmuller

0

Итак, похоже, что нет, но вы можете использовать этот обходной путь, используя guava или эквивалентную реализацию класса Function, потому что этот класс чрезвычайно прост, например:

    assert false : new com.google.common.base.Function<Void,String>(){
        @Override public String apply(Void input) {
            //your complex code go here
            return "weird message";
        }}.apply(null);

да, это мертвый код, просто чтобы проиллюстрировать, как создать сложный блок кода (внутри {}), чтобы сделать что-то настолько конкретное, что не должно нас беспокоить при создании для него какого-либо метода, AKA inline!


Вроде разумная идея. У вас есть версия, в которой не используются общие библиотеки Google?
ragerdl 02

0

В Java9 есть компилятор «впереди времени», который выполняет несколько оптимизаций во время компиляции, а не во время выполнения, что можно рассматривать как встраивание.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.