#java #reflection #classloader
#java #отражение #classloader
Вопрос:
У меня есть структура проекта EAR:
EAR
-
TestDependency.jar
- MyInterface.class;
-
TestEJBModule.jar
- ExternalObject.class (реализует MyInterface);
-
TestWar
- SingletonBean
- MyTestClass (реализует MyInterface);
В одноэлементном компоненте мне нужно динамически создавать класс ExternalObject, используя имя класса, но я получаю
Caused by: javax.ejb.EJBException: java.lang.ClassCastException: com.bsssrl.testejbmodule.ExternalObject cannot be cast to com.bsssrl.MyInterface
Код является:
Class localclass = Class.forName("com.bsssrl.test.testwar.MyTestClass");
Object olocal = localclass.newInstance();
MyInterface local = (MyInterface) olocal;
LOG.log(Level.INFO, "Test local.getString() : {0}",local.getString());
LOG.log(Level.INFO, "Test local.getAlfa() : {0}",local.getAlfa());
Class exclass = Class.forName("com.bsssrl.testejbmodule.ExternalObject");
Object oex = exclass.newInstance();
if(MyInterface.class.isAssignableFrom(exclass)){
MyInterface extern = (MyInterface) oex;
LOG.log(Level.INFO, "Test extern.getString() : {0}",extern.getString());
LOG.log(Level.INFO, "Test extern.getAlfa() : {0}",extern.getAlfa());
}else{
LOG.log(Level.SEVERE, "Class {0} not implement MyInterface",exclass);
}
Класс является:
public class ExternalObject implements MyInterface{
public Alfa alfa;
@Override
public String getString() {
return "from external object in EJB module";
}
@Override
public Alfa getAlfa() {
return alfa;
}
@Override
public void setAlfa(Alfa a) {
this.alfa = a;
}
}
Первый фрагмент кода работает, но второй запускает ClassCastException;
Я полагаю, у меня проблема с classloader.
Как я могу это решить?
PS: я использую wildfly-9.0.2.Final
Комментарии:
1. попробуйте проверить, реализует ли ExternalObject MyInterface.
2. @RayLloy я изменил код в вопросе, добавив проверку … проверка завершается неудачей, даже если ExternalObject реализует MyInterface
3. Я выполнил тот же тест, что и Java-приложение, и ваша проверка работает нормально. Вы уверены, что создали TestEJBModule. jar после модификации?
Ответ №1:
Если вы получаете исключения classcast между совместимыми классами, это всегда означает, что они были загружены разными загрузчиками классов (очень вероятно, поскольку один находится в состоянии ВОЙНЫ, другой в EAR) или что доступно несколько версий класса, и выбирается неправильная (несовместимая). С JBoss / Wildfly последнее особенно легко сделать, поскольку у него испорченная стратегия загрузки классов.
Чтобы проверить первое, попробуйте установить classloader на тот же, который был загружен MyInterface
явно:
Class.forName("com.bsssrl.testejbmodule.ExternalObject", true, MyInterface.class.getClassLoader())
Комментарии:
1. Попробовав, я получаю ту же ошибку:
ClassLoader clInterfaccia = MyInterface.class.getClassLoader(); localclass = Class.forName(classname, true, clInterfaccia); olocal = localclass.newInstance(); if(MyInterface.class.isAssignableFrom(localclass)) -> false
Ответ №2:
Я получил ClassCastException на
IService iService=(IService) classS.newInstance();
с
urlClassLoader=URLClassLoader.newInstance(new URL[] {new URL(urlStr)});
а затем добавьте загрузчик класса в качестве параметра newInstance, и это решило проблему для меня:
urlClassLoader=URLClassLoader.newInstance(new URL[] {new URL(urlStr)},IService.class.getClassLoader());