【发布时间】:2020-05-13 05:36:58
【问题描述】:
我们在这里遇到了一个毫无意义的 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 这个异常表示JVM 查看其内部类定义数据结构 定义了一个类,并没有找到它。这不同于 说它无法从类路径加载。通常这个 表示我们之前尝试从 类路径,但由于某种原因它失败了
请指教!
编辑: 完整的堆栈跟踪:(非常感谢 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$000(ErrorPageFilter.java:66)
at org.springframework.boot.web.support.ErrorPageFilter$1.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$2.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 拾取并提供给所有 web 应用程序的文件已配置 - 所以一个简单的副本可能足够也可能不够。其次,从 clojure 1.9 开始,clojure.jar 还依赖于 spec-alpha 和 core-specs-alpha jars。如果是这种情况,您的 stracktrace 应该会告诉您,但我提到它以防万一。从长远来看,您最好将 clojure 依赖添加到您的 grails 项目中?
-
感谢您的见解!我们在 grails 项目中添加了所有 Clojure 依赖项。它在一台服务器(B)中运行良好。已经运行了几个月。新服务器(A)运行保存WAR文件时抛出异常。
-
其他要探索的事情:检查两个服务器中的 CLASSPATH 环境变量。 WAR 可能包含无效的 JAR,并且 Clojure 类在其他地方找到(Tomcat 自己的 JAR 或 JDK 本身的
lib文件夹中的额外 JAR)。另外,尝试在新的 Ubuntu 服务器中重现,看看差异是否可以归因于操作系统设置或 Tomcat 设置的差异。 -
我们遇到了某种类似的问题,但是第 3 方库在服务器上抛出 NoSuchMethodError,同时在本地机器上愉快地工作。原来这是一个依赖冲突——即同一个库的多个版本包含在类路径中,但与在本地运行时相比,在远程服务器上运行时选择了不同的版本。检查您的类路径是否存在冲突,可能使用
lein deps :tree。 -
好电话!我们会尽快检查!并会通知您。
标签: clojure ubuntu-16.04 tomcat8 suse clojure-java-interop