Вопрос-ответ

ClassCastException when casting to the same class

ClassCastException при приведении к тому же классу

У меня есть 2 разных Java-проекта, в одном есть 2 класса: dynamicbeans.DynamicBean2 и dynamic.Validator.

В другом проекте я динамически загружаю оба этих класса и сохраняю их в Object

class Form {
Class beanClass;
Class validatorClass;
Validator validator;
}

Затем я продолжаю и создаю Validator объект с помощью validatorClass.newInstance() и сохраняю его на validator затем я также создаю bean-объект с помощью beanClass.newInstance() и добавляю его в сеанс.

portletRequest.setAttribute("DynamicBean2", bean);

В течение жизненного цикла Form проекта я вызываю validator.validate() который загружает ранее созданный объект bean из сеанса (я использую Websphere Portal Server). Когда я пытаюсь привести этот объект обратно в DynamicBean2 он завершается неудачей с ClassCastException.

Когда я вытаскиваю объект обратно из сеанса с помощью

faces.getApplication().createValueBinding("#{DynamicBean2}").getValue(faces);

и проверьте его класс, используя .getClass() я получаю dynamicbeans.DynamicBean2. Это класс, к которому я хочу привести его, однако при попытке я получаю ClassCastException.

Есть какая-нибудь причина, по которой я это получаю?

Переведено автоматически
Ответ 1

Я не совсем понимаю ваше описание потока работы программы, но обычно, когда вы получаете ClassCastExceptions, вы не можете объяснить, что вы загрузили класс с помощью одного classloader, а затем пытаетесь привести его к тому же классу, загруженному другим classloader. Это не сработает - они представлены двумя разными объектами класса внутри JVM, и приведение завершится ошибкой.

Есть статья о загрузке классов в WebSphere. Я не могу сказать, как это применимо к вашему приложению, но есть ряд возможных решений. Я могу придумать по крайней мере:


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


    Thread.currentThread().setContextClassLoader(...);

  2. Убедитесь, что класс загружен загрузчиком классов выше по иерархии.


  3. Сериализуйте и десериализуйте объект. (Фу!)


Однако, вероятно, есть более подходящий способ для вашей конкретной ситуации.

Ответ 2

Я столкнулся с этой проблемой после добавления зависимости в spring-boot-devtools в моем проекте Springboot. Я удалил зависимость, и проблема исчезла. Мое лучшее предположение на данный момент заключается в том, что spring-boot-devtools вводит новый загрузчик классов, и это вызывает проблемы с приведением классов между разными загрузчиками классов в определенных случаях, когда новый загрузчик классов не используется некоторыми потоками.

Ссылка: Исключение карты бульдозера, связанное с Spring boot devtools

Ответ 3

Объекты класса были загружены в разные загрузчики классов, поэтому экземпляры, созданные из каждого из классов, рассматриваются как "несовместимые". Это распространенная проблема в среде, где используется много разных загрузчиков классов и объекты передаются по кругу. Эти проблемы могут легко возникнуть в средах Java EE и portal.

Для приведения экземпляра класса требуется, чтобы класс, связанный с приводимым объектом, совпадал с классом, загруженным текущим загрузчиком классов контекста потока.

Ответ 4

У меня возникла проблема с A2AClassCastException при попытке создать список объектов из XML с помощью Apache Commons Digester.

List<MyTemplate> templates = new ArrayList<MyTemplate>();
Digester digester = new Digester();
digester.addObjectCreate("/path/to/template", MyTemplate.class);
digester.addSetNext("/path/to/template", "add");
// Set more rules...
digester.parse(f); // f is a pre-defined File

for(MyTemplate t : templates) { // ClassCastException: Cannot cast mypackage.MyTemplate to mypackage.MyTemplate
// Do stuff
}

Как указано выше, причина в том, что digester не использует тот же ClassLoader, что и остальная часть программы. Я запустил это в JBoss, и оказалось, что это commons-digester.jar было не в каталоге lib JBoss, а скорее в каталоге lib веб-приложения. Копирование jar в mywebapp / WEB-INF / lib также решило проблему. Другим решением было использовать digester.setClassLoader(MyTemplate.class.getClassLoader()), но в данном контексте это кажется довольно уродливым решением.

2023-06-25 08:58 java reflection