java.lang.NoClassDefFoundError 对于 clojure.java.api.Clojure

java.lang.NoClassDefFoundError for clojure.java.api.Clojure

我们正在为一个毫无意义的 java.lang.NoClassDefFoundError 苦苦挣扎。

相同 WAR 文件在服务器 B 中运行完美,但在服务器 A 上抛出 java.lang.NoClassDefFoundError。

配置为:

服务器 A(抛出异常):

OS: 
    NAME="SLES"
    VERSION="12-SP4"
    VERSION_ID="12.4"
    PRETTY_NAME="SUSE Linux Enterprise Server 12 SP4"
Apache Tomcat 8.5.49
Oracle Java dk1.8.0_231

服务器 B(完美运行):

OS:
    NAME="Ubuntu"
    VERSION="16.04.6 LTS (Xenial Xerus)"
    ID=ubuntu
    ID_LIKE=debian
    VERSION_ID="16.04"
    PRETTY_NAME="Ubuntu 16.04.6 LTS"
Apache Tomcat 8.5.37
Oracle Java jdk 1.8.0_201-b09

例外情况是:

2020-01-27 15:57:27.103 [http-nio-8081-exec-10] ERROR o.g.w.errors.GrailsExceptionResolver - NoClassDefFoundError occurred when processing request: [GET] /server-0.1/cenario/getCenarioJson
Could not initialize class clojure.java.api.Clojure. Stacktrace follows:
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class clojure.java.api.Clojure
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:982)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
        ...
        at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NoClassDefFoundError: Could not initialize class clojure.java.api.Clojure
        at com.nitryx.brkmopt.util.ClojureHandler.invoke(ClojureHandler.java:176)
        at com.nitryx.brkmopt.util.ClojureHandler.invoke(ClojureHandler.java:173)
        at com.nitryx.brkmopt.CenarioService.$tt__getCenarioJson(CenarioService.groovy:35)
        ...        

WAR 文件在服务器 B 上运行完美,但在服务器 A 上抛出异常。

我们检查了 tomcat 下的 ~/WEB-INF/lib/ 文件夹,必要的依赖项 (clojure-1.9.0.jar) 在那里并且是一致的。孤注一掷,我们甚至尝试过手动更换新的jar文件,但没有成功。

来自 Why am I getting a NoClassDefFoundError in Java? :

java.lang.NoClassDefFoundError This exception indicates that the JVM looked in its internal class definition data structure for the definition of a class and did not find it. This is different than saying that it could not be loaded from the classpath. Usually this indicates that we previously attempted to load a class from the classpath, but it failed for some reason

请指教!

编辑: 完整的堆栈跟踪:(非常感谢 clojurians @jumar @alexmiller @ghadi @seancorfield)

2020-02-05 16:00:02.342 [http-nio-8081-exec-10] ERROR o.g.w.errors.GrailsExceptionResolver - NoClassDefFoundError occurred when processing request: [GET] /server-0.1/cenario/getCenarioJson
Could not initialize class clojure.java.api.Clojure. Stacktrace follows:
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class clojure.java.api.Clojure
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:982)
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
        at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:239)
        at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:215)
        at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
        at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:239)
        at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:215)
        at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
        at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
        at org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:130)
        at org.springframework.boot.web.support.ErrorPageFilter.access[=15=]0(ErrorPageFilter.java:66)
        at org.springframework.boot.web.support.ErrorPageFilter.doFilterInternal(ErrorPageFilter.java:105)
        at org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:123)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NoClassDefFoundError: Could not initialize class clojure.java.api.Clojure
        at com.nitryx.brkmopt.util.ClojureHandler.invoke(ClojureHandler.java:176)
        at com.nitryx.brkmopt.util.ClojureHandler.invoke(ClojureHandler.java:173)
        at com.nitryx.brkmopt.CenarioService.$tt__getCenarioJson(CenarioService.groovy:35)
        at grails.melody.plugin.MelodyInterceptorEnhancer$_enhance_closure1$_closure2.doCall(MelodyInterceptorEnhancer.groovy:77)
        at grails.gorm.transactions.GrailsTransactionTemplate.doInTransaction(GrailsTransactionTemplate.groovy:94)
        at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133)
        at grails.gorm.transactions.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:91)
        at grails.melody.plugin.MelodyInterceptorEnhancer$_enhance_closure1$_closure2.doCall(MelodyInterceptorEnhancer.groovy:77)
        at com.nitryx.brkmopt.CenarioController.getCenarioJson(CenarioController.groovy:20)
        at org.grails.core.DefaultGrailsControllerClass$MethodHandleInvoker.invoke(DefaultGrailsControllerClass.java:223)
        at org.grails.core.DefaultGrailsControllerClass.invoke(DefaultGrailsControllerClass.java:188)
        at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:90)
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
        ... 18 common frames omitted

看起来 Tomcat 8.5.50 在 Catalina 中包含了一堆回归修复和资源加载,这可能会影响 Clojure 源文件的加载。建议降级到与工作相同的版本或升级到 8.5.50。

https://tomcat.apache.org/tomcat-8.5-doc/changelog.html