Вы объединяете две разные проблемы.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 или любое другое обновление, в котором реализовано исправление безопасности.