java lang reflect invocationtargetexception как исправить

Попробуйте посмотреть здесь, правда на английском. но разобраться можно [ссылка заблокирована по решению администрации проекта]
ЗагрузитьЗагрузите пакет исправлений.
Дополнительные сведения о том, как загрузить файлы поддержки Майкрософт — щелкните следующий номер статьи базы знаний Майкрософт:
119591 Как загрузить файлы поддержки Microsoft через веб-службы
Корпорация Майкрософт проверила этот файл на наличие вирусов. Корпорация Майкрософт использует последнее антивирусное программное обеспечение, доступное на период публикации файла. Файл хранится на защищенных серверах, что предотвращает его несанкционированное изменение.

Примечание переводчика: развитие фреймворка CUBA порождает большое количество R&D проектов. В ходе одного такого проекта выяснилось, что нам нужно вызывать default методы интерфейсов из прокси классов. Наткнулись на очень полезную статью, мне кажется, что опыт, изложенный в ней, будет, как минимум интересен, как максимум — полезен широкому кругу разработчиков.

Когда дело касается доступа к default методам интерфейсов в Java через рефлексию, гугление не очень помогает. Например, решение на StackOverflow работает только в определенных ситуациях и не на всех версиях Java.

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

TL;DR Если вам не терпится, то все способы вызова default методов, описанные в этой статье, доступны по этой ссылке, а также эта проблема уже решена в нашей библиотеке jOOR.

Содержание

  1. Проксирование интерфейсов с default методами
  2. Использование Method Handles API
  3. Вызов метода интерфейса с не приватным доступом
  4. Более глубокое исследование
  5. Заключение

Проксирование интерфейсов с default методами

Полезный API java.lang.reflect.Proxy существует достаточно давно, с его помощью мы можем делать клевые штуки, например:

Этот код просто выводит:

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

Интересное начнется, когда мы захотим добавить реализацию метода в интерфейс и делегировать вызов в этот метод:

Скорее всего, захочется написать такой код:

Но это всего лишь сгенерирует длиннющий стек вложенных исключений (и это не связано с вызовом реализации метода в интерфейсе, так просто запрещено делать):

Не очень-то полезно.

Использование Method Handles API

Так, поиск в Гугле выдает нам, что нужно использовать MethodHandles API. Ну что, давайте попробуем!

Круто, похоже, что заработало!

Вызов метода интерфейса с не приватным доступом

Интерфейс из примера выше был аккуратно сделан так, чтобы у вызывающего кода к нему был приватный доступ, т.е. интерфейс был вложен в вызывающий класс. А что, если у нас есть не вложенный интерфейс?

Почти такой же код больше не работает. Получаем исключение IllegalAccessException:

Фигня вышла. Если погуглить еще, можно найти следующее решение, которое получает доступ к внутренностям MethodHandles.Lookup через рефлексию.

И, ура, мы получаем:

У нас получилось сделать это на JDK 8. Как насчет JDK 9 или 10?

Опачки. Это то, что происходит по умолчанию. Если мы запустим программу с флагом —illegal-access=deny :

Ну, тогда мы получаем (и правильно!):

Одна из целей проекта Jigsaw была как раз именно в том, чтобы не допускать подобных хаков. Так, а какое решение лучше? Это?

Отлично, это работает в Java 9 и 10, а как насчет Java 8?

Вы издеваетесь, да?

Итак, у нас есть решение (хак), которое работает в Java 8, но не в 9 и 10, и есть решение, которое работает в 9 и 10, но не в 8

Более глубокое исследование

Ну что, я только что попробовал запустить разный код на разных JDK. Следующий класс пробует все вышеперечисленные комбинации. Он также доступен в виде GIST здесь.

Компилируйте код с использованием JDK 9 или 10 (потому что требуется JDK 9+ API: MethodHandles.privateLookupIn()), но компилировать нужно командой, указанной ниже, чтобы можно было запустить класс на JDK 8:

Вывод вышеприведенной программы:

Заключение

Понять все это немного сложновато.

  • В Java 8 наилучший рабочий подход – хак, который влезает во внутренности JDK через доступ к package-private конструктору класса Lookup . Это единственный способ единообразно вызывать методы интерфейсов как с приватным доступом, так и с не приватным доступом из любого класса.
  • В Java 9 и 10 лучший способ — использовать Lookup.findSpecial() (не работает в Java 8) или MethodHandles.privateLookupIn() (метод не существует в Java 8). Последний подход нужно использовать, если интерфейс находится в другом модуле. Этот модуль должен предоставлять интерфейс для вызова извне.

Честно сказать, это немного запутанно. Подходящий мем для этого:

Rafael Winterhalter (автор ByteBuddy) сказал, что, “настоящий” фикс будет в переработанной версии Proxy API:

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

И ясно, что эта статья не полная, например, не тестировалось, будут ли эти подходы работать, если Duck импортирован из другого модуля:

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

Когда я щелкаю по классу с main → run как java application, возникают следующие проблемы:

Источник: computermaker.info

Техника и Гаджеты
Добавить комментарий