【TongWeb7启动报错】TongWeb控制台可以访问,但是应用访问404

现象:

  • 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、部署异常的问题,都可以按照这个思路一步步缩小范围,最终定位到根因,而不是被表面的报错带偏方向。

相关推荐
杨运交3 小时前
080-缓存模块-Spring Cache缓存键前缀设计与租户隔离实践
java·spring·缓存
学逆向的3 小时前
C printf原型解析
c语言·开发语言·网络安全
\光辉岁月/3 小时前
5.math类
java·开发语言
文丑颜不良啊3 小时前
LeetCode76~100题目解析
java·leetcode
她的男孩3 小时前
页面已发布用户仍进不去:Forge Admin 门户入口与系统菜单挂载解耦
java·spring boot·低代码
不像程序员的程序媛3 小时前
mybatisplus insert dto未指定id时会如何
java·开发语言
BeiGuTing_code3 小时前
C字符输出:一个换行符引发的“失踪案”
c语言·开发语言
我命由我123453 小时前
5-2.Python 编码进阶 - 字符串进阶(拼接、普通格式化、普通格式化数字精度控制、快速格式化、遍历、常用方法)
java·开发语言·后端·python·学习·java-ee·学习方法
http阿拉丁神猫7 小时前
Go语言入门笔记:从基础到开发环境搭建(二)
开发语言·笔记·golang
不会就选b8 小时前
C++补充部分(一)--lambda 表达式
开发语言·c++