现象:
- TongWeb7 启动日志出现大量报错
- 控制台可以正常访问
- 部署的应用全部 404
- 日志中一直提示:
java.lang.NoClassDefFoundError: Could not initialize class com.tongweb.tongejb.assembler.DeployerEjb
先看现象
最近帮客户排查一个 TongWeb7 的问题。
启动的时候日志一直报错:
text
java.lang.NoClassDefFoundError:
Could not initialize class
com.tongweb.tongejb.assembler.DeployerEjb

第一眼看到这个错误,我的反应和很多人一样:
是不是 TongWeb 缺少 Jar 包?
是不是版本有问题?
是不是安装包损坏了?
但是继续观察发现了一个很奇怪的现象。
- TongWeb 控制台可以正常访问
- 服务其实已经启动成功
- 唯独应用访问全部 404
说明 TongWeb 并没有真正启动失败,而是应用没有成功部署。
这时候排查方向就不能只盯着 NoClassDefFoundError 了。
第一反应:先对比 Jar 包
因为异常提示的是:
text
Could not initialize class
很多人第一反应都会怀疑:
是不是少了某个 Jar?
于是我找到另外一台正常运行的 TongWeb。
把两个 TongWeb 的 Jar 包全部进行了对比。
结果发现:
完全一致,没有任何区别。
说明:
并不是安装包的问题。
日志太多,看不到真正原因
TongWeb 的启动日志非常长。
前面几百行都是各种初始化信息。
真正有价值的异常,很容易被淹没。
翻了很久日志,都没有发现真正的问题。
后来突然想到一个经验:
Java 的真正原因,很多时候都藏在 Caused by 后面。
于是没有继续人工翻日志,而是直接过滤。
例如:
bash
grep "Caused by" server.log
果然一下子找到了真正的异常。
真正的问题终于出现了
过滤以后,看到了下面这段日志。

核心内容如下:
text
Caused by:
com.tongweb.tongejb.OpenEJBRuntimeException:
cannot create unique file,
please set java.io.tmpdir to a writable folder
or create work folder
继续往下看。
还有真正的 IOException。
text
Caused by:
java.io.IOException:
Permission denied
看到这里,问题基本就已经明确了。
不是类找不到。
而是:
初始化这个类的时候,需要创建临时文件,但是没有权限
所以最终才导致:
text
NoClassDefFoundError
很多时候:
NoClassDefFoundError 并不是类不存在。
而是:
类初始化失败。
真正原因一定要继续往下找。
为什么会没有权限?
继续检查对应目录。
发现 temp 目录里的文件居然属于 root。
后来和客户沟通了解到。
客户平时有两种启动方式。
有时候:
text
root
启动 TongWeb。
有时候:
text
普通用户
启动 TongWeb。
例如:
今天 root 部署应用。
明天普通用户启动。
后天又 root 更新。
这样来回切换以后。
temp、work、deployment 等目录,很容易出现:
文件属于 root,普通用户没有写权限。
于是:
初始化临时文件失败。
应用部署失败。
最终表现出来就是:
- 控制台正常
- 应用 404
- NoClassDefFoundError
最终解决办法
把 temp 目录重新赋予普通用户权限即可。
例如:
bash
chown -R coremail:coremail /tongweb/TongWeb7/temp
然后重新启动 TongWeb。
结果:
- 不再出现 NoClassDefFoundError
- 应用正常部署
- 页面恢复访问
问题彻底解决。
为什么会出现 NoClassDefFoundError?
很多人看到这个异常就开始找 Jar。
其实 Java 里面,它还有另一种情况。
例如:
text
class A {
static{
// 初始化失败
}
}
如果静态代码块执行失败。
或者静态变量初始化失败。
那么以后再次加载这个类。
Java 就会直接抛:
text
NoClassDefFoundError
所以:
看到这个异常,不一定是缺类。
还要继续看:
text
Caused by
那里才是真正原因。
以后遇到这种问题,可以按照这个思路排查
① 不要只看第一条异常。
很多时候第一条只是结果。
真正原因在下面。
② 重点搜索 Caused by。
例如:
bash
grep "Caused by" server.log
效率远远高于人工翻日志。
③ 确认是不是权限问题。
重点检查:
- temp
- work
- deployment
- logs
看看目录是不是属于 root。
普通用户有没有写权限。
④ 如果两台环境一台正常一台异常。
先不要怀疑程序。
先对比:
- Jar 包
- 配置
- 用户
- 文件权限
很多问题,其实都出在运行环境。
思考
这次排查,真正花时间的不是解决问题,而是找到真正的异常。
日志里一直提示的是:
text
NoClassDefFoundError
如果一直围绕这个错误去分析,很容易认为是 Jar 包、版本或者安装包的问题。
但真正的根因,其实藏在 Caused by 后面的几行日志里。
以后排查 Java 或 TongWeb 启动问题时,可以记住一个思路:
第一条异常只是现象,最后一个
Caused by才最有可能是真正的原因。
很多启动失败、应用 404、部署异常的问题,都可以按照这个思路一步步缩小范围,最终定位到根因,而不是被表面的报错带偏方向。