Сбой приложения Spring при запуске с NoClassDefFoundError при развертывании на сервере tc с Insight

У меня есть приложение на основе Spring (упакованное в WAR), которое отлично работает в Jetty и «обычном» Tomcat 7, но выдает странный NoClassDefFoundError при развертывании на tc Server с помощью Spring Insight. Класс, который он жалуется, что не может быть найден, определенно находится в JAR в папке WEB-INF/lib (и я дважды проверил, что в общей папке Tomcat нет конкурирующих JAR).

Вот трассировка стека, показывающая, что Spring считает, что не может найти класс HierarchicalLoop:

java.lang.ClassNotFoundException: com.foo.HierarchicalLoop<com.foo.Loop>
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1714) ~[na:na]
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559) ~[na:na]
    ... 32 common frames omitted
Wrapped by: java.lang.NoClassDefFoundError: com/foo/HierarchicalLoop<com/foo/Loop>
    at java.lang.Class.getDeclaredConstructors0(Native Method) ~[na:1.7.0_60]
    at java.lang.Class.privateGetDeclaredConstructors(Class.java:2532) ~[na:1.7.0_60]
    at java.lang.Class.getConstructor0(Class.java:2842) ~[na:1.7.0_60]
    at java.lang.Class.getDeclaredConstructor(Class.java:2053) ~[na:1.7.0_60]
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:80) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1094) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]
    ... 26 common frames omitted
Wrapped by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'x12Builder' defined in class path resource [spring/x12-builder-config.xml]: Instantiation of bean failed; nested exception is java.lang.NoClassDefFoundError: com/foo/HierarchicalLoop<com/foo/X12Loop>
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1101) ~[spring-beans-4.1.6.RELEASE.jar:4.1.6.RELEASE]

Если я отключу Insight в экземпляре сервера, приложение загрузится нормально, и это будет воспроизведено на 3 разных машинах. Как я уже сказал, WAR также корректно загружается под Jetty и Tomcat (без Insight). Так что я почти уверен, что это сужено до того, что делает Insight.

По моему опыту, такого рода загадочные ошибки NoClassDefFoundError или ClassNotFoundException часто возникают из-за путаницы в загрузчике классов. Например, корневой загрузчик классов контейнера пытается загрузить классы из файла JAR приложения. Но в данном случае Insight для меня — черный ящик, я не знаю, что он делает под одеялом. Я подозреваю, что, возможно, классы Spring поступают из загрузчика классов, отличного от загрузчика классов моего приложения, что объясняет, почему Spring не может видеть классы из JAR-файлов в файле lib приложения. Но это не более чем обоснованное предположение, и даже если бы оно было точным, я понятия не имею, как его разрешить.

Приветствуются любые идеи по устранению неполадок или понимание того, как работает Insight.


person E-Riz    schedule 29.05.2015    source источник


Ответы (1)


Оказывается, это было связано с каким-то ограничением или ошибкой в ​​Insight. Класс, на который он жаловался, HierarchicalLoop<Loop> вызывал проблемы с загрузчиком классов Insight (TomcatWeavingInsightClassLoader), из-за чего он сообщал о нем как ClassNotFoundException. Это как-то связано с параметрами типа; вот два класса, которые были вовлечены в возникновение проблем с загрузчиком классов:

public class Loop<ChildType extends Loop> {
    //...
}

public class HierarchicalLoop<ChildType extends Loop> extends Loop<ChildType> {
    //...
}

Это совершенно допустимая Java, и никакие другие контейнеры/загрузчики классов (Tomcat, Jetty, JUnit) не имеют проблем с загрузкой этих классов. Но Insight по какой-то причине это делает.

Существуют подклассы HierarchicalLoop, но все они просто указывают Loop в качестве параметра ChildType, поэтому этот параметр на самом деле не нужен. Так что я смог обойти проблему, удалив параметр типа из HierarchicalLoop :

public class HierarchicalLoop extends Loop<Loop> {
    //..
}

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

person E-Riz    schedule 01.06.2015
comment
Э-Риз, я передам это команде Spring Insight. Спасибо за обновление. - person Jason K.; 23.06.2015