各位大佬好,我现在有一个需求:
启动一个程序 A 一直执行单测 B ,对于每次测试 C ,需要获取到 C 当次测试用例的执行路径信息: 即调用点在哪里,依次经过了哪些函数,最后在哪里终止(终止点某个函数的某一行)
程序的执行过程是一个不断压栈弹栈的过程,想要获取完整的执行路径,只有最后的栈快照是不行的。 目前想到的方法是这样的:
在每个方法的第一行插入一段代码,这段代码可以完成以下功能: 调用 A 程序中的静态方法,把自己的函数名称传递给 A 。
在 A 程序中维护一个 C 的执行路径序列,这样在 C 运行结束的时候,就可以获取到 C 执行了哪些函数。具体在某一行截至这个还没考虑。
不知道自己考虑的对不对,或者大家还有没有什么更好的方案,希望可以多多交流
1
foolishcrab 239 天前 via iPhone
写过几乎一模一样的代码,基于 agent 的字节码修改,逻辑跟你描述的差不多,是可以实现的
|
2
iseki 239 天前
主要还是得考虑跨线程时怎么处理
|
4
Zzhiter OP @foolishcrab 好的,谢谢大佬
|
5
Mmahaha 239 天前
前段时间也在研究这个,方法和 1L 说的一样,用的是 javaassist
|
7
Ayanokouji 239 天前
如果只是调试,arthas 应该可以吧
|
8
Zzhiter OP @Ayanokouji 嗯嗯,关键在于想把整个流程自动化,如果要是 arthas 有 api 就好了😂😂
|
9
winv87 239 天前 1
几年前看过 jvm sandbox ,Arthas 相当于成品,看看这个试试呢
|
10
Ayanokouji 239 天前
@winv87 arthas 有 api 的,但是不清楚满不满足你的需求
|
11
Zzhiter OP @Ayanokouji 感谢!我去看一下
|
12
mpi2018 239 天前
pinpoint 可以看一下 https://github.com/pinpoint-apm/pinpoint
|
13
wolfie 239 天前 1
感觉实现原理不是很难,需要增强全部 class ,skywalking 就在启动时指定 javaagent 并用 bytebuddy 增强的。
https://github.com/apache/skywalking |
14
dyv9 238 天前 via Android
以前为了测试公司自研的框架事务不能回滚错在回哪里,俺用 AspectJ 读取 ejb-jar.xml / web.xml 里面的事务相关设置,用 AspectJ 把涉及到事务边界的地方拿来记录事件,在事务上下文切换时要检测在这事务边界内使用的 JDBC 连接等资源当前应该是绑定到哪个事务,为什么作为参数传递下去会越界,检测到 把一个在事务 A 中打开的连接传参到事务 B 中导致的事务不一致。这些类似的东西只能是操作字节码自动插入代码,用 AspectJ 静态编织很方便。
|
15
Aresxue 237 天前 1
这不就是 arthas 的 trace 嘛,直接搞过来。pinpoint 、jvm sandbox 等也可以抄一抄。
|
16
xhd2015 232 天前 via iPhone
这个在 go 中已经实现了,原理是代码重写。java 应该更容易,参考这个例子: https://github.com/xhd2015/xgo/blob/master/cmd/xgo/trace/testdata/stack_trace.jpg
这是一个完整的调用堆栈 |
18
xhd2015 232 天前 via iPhone
巧了。你的关于插入代码想法是正确的
|
20
xhd2015 232 天前 via iPhone 1
@Zzhiter 存多次,存在数组中。其实调用栈就是一棵树,每次调用都是产生一个子结点。存储结构:
StactTrace{ ClassName string Method string Request Object Response Object Children StackTrace[] } 可以参考这个定义: https://github.com/xhd2015/xgo/blob/1211c519c8005ddbd66189cf64e958aa69e5789f/runtime/trace/stack.go#L16 |
21
xhd2015 231 天前 via iPhone
go 的原理可以参考我之前写的一篇文章: https://blog.xhd2015.xyz/zh/posts/xgo-monkey-patching-in-go-using-toolexec/
|