欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 旅游 > NoClassDefFoundError: Could not initialize class竟与环境变量有关

NoClassDefFoundError: Could not initialize class竟与环境变量有关

2025/2/23 1:33:53 来源:https://blog.csdn.net/m0_48333563/article/details/141119510  浏览:    关键词:NoClassDefFoundError: Could not initialize class竟与环境变量有关

项目场景:

基于本地提供的jar包实现gtp文件下载,web服务部署在Linux系统。


问题描述

每天下载文件都会出现bug,但是同个jar包手动重启又不会出现该bug,下面是日志中打印的bug记录:

org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.NoClassDefFoundError: Could not initialize class xxx.xxx.gtp.ClientKernel


原因分析:

起初看日志的报错以为是打包没有将这个ClientKernel类所在的javagtpclient.jar打进去,但是又很矛盾,每次打包都是maven clean install,怎么会出现问题呢?其次,本地包在pom中的引入方式和插件打包方式都没问题:
本地包的引入:

<dependency> .......<scope>system</scope><systemPath>/${basedir}/../../lib/javagtpclient.jar</systemPath>
</dependency>

打包方式:

<configuration><includeSystemPath>true</includeSystemPath>
</configuration>

最后将打包后的jar压缩打开一看,发现BOOT-INF/lib下确实有这个jar包,同时结合每天早上手动重启前后使用的都是同一个jar包,证实了并不是打包的时候没有将这个类所在的gtpclient.jar打包进去;
然后进一步看bug记录中的调用栈,发现最顶层的栈桢是xxx.xxx.GtpClient.(GtpClient.java8)
顺着这个线索,发现ClientKernel是GtpClient的成员变量,而且采用的是饿汉模式构造,同时GtpClient还静态加载了动态链接库(system.loadLibrary("javagtp_client);),再加上是xxx.xxx.GtpClient.,我就把目光投向了加载动态链接库这块地方:有没有可能是找不到这个文件?我就在服务器上搜*javagtp_client.so(find / -name *javagtp_client.so),果然搜到了,具体名称是(libjavagtp_client.so),这是linux系统的,在win上应是javagtp_client.dll。那确实有啊,怎么会找不到呢?于是,我又搜“java部署找不到.so文件”,发现了一个LD_LIBRARY_PATH的字眼,其中百度的释义:

LD_LIBRARY_PATH是Linux环境变量名,该环境变量主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径。

然后我手动echo了以下LD_LIBRARY_PATH:echo $LD_LIBRARY_PATH,发现了打印出的路径确实是libjavagtp_client.so所在的目录。于是我又想着,既然能打印,同时手动重启web服务能上传文件不报错,那么/etc/profile中是不是会有呢?接着vim了一下这个文件,发现这个目录确实被显示声明了(export命令)。这就奇怪了,为什么每天手动重启前都会报错了,感觉昨天晚上重启了一样。忽然,我想着看看jar进程,看下启动时间,23:30:这是我配置了LInux系统级别的定时任务(/etc/crontab),每晚11:35重启。配置如下:

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:usr/bin
MAILTO=root
30 23 * * * root /xxx/xxx.sh

虽说这个导致了服务定时每晚11:30重启,但是看着也没毛病。于是我带着“Linux定时任务读取不到.so文件”去搜,最终定位到了环境变量的字眼。说是Linux的定时任务仅加载了极少部分的环境变量且并未载入 /etc/profile,因此我们需要引入相关的环境变量(具体可网搜)。


解决方案:

这里我将原来脚本的启动命令30 23 * * * root /xxx/xxx.sh修改成30 23 * * * root souce /etc/profile && /xxx/xxx.sh,因为所需的环境变量已经在/etc/profile中export声明了。

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:usr/bin
MAILTO=root
30 23 * * * root souce /etc/profile && /xxx/xxx.sh

其他解决方案:
java启动命令添加-Djava.library.path=/path/to/library:/another/path ...指定java.library.path路径

参考
参考2(重点)

参考3
参考4
参考5
参考6
参考7
参考8

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词