Чи є вбудовані функції в java?


112

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


4
Просто для уточнення, ви маєте на увазі en.wikipedia.org/wiki/Inline_function , а не en.wikipedia.org/wiki/Anonymous_function , правда?
JW.

3
Як незначний коментар, передчасна оптимізація - корінь усього зла. Без повного розуміння природи загальнодоступного, статичного та остаточного ви не можете реально зрозуміти, який вплив може скласти - і це залежить від використовуваного JVM. Перш за все, обов'язково відповідь, чому потрібно щось вбудувати: майже впевнено, що вищі оптимізації рентабельності інвестицій можна зробити в інших місцях.
Натаніель Форд

Відповіді:


123

У Java оптимізація зазвичай проводиться на рівні JVM. Під час виконання, JVM проводить деякий "складний" аналіз, щоб визначити, які методи вбудувати. Він може бути агресивним у вбудованому виконанні, і JVM Hotspot насправді може вбудувати не завершальні методи.

Компілятори Java майже ніколи не вбудовують будь-який виклик методу (JVM робить все це під час виконання). Вони роблять вбудовані постійні часу (наприклад, кінцеві статичні примітивні значення). Але не методами.

Для отримання додаткових ресурсів:

  1. Стаття: Двигун продуктивності Java HotSpot: Приклад вкладки методу

  2. Вікі: Вбудований у OpenJDK , не повністю заповнений, але містить посилання на корисні дискусії.


15

Ні, в Java немає вбудованої функції . Так, ви можете використовувати загальнодоступний статичний метод в будь-якому місці коду, коли розміщується в загальнодоступному класі. Компілятор java може робити вбудоване розширення статичним або кінцевим методом, але це не гарантується.

Зазвичай такі оптимізації коду здійснюються компілятором у поєднанні з JVM / JIT / HotSpot для сегментів коду, які використовуються дуже часто. Також в Java не відомі інші концепції оптимізації, такі як оголошення регістру параметрів.

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

Оголошення методів Java статичним, остаточним або приватним також є підказками для компілятора. Ви повинні використовувати його, але ніяких гарантій. Продуктивність Java динамічна, а не статична. Перший виклик до системи завжди повільний через завантаження класу. Наступні дзвінки проходять швидше, але залежно від пам’яті та часу виконання, найпоширеніші дзвінки оптимізовані за допомогою запущеної системи, тому сервер може стати швидшим під час виконання!


3
finalне впливайте на вбудований JIT
Стів Куо

1
+1, Але як ми можемо перевірити, чи складена версія методу вбудована?
Pacerier

@Pacerier Але навіщо нам перевіряти, чи щось накреслено?
Арн Бурмейстер

14

Java не пропонує способу вручну підказати, що метод повинен бути накреслений. Як зазначає @notnoop у коментарях, вбудовування, як правило, виконується JVM під час виконання.


3
Більшість компіляторів Java ніколи не здійснює вбудовані методи викликів. Переважно JVM це робить.
notnoop

Дякуємо, що уточнили це. Я не був впевнений, в якій саме стадії відбулася фаза. Я відредагую свою публікацію, щоб це відобразити.
Томас Оуенс

@ThomasOwens це робить, але це не публічноjdk.internal.vm.annotation.ForceInline
Євген

4

Те, що ви сказали вище, є правильним. Іноді остаточні методи створюються як вбудовані, але іншого способу явного створення вбудованої функції в java немає.


5
Кінцеві методи не гарантовано є вбудованими.
Томас Оуенс

4
На HotSpot додавання finalнавіть не має ніякої різниці щодо того, введений метод чи ні.
Том Хотін - тайклін

4
@Thomas - саме тому я сказав "Іноді остаточні методи ..."
GreenieMeanie

@ TomHawtin-tackline У вас є авторитетне джерело для цього? Наскільки я знаю, остаточні методи можуть бути вбудовані без використання захисного типу, це означає, що модифікатор робить метод вбудовування даних більш ефективним, ніж без модифікатора. Я знаю, що 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 іншим, який завжди повертає помилковим.

Я погоджуюсь, було б дуже примусити компілятора надати статичний остаточний метод всім класам, на які він посилається. У цьому випадку вам навіть не потрібно включати клас Control, оскільки він би не знадобився під час виконання.

З мого дослідження, цього неможливо зробити. Можливо, деякі інструменти Obfuscator можуть це зробити, або ви можете змінити процес збирання для редагування джерел перед компіляцією.

Що стосується доведення, якщо метод із класу управління розміщено в рядку до іншого класу під час компіляції, спробуйте запустити інший клас без класу Control на classpath.


2

Що ж, існують методи, які можна назвати "вбудованими" методами у java, але залежно від jvm. Після компіляції, якщо машинний код методу менше 35 байт, він буде негайно переведений в метод вбудованого, якщо машинний код методу менше 325 байт, він може бути переведений у вбудований метод, залежно від jvm.


1
Це значення за замовчуванням для VM Oracle, див. Docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
rmuller

0

так що, здається, немає, але ви можете використовувати це вирішення, використовуючи guava або еквівалентну реалізацію класу функцій, оскільки цей клас надзвичайно простий, напр .:

    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

0

У Java9 є компілятор "Попереду часу", який робить кілька оптимізацій за час компіляції, а не час виконання, що може розглядатися як вбудований.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.