Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,27 @@ jobs:
cache: "maven"
- name: Build with Maven
run: mvn -V -ntp clean install -P full

telnet_stop_leak_it:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v3
- name: Setup java
uses: actions/setup-java@v3
with:
java-version: 17
distribution: "zulu"
cache: "maven"
- name: Install expect/telnet
run: sudo apt-get update && sudo apt-get install -y expect telnet
- name: Build packaging
run: mvn -V -ntp clean install -P full -DskipTests
- name: Run telnet stop leak test
run: python3 integration-test/telnet-stop-leak/run_telnet_stop_leak_test.py --iterations 10 --warmup 2 --threshold 5 --work-dir integration-test/telnet-stop-leak/work
- name: Upload artifacts on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: telnet-stop-leak-logs
path: integration-test/telnet-stop-leak/work
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,7 @@ pom.xml.versionsBackup
**/cmake-build-debug/**

# VSCode
.vscode/
.vscode/

# integration-test (python/expect)
integration-test/telnet-stop-leak/work*/
40 changes: 40 additions & 0 deletions integration-test/telnet-stop-leak/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# telnet-stop-leak 集成测试

目的:对同一目标 JVM 反复执行 `attach -> telnet 执行多命令 -> stop -> jmap`,检查 `com.taobao.arthas.agent.ArthasClassloader` 实例数是否随轮次增长。

## 依赖

- JDK(需要 `java`、`jmap`)
- `expect`、`telnet`
- Maven(用于构建 `packaging/target/arthas-bin`)

## 本地运行

1. 构建打包产物:

```bash
mvn -V -ntp -pl packaging -am package -DskipTests
```

2. 运行测试(默认会创建临时目录保存日志;建议指定 `--work-dir` 便于排查):

`threshold` 可以考虑设置更高,JVM不能保证 ArthasClassLoader 必定会被回收。

```bash
python3 integration-test/telnet-stop-leak/run_telnet_stop_leak_test.py \
--iterations 10 \
--warmup 2 \
--threshold 3 \
--work-dir integration-test/telnet-stop-leak/work
```

输出目录里会生成:

- `results.csv`:每轮统计的 `ArthasClassloader` 实例数
- `logs/`:目标 JVM、attach、telnet transcript、jmap 错误输出

## 调整覆盖面

- 命令集合:`integration-test/telnet-stop-leak/commands.txt`
- telnet 执行逻辑:`integration-test/telnet-stop-leak/arthas_telnet.exp`

96 changes: 96 additions & 0 deletions integration-test/telnet-stop-leak/arthas_telnet.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#!/usr/bin/env expect -f

# 用法:
# arthas_telnet.exp <host> <port> <commands_file> <timeout_seconds> <transcript_file>
#
# 说明:
# - 通过 telnet 连接 Arthas,按行执行 commands_file 里的命令,最后执行 stop 并等待连接关闭。
# - 为避免 CI 卡死,每条命令都设置超时;超时会尝试发送 Ctrl+C 进行中断并继续。

proc usage {} {
puts stderr "usage: arthas_telnet.exp <host> <port> <commands_file> <timeout_seconds> <transcript_file>"
exit 1
}

if {[llength $argv] < 5} {
usage
}

set host [lindex $argv 0]
set port [lindex $argv 1]
set commands_file [lindex $argv 2]
set timeout_seconds [lindex $argv 3]
set transcript_file [lindex $argv 4]

log_file -noappend $transcript_file
set timeout $timeout_seconds

spawn telnet $host $port

# Arthas 默认 prompt 为 "$ "(可能带 ANSI 颜色),匹配子串即可。
set prompt_re {\$ }

expect {
-re $prompt_re {}
timeout {
puts stderr "ERROR: 等待 Arthas prompt 超时"
exit 2
}
eof {
puts stderr "ERROR: 未出现 prompt 连接已关闭"
exit 3
}
}

set fp [open $commands_file r]
while {[gets $fp line] >= 0} {
set line [string trim $line]
if {$line eq ""} { continue }
if {[string match "#*" $line]} { continue }

send -- "$line\r"

expect {
-re $prompt_re {}
-re {Session has been terminated} {
close $fp
exit 0
}
timeout {
# 命令可能是持续输出/等待触发,尝试 Ctrl+C 打断后继续。
send -- "\003"
expect {
-re $prompt_re {}
timeout {
puts stderr "ERROR: 命令超时且 Ctrl+C 未恢复到 prompt: $line"
close $fp
exit 4
}
eof {
puts stderr "ERROR: Ctrl+C 后连接关闭: $line"
close $fp
exit 5
}
}
}
eof {
puts stderr "ERROR: 命令执行后连接关闭: $line"
close $fp
exit 6
}
}
}
close $fp

send -- "stop\r"
expect {
-re {Session has been terminated} {}
eof {}
timeout {
puts stderr "ERROR: stop 超时"
exit 7
}
}

exit 0

23 changes: 23 additions & 0 deletions integration-test/telnet-stop-leak/commands.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# 这些命令用于覆盖常见路径(查询类命令 + 触发增强命令),最后由 expect 脚本统一执行 stop。
help
version
session
dashboard -n 1
thread -n 3
sc -d demo.MathGame
sm demo.MathGame
jad demo.MathGame
watch demo.MathGame primeFactors "{params,returnObj,throwExp}" -n 1 -x 1
# trace 命令:追踪方法调用路径及耗时
trace demo.MathGame run -n 1
trace demo.MathGame primeFactors '#cost>0' -n 1
# ognl 命令:执行 OGNL 表达式
ognl '@java.lang.System@getProperty("java.version")'
ognl '@java.lang.Runtime@getRuntime().availableProcessors()'
ognl -x 2 '@java.lang.System@getProperties()'
# vmtool 命令:JVM 工具
vmtool --action getInstances --className demo.MathGame --limit 5
vmtool --action getInstances --className demo.MathGame --express 'instances.length'
vmtool --action forceGc
reset

Loading
Loading