我正在考虑编写一个脚本
- 每分钟(或每五分钟)运行一次
- 在生产环境中针对正在运行的 JVM 运行 jstack
- 解析 jstack 输出并统计我感兴趣的内容
- 通过在另一台服务器上集中安装 Cacti 导出 24/365 绘图结果
但我不知道 jstack 在运行的 JVM 上的成本或侵入性如何。在正在运行的 JVM 上执行 jstack 的成本是多少?我是在为一个受伤的世界做好准备吗?
我知道这个答案迟到了,但 jstack 的昂贵部分来自附加到调试器接口,通常不会生成堆栈跟踪,但有一个重要的例外(堆大小根本不重要):
任意堆栈跟踪可以仅在安全点上或在线程等待时(即在 java 范围之外)生成。如果线程正在等待/在 java 范围之外,则堆栈请求线程将通过自行执行堆栈遍历来执行任务。但是,您可能不希望“中断”一个线程来遍历它自己的堆栈,尤其是在它持有锁(或做一些忙碌的等待)时。由于无法控制安全点 - 这是需要考虑的风险。
与 jstack 相比,另一个选项避免附加到调试接口:Thread.getAllStackTraces() 或使用 ThreadMXBean,在进程中运行它,保存到文件并使用外部工具轮询该文件。
最后一点:我喜欢 jstack,它在生产系统上非常有用。
措施。其中一种time
变体(我相信是 /usr/bin/time)有一个 -p 选项,可以让您查看使用的 cpu 资源:
ravn:~ ravn$ /usr/bin/time -p echo Hello World
Hello World
real 0.32
user 0.00
sys 0.00
ravn:~ ravn$
这意味着它花费了 0.32 秒的挂墙时间,在用户空间使用了 0.00 秒的 cpu 时间,在内核空间使用了 0.00 秒。
创建一个测试场景,其中您有一个程序正在运行但没有做任何事情,并尝试与有和没有附加 jstack 的用法进行比较,例如每秒。然后你有硬数字,可以试验看看什么会产生合理的开销。
我的直觉是,每五分钟一次是可以忽略的。
根据线程的数量和堆的大小,jstack 可能会非常昂贵。JStack 用于故障排除,并不是为收集统计数据而设计的。最好在检测上使用某种形式或公开 JMX 接口以直接获取您想要的信息,而不是必须解析堆栈跟踪。