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

14 篇文章 0 订阅
4 篇文章 0 订阅

项目场景:

基于本地提供的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

  • 10
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fire king

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值