2023-01-04
温故知新
00
请注意,本文编写于 559 天前,最后修改于 111 天前,其中某些信息可能已经过时。

目录

简介
报错示例
报错原因
报错解决
问题排查思路总结

简介

一次踩坑记录。

本地安装多个版本的JDK时,如果不指定版本启动Java程序,我的本地是默认使用高版本的,所以出现了预料之外的错误。

报错示例

  • 报错场景:使用JWT工具生成token时,需要使用DatatypeConverter类进行一些数据处理。
java.lang.ClassNotFoundException: javax.xml.bind.DatatypeConverter at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:445) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:587) at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:94) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) at com.hlkj.dncc.util.JwtHelper.createJwt(JwtHelper.java:48) at com.hlkj.dncc.service.impl.AccountServiceImpl.login(AccountServiceImpl.java:89) at com.hlkj.dncc.controller.AccountController.login(AccountController.java:37) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892)

报错原因

我在开发时使用的是JDK8环境,但是我本地安装了多个版本的JDK,包括JDK11JDK17。当我将代码打包成jar包后,在本地试运行,他默认使用的不是JDK8,而是JDK17

  • 检查JDK版本:cmd窗口执行java -version,输出如下信息
shell
java version "17.0.5" 2022-10-18 LTS Java(TM) SE Runtime Environment (build 17.0.5+9-LTS-191) Java HotSpot(TM) 64-Bit Server VM (build 17.0.5+9-LTS-191, mixed mode, sharing)

未知疑问:正常来说,这里应该是环境变量配置的JDK版本才对,刚开始的解决思路也是去修改环境变量为JDK8,但是当我去修改时,发现环境变量配置的是JDK11,这就让我呆住了。

所以我也没有去修改环境变量,而是通过设置临时环境变量的方式来解决这个问题。

报错解决

PS:如果你可以跳过本地试运行这一步,不解决这个问题也无所谓,直接到正常的服务器上试运行即可。

  • 设置临时环境变量。注意其中C:\Program Files\Java\jdk1.8.0_281\bin是你想要的JDK版本的可执行文件路径,根据自身实际情况配置。
shell
set PATH=C:\Program Files\Java\jdk1.8.0_281\bin
  • 配置完成后,再次查看java版本java -version,可以发现已经切换到JDK8,此时正常运行程序再检查是否还会报错即可。
shell
java version "1.8.0_281" Java(TM) SE Runtime Environment (build 1.8.0_281-b09) Java HotSpot(TM) 64-Bit Server VM (build 25.281-b09, mixed mode)

问题排查思路总结

如果你知道一个知识点,这个问题可能很好解决,那就是:javax.xml.bind包,在JDK11以后,已经从jdk中完全移除。 详情可阅读官方发行说明:JDK 11 Release Notes

如果你不知道这个知识点,你可以按照常规思路排查:

  1. 首先找到包路径javax.xml.bind.DatatypeConverter
  2. 如果是其他框架依赖下的类,如org.springframework.beans等,可以检查是否存在依赖冲突。(一般是存在相同名,但版本不同的依赖被引用了)
  3. 如果不是框架依赖下的类,如本次示例中的javax.xml.bind.DatatypeConverter,看起来就是JDK应该自带的相关类,那么就可以检查是否是JDK版本或环境变量的问题。
如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:DingDangDog

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!