JDK8升级至JDK17时Jersey服务报NoClassDefFoundError求助
JDK8升级JDK17时Jersey 2.35初始化异常排查与适配方案
问题背景
基于Maven的Java项目从JDK8升级至JDK17,使用Jersey 2.35版本,启动时出现Servlet初始化异常,阻碍升级进度。
异常栈信息
顶层异常
javax.servlet.ServletException: Servlet.init() for servlet [Servlet_Class] threw exception org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687) org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890) org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743) org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) java.base/java.lang.Thread.run(Thread.java:833)
根因异常
java.lang.NoClassDefFoundError: Could not initialize class org.glassfish.jersey.internal.inject.Providers org.glassfish.jersey.model.internal.ComponentBag.modelFor(ComponentBag.java:495) org.glassfish.jersey.model.internal.ComponentBag.lambda$registerModel$10(ComponentBag.java:454) org.glassfish.jersey.internal.Errors.process(Errors.java:292) org.glassfish.jersey.internal.Errors.process(Errors.java:274) org.glassfish.jersey.internal.Errors.process(Errors.java:205) org.glassfish.jersey.model.internal.ComponentBag.registerModel(ComponentBag.java:446) org.glassfish.jersey.model.internal.ComponentBag.register(ComponentBag.java:357) org.glassfish.jersey.model.internal.CommonConfig.register(CommonConfig.java:463) org.glassfish.jersey.server.ResourceConfig.register(ResourceConfig.java:429) org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:306) org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:154) org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:339) javax.servlet.GenericServlet.init(GenericServlet.java:158) org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687) org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890) org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1743) org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) java.base/java.lang.Thread.run(Thread.java:833)
项目配置与代码
web.xml配置
<servlet> <servlet-name>Servlet_Class</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <!--<init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>webservices.Jersey</param-value> </init-param> --> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>webservices.Jersey.Servlet_Application</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Servlet_Class</servlet-name> <url-pattern>/Jersey/*</url-pattern> </servlet-mapping>
Servlet_Application实现代码
package webservices.Jersey; import org.glassfish.jersey.logging.LoggingFeature; import org.glassfish.jersey.server.ResourceConfig; public class Servlet_Application extends ResourceConfig { public Servlet_Application() { packages(true, "webservices.Jersey"); register(LoggingFeature.class); register(Servlet_Class.class); } }
问题定位
- JDK17模块化与反射限制:Jersey 2.35未完全适配JDK17的模块系统(JPMS),其内部依赖的反射操作被JDK17默认禁用的
--illegal-access机制阻止,导致org.glassfish.jersey.internal.inject.Providers类初始化失败。 - 依赖兼容性缺失:Jersey 2.35的底层依赖(如HK2注入框架、核心组件)未针对JDK17的API变更做适配,触发类加载时的
NoClassDefFoundError。 - 冗余注册隐患:
Servlet_Application中同时调用包扫描和手动注册Servlet_Class,虽然不是本次异常的直接根因,但可能引发重复加载冲突。
适配JDK17的Jersey版本推荐
- 最低兼容版本:Jersey 2.39.1,该版本开始正式支持JDK17,修复了JPMS模块访问、反射权限等核心适配问题。
- 推荐稳定版本:Jersey 2.41(截至2024年的最新稳定版),包含更多JDK17及后续版本的兼容性修复,同时修复了多个安全漏洞和功能bug。
解决步骤建议
- 统一升级Jersey版本:在Maven的
pom.xml中将所有Jersey相关依赖的版本号修改为2.41(或2.39.1),确保组件版本一致,避免版本冲突。 - 移除冗余注册代码:删除
Servlet_Application中的register(Servlet_Class.class)调用,packages(true, "webservices.Jersey")已完成包内资源类的自动扫描注册。 - 可选:调整JVM参数:若升级后仍有反射相关异常,可临时添加JVM启动参数
--add-opens java.base/java.lang=ALL-UNNAMED,但优先通过版本升级解决问题。
内容的提问来源于stack exchange,提问作者imzz
相关产品推荐
相关产品推荐

