Почему эта ошибка иногда появляется на этапе развертывания на сервере приложений Glassfish/Payara? Я могу предположить, что сервер приложений пытается использовать два разных класса двух разных загрузчиков классов, но есть ли способ предотвратить такое поведение?
Я попытался найти какой-то источник в Интернете, но ничего не нашел.
Обновлено: это происходит в том же приложении во время повторного развертывания. Это решается перезапуском сервера приложений, но это не решение.
java.lang.ClassCastException: class com.MyClass cannot be cast to class com.MyClass (com.MyClass is in unnamed module of loader org.glassfish.web.loader.WebappClassLoader@1, com.MyClass is in unnamed module of loader org.glassfish.web.loader.WebappClassLoader@2)
Последнее редактирование, после отличного отклика Стивена С. Какие есть инструменты, чтобы понять, почему Payara/GC не уничтожает старый объект?
Я могу предположить, что сервер приложений пытается использовать два разных класса двух разных загрузчиков классов, но есть ли способ предотвратить такое поведение?
Да, я думаю, что это происходит. Если одинаковые файлы .class
загружаются разными загрузчиками классов, результирующие типы среды выполнения будут разными и не могут быть преобразованы.
Есть три способа избежать этого:
Не передавайте и не делитесь этими объектами между разными веб-приложениями.
Переместите JAR-файлы, которые определяют классы, которые необходимо использовать совместно, в область общей библиотеки веб-контейнера... так, чтобы они загружались загрузчиком классов веб-контейнера, а не загрузчиками классов веб-приложений.
Если классы должны быть загружены несколькими загрузчиками классов веб-приложений (например, потому что они имеют одно и то же имя, но разные реализации), вам может потребоваться изменить архитектуру вашего приложения, чтобы классы реализовывали общий интерфейс, который загружается одним загрузчиком классов. Если ваш код веб-приложения затем приводит только к общему интерфейсу, вы не столкнетесь с этой проблемой.
Что, если веб-приложение такое же? (поэтому, когда приложение повторно развертывает одно и то же приложение)
Если это так, то похоже, что проблема в том, что код выключения вашего веб-приложения работает неправильно. Объекты Java, созданные при более раннем развертывании веб-приложения, просачиваются в более позднее.
Отлично... Инструментально понять, почему (пайара? сборщик мусора?) решили оставить старое? Профайлер? @Стивен С
1) Эти проблемы также возникнут при повторном развертывании того же приложения. Каждое повторное развертывание создает новый загрузчик классов. 2) Я не понимаю, о чем вы спрашиваете.
Честно говоря, я не знаю подходящего инструмента для исследования и устранения таких проблем, как я могу проверить, не скрываются ли «объекты приложения в состоянии сеанса или в локальных потоках»?
Что ж... вы могли бы написать код, который просматривает объекты, которые скрываются в состоянии сеанса или в локальных переменных потока. Или вы можете написать некоторый код, который очищает все состояние сеанса или локальные потоки при повторном развертывании. Или вы можете вручную проверить свой код, чтобы увидеть, какие объекты там хранятся.
Mhnn ok @StephenC Я попытался с помощью JProfiler найти «корни GC», я удалил из проекта все эти ссылки, пока класс не исчез из моментального снимка кучи. Я переустанавливал без сеанса, но проблема не устранена, что еще можно попробовать? :( Единственный момент, который ясен, это то, что когда должен вызываться адаптер jsonb, загруженный класс внутри JsonBSingleton является одним из старых путей к классам. Я попытался выполнить быстрый поиск в Интернете, но безуспешно. У вас есть ссылка на «Или вы могли бы написать какой-нибудь код, который очищает все состояние сеанса или локальные потоки при повторном развертывании»?
Что, если веб-приложение такое же? (поэтому, когда приложение повторно развертывает одно и то же приложение)