Одним летним утром мы обсудили Method Handle API.
А в первом осеннем посте сделаем полшага назад и посмотрим, как вызываются методы в JVM. Эта история тоже непростая, поэтому начнём с древних времён java 6.
Для разных методов компилятор генерирует разные байткод инструкции:
🍂 invokespecial - приватные методы, конструкторы и вызовы через super
🍂 invokestatic - статические методы
🍂 invokevirtual - public и protected методы
🍂 invokeinterface - вызов методов интерфейса
Байткод можно посмотреть, вызвав команду для скомпилированного файла:
javap -c -v UserInfo.classПри первом использовании файл с байткодом загружается с диска и регистрируется внутри JVM. Нам интересны четыре сущности:
1️⃣ ConstantPool - табличка из class-файла с именами полей, методов и аргументов. Выглядит как-то так:
#14=Utf8 Autumn2️⃣ Список байткод инструкций
#16=Class #18
#17=NameAndType #19:#20
29: getstatic #39Все конкретные методы и аргументы обозначаются через ссылки из Constant Pool.
32: aload_3
33: invokevirtual #45
3️⃣ Табличка виртуальных методов для класса
4️⃣ Табличка с интерфейсами и реализациями
Таблицы 3 и 4 лежат внутри JVM в особой структуре, чтобы по ним было легко перемещаться.
Каждый из invoke* методов работает по своему алгоритму. Понятно, что для protected метода нужно походить по иерархии, а для приватного это не нужно.
Что тут важно: все структуры строятся при загрузке класса и больше не меняются.
В Java 7 в JVM добавилась инструкция invokedynamic для поддержки динамических языков.
Зачем в JVM поддержка других языков? А потому что JVM - очень развитая и крутая:
🍁 Кроссплатформенность - берёт на себя работу с операционной системой и даёт заняться чистейшим программированием
🍁 Изоляция - можно безопасно запускать несколько приложений
🍁 JIT компиляторы
🍁 Поддержка многопоточности, сборщики мусора, рефлекшн
Думаете, у всех такое есть? А вот и нет.
Но есть один недостаток. JVM совершенно не приспособлена под динамические языки - JavaScript, Python, Ruby. Все invoke* методы должны заранее знать все классы и типы аргументов.
Поэтому в JVM добавили новую инструкцию invokedynamic. А о том, как она работает, поговорим в пятницу.