【TongWeb7】启动接近两分钟问题排查

问题现象

客户反馈 TongWeb7 启动速度较慢,完整启动接近两分钟。

刚开始接收到这个问题时,不能直接判断是 TongWeb 本身启动慢。

因为 Java 应用启动过程比较复杂,除了中间件自身初始化,还可能受到外部环境影响,例如:

  • JVM参数配置
  • 服务器DNS解析
  • 应用部署耗时
  • 磁盘IO
  • 安全软件
  • Java Agent

所以排查重点需要确认:

启动时间到底消耗在哪里。

是 TongWeb 自身组件初始化慢,还是 JVM 启动过程中被其他组件影响。


一、为什么选择jstack排查?

对于 Java 应用启动慢的问题,日志只能看到启动过程中的一些事件,但是无法直接看到 JVM 当前正在执行什么。

例如:

日志显示:

复制代码
TongWeb starting...

但是不知道:

  • 当前卡在哪个线程?
  • 正在执行哪个类?
  • 是否一直停留在某个方法?

这时候可以使用 JDK 自带工具 jstack

jstack是什么?

jstack 是 JDK 提供的 JVM 线程诊断工具。

它可以打印 Java 进程当前所有线程的信息,包括:

  • 线程名称
  • 线程状态
  • 当前执行方法
  • 锁等待情况
  • 调用链

简单理解:

jstack就是查看Java程序当前"正在做什么"的工具。

在启动慢、CPU异常、线程死锁等问题排查中,经常使用 jstack 分析。


二、jstack常用使用方式

1. 获取Java进程PID

首先查看 TongWeb JVM 进程:

bash 复制代码
ps -ef | grep java

例如:

复制代码
tongweb  12345  java com.tongweb.server.ThorBootstrap

其中:

复制代码
12345

就是 JVM 的 PID。


2. 生成线程dump

执行:

bash 复制代码
jstack 12345 > tongweb_dump.log

生成的文件中包含当前 JVM 所有线程信息。

例如:

复制代码
"main" #1

java.lang.Thread.State: RUNNABLE

at xxx.xxx.xxx

可以通过调用链判断线程当前执行位置。


3. 为什么需要连续抓取?

单次 jstack 只能代表某一个时间点。

如果是启动卡顿,需要连续抓取多次。

例如:

复制代码
jstack PID > dump1.log

sleep 5

jstack PID > dump2.log

sleep 5

jstack PID > dump3.log

然后对比三个文件。

如果发现某个线程:

几秒甚至十几秒一直停留在同一个方法,

说明启动耗时可能就在这里。


三、编写自动抓取脚本

由于客户环境不方便重复操作,所以编写了:

bash 复制代码
#!/bin/bash

# TongWeb启动卡顿自动抓取线程dump脚本

DUMP_DIR=$(pwd)

WAIT_TIMEOUT=120
INTERVAL=1

DUMP_TIMES=3
SLEEP_BETWEEN_DUMP=3


echo "停止正在运行的TongWeb"

sh stopserver.sh

sleep 2


echo "后台启动TongWeb"

sh startservernohup.sh


START_TIME=$(date +%s)

PID=""


while true
do

    NOW=$(date +%s)

    ELAPSED=$((NOW - START_TIME))


    if [ ${ELAPSED} -ge ${WAIT_TIMEOUT} ];then

        echo "超过等待时间,未检测到TongWeb进程"

        exit 1

    fi


    PID=$(ps -ef | grep ThorBootstrap | grep -v grep | awk '{print $2}')


    if [ -n "${PID}" ];then

        echo "成功获取TongWeb PID=${PID}"

        break

    fi


    echo "等待TongWeb启动 ${ELAPSED}s"

    sleep ${INTERVAL}

done



i=1

while [ $i -le ${DUMP_TIMES} ]

do

    FILE="${DUMP_DIR}/tongweb_start_dump_$(date +%Y%m%d_%H%M%S)_${i}.log"


    echo "生成dump文件:${FILE}"


    jstack ${PID} > ${FILE}


    sleep ${SLEEP_BETWEEN_DUMP}


    i=$((i+1))

done


echo "抓取完成"

脚本主要作用:

  1. 停止当前 TongWeb
  2. 重新后台启动 TongWeb
  3. 自动获取 TongWeb PID
  4. 连续抓取3次 jstack
  5. 保存线程快照方便分析

执行:

复制代码
bash dump_start_block.sh

核心逻辑:

复制代码
PID=$(ps -ef | grep ThorBootstrap | grep -v grep | awk '{print $2}')

jstack ${PID} > tongweb_start_dump.log

通过自动化方式,避免客户手动操作导致采集信息不完整。


四、分析客户提供的jstack

客户提供了三个时间点的 dump:

第一次:

复制代码
2026-07-30 15:25:51

第二次:

复制代码
2026-07-30 15:25:59

第三次:

复制代码
2026-07-30 15:26:07

三个 dump 间隔约8秒。

重点查看 JVM 主线程。

三个文件中都出现:

复制代码
"main" #1

java.lang.Thread.State: RUNNABLE

at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method)

at java.net.InetAddress.getLocalHost(InetAddress.java:1507)

at sun.management.VMManagementImpl.getVmId(VMManagementImpl.java:140)

at com.moresec.loader.agent.IastLoaderAgent.getProcessId(IastLoaderAgent.java:239)

at com.moresec.loader.agent.IastLoaderAgent.premain(IastLoaderAgent.java:43)

五、关键调用分析

重点关注:

复制代码
com.moresec.loader.agent.IastLoaderAgent

继续向上看调用关系:

复制代码
IastLoaderAgent

    ↓

获取Java进程信息

    ↓

InetAddress.getLocalHost()

    ↓

主机名解析

这里可以发现:

当前线程执行的并不是 TongWeb 内部代码。

而是在加载:

复制代码
MoresecAgent
IastLoaderAgent

这说明 JVM 启动阶段存在外部 Java Agent。


六、什么是Java Agent?

Java Agent 是一种 JVM 扩展机制。

它可以在 Java 应用启动之前,通过:

复制代码
-javaagent

参数加载。

常见用途:

  • 安全检测
  • 应用监控
  • 链路追踪
  • 字节码增强

例如:

服务器安装漏洞扫描工具后,可能会自动给 Java 服务增加 Agent。

此时:

Java应用启动流程变成:

复制代码
JVM启动

↓

加载Java Agent

↓

Agent初始化

↓

TongWeb启动

↓

应用加载

如果 Agent 初始化耗时,就会影响整体启动时间。


七、三次dump对比定位问题

三个时间点中:

main线程一直停留:

复制代码
com.moresec.loader.agent.IastLoaderAgent.getProcessId

说明:

经过多个时间点采样,线程没有明显推进。

如果是 TongWeb 自身部署慢,通常会看到:

复制代码
Deployer

ApplicationLoader

WebContainer

EJB

等相关调用。

但是本次没有出现 TongWeb 初始化相关调用。

反而一直停留:

复制代码
MoresecAgent

IastLoaderAgent

InetAddress.getLocalHost

因此判断:

TongWeb启动慢不是TongWeb自身原因,而是外部安全Agent影响。


八、最终定位结果

继续和客户确认服务器环境。

客户反馈:

服务器安装了漏洞检测工具。

该工具通过 Java Agent 方式注入 TongWeb JVM。

启动过程中:

  1. JVM加载安全Agent
  2. Agent获取Java进程信息
  3. Agent获取服务器主机信息
  4. 执行安全检测逻辑

其中:

复制代码
InetAddress.getLocalHost()

涉及主机名解析。

如果服务器DNS或者hosts配置不合理,会进一步增加耗时。

最终确认:

TongWeb7启动慢主要由于服务器漏洞扫描工具加载Java Agent导致。


九、处理建议

1. 查看Java启动参数

执行:

复制代码
ps -ef | grep java

确认是否存在:

复制代码
-javaagent

参数。


2. 检查hosts解析

执行:

复制代码
hostname

cat /etc/hosts

确认服务器 hostname 可以正常解析。


3. 验证安全工具影响

可以临时关闭漏洞扫描工具,再重新启动 TongWeb。

如果启动时间恢复正常,则可以进一步确认。


十、这次排查学到了什么

以前遇到中间件启动慢的问题,容易关注:

  • TongWeb启动日志
  • 应用部署情况
  • JVM内存参数

但是实际生产环境中:

Java应用启动链路并不只有中间件本身。

很多外部组件都会参与 JVM 启动:

  • 安全扫描工具
  • 监控Agent
  • 链路追踪工具

这些组件通过 Java Agent 进入 JVM 后,也可能影响启动速度。

通过这次问题排查,最大的收获:

排查Java应用问题,不能只看应用本身,需要站在整个JVM启动链路分析。

使用连续多个时间点的 jstack,可以快速判断:

到底是 TongWeb 卡住了,

还是外部组件影响了启动流程。

相关推荐
八角.。1 小时前
Java案例-学生管理系统
java
深色風信子1 小时前
Kotlin Bytedeco OpenCV 图像图像58 无缝克隆
开发语言·opencv·kotlin·bytedeco
朝阳391 小时前
react19【系列实用教程】实用组件封装
开发语言·前端·javascript
我是苏苏2 小时前
C#基础:使用System.Speech.Synthesis离线播放/朗读文字内容
开发语言·c#
Patrick在香港2 小时前
Python依赖管理从踩坑到选型:pip/poetry/uv四种方案全面实测
开发语言·python·数据分析·scikit-learn·ai编程·pip·uv
骇客野人2 小时前
IntelliJ IDEA 菜单中英对照
java·ide·intellij-idea
我命由我123452 小时前
Kotlin 面向对象 - 枚举排序
android·java·开发语言·java-ee·kotlin·android studio·android-studio
程序喵大人2 小时前
【C++进阶】STL容器与迭代器 - 10 把容器、迭代器和数据流串成一个小程序
开发语言·c++·容器·小程序·迭代器·stl
Sam_Deep_Thinking2 小时前
用Java 17从0到1写一个mini版RPC,理解远程调用的本质
java·面试·rpc·程序员·系统架构