Invokespecial со старой семантикой: вызов метода экземпляра другого класса - PullRequest
0 голосов
/ 17 декабря 2018

Согласно this в старых версиях Java существовала менее ограничительная версия invokespecial, называемая invokenonvirtual.Эта инструкция позволит вам вызывать методы экземпляра без виртуального поиска, и, если я правильно понял, эти методы могут принадлежать классам, которые нельзя назначить текущему классу.В invokespecial это изменилось, поскольку оно используется только для вызова супер, приватных или инициализирующих методов.

Мои вопросы: есть ли способ с использованием Java 8 (или выше) обойти эти структурные ограничения [4.9.2] инструкции invokespecial и вызова без виртуального поиска метода другого класса (т. Е. Класса, несовместимого с текущим классом по присваиванию)

Я мог бы использовать флаг no-verify для отключенияпроцесс проверки, но есть ли более элегантный способ?

1 Ответ

0 голосов
/ 17 декабря 2018

Вы объединяете две разные проблемы.invokenonvirtual и inokespecial одинаковы и всегда были.Это просто два разных имени для одного и того же кода операции.

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

По сути,в очень ранних версиях Java компиляция супер-вызовов была прервана.При компиляции вызова суперкласса он вставил бы invokespecial в метод суперкласса во время компиляции .Если иерархия классов была позже изменена, она все равно будет пытаться вызвать метод, который был скомпилирован для вызова, даже если новое переопределение было вставлено в промежуточную точку в иерархии.

Обратите внимание, что это все еще не позволяло вам вызывать методы в несвязанных классах - проблема, связанная только с различными переопределениями одного и того же метода, добавляемого в одно и то же изменение наследования после компиляции.

ПослеАвторы Java осознали свою ошибку, они обновили обработку JVM invokespecial для правильной обработки супер-вызовов.Теперь, независимо от того, какой метод указан в инструкции, он будет обходить иерархию суперкласса во время соединения / выполнения и вызывать соответствующий метод.

Однако их беспокоило то, что код, скомпилированный в старых версиях Java, полагался на некорректное поведение, поэтому для обратной совместимости они добавили новый флаг файла классов ACC_SUPER.Если флаг установлен для класса, он имеет новое (правильное) поведение, если нет, он использует старое поведение.Поскольку старые файлы классов были скомпилированы до того, как флаг существовал, он не будет установлен.Тем временем компилятор был обновлен, чтобы установить ACC_SUPER для всех новых классов, и все были счастливы ...

Вплоть до 2011 года.Оказывается, что java.lang.Thread имеет чувствительный к безопасности метод, который пользователи не должны вызывать.Чтобы люди не могли вызывать его из подклассов Thread, они отвергли его, чтобы вызвать исключение.Однако, кто-то понял, , что хакеры могут определить подкласс Thread без флага ACC_SUPER и, таким образом, пропустить проверку безопасности, вызвать опасную версию метода и выйти из песочницы Java.

К сожалению, единственный способ исправить эту уязвимость безопасности - полностью удалить функцию ACC_SUPER, то есть обработать каждый класс, как если бы у него был установлен флаг, независимо от того, действительно ли он установлен или нет.Это было поспешно исправлено в Java 7 update 13, а в Java 8 сама спецификация была изменена на документ, который ACC_SUPER больше не имел никакого эффекта.

Таким образом, ответ - нет, нет способа получитьстарое поведение супер-вызовов в любой версии Java после 7u13 или любое другое обновление, в котором реализовано исправление безопасности.

...