V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Zzhiter
V2EX  ›  Java

关于 Java 的如何进行单体应用 tracing 的问题

  •  
  •   Zzhiter · 215 天前 · 2169 次点击
    这是一个创建于 215 天前的主题,其中的信息可能已经有所发展或是发生改变。

    各位大佬好,我现在有一个需求:

    启动一个程序 A 一直执行单测 B ,对于每次测试 C ,需要获取到 C 当次测试用例的执行路径信息: 即调用点在哪里,依次经过了哪些函数,最后在哪里终止(终止点某个函数的某一行)

    程序的执行过程是一个不断压栈弹栈的过程,想要获取完整的执行路径,只有最后的栈快照是不行的。 目前想到的方法是这样的:

    在每个方法的第一行插入一段代码,这段代码可以完成以下功能: 调用 A 程序中的静态方法,把自己的函数名称传递给 A 。

    在 A 程序中维护一个 C 的执行路径序列,这样在 C 运行结束的时候,就可以获取到 C 执行了哪些函数。具体在某一行截至这个还没考虑。

    不知道自己考虑的对不对,或者大家还有没有什么更好的方案,希望可以多多交流

    22 条回复    2024-04-07 16:06:03 +08:00
    foolishcrab
        1
    foolishcrab  
       215 天前 via iPhone
    写过几乎一模一样的代码,基于 agent 的字节码修改,逻辑跟你描述的差不多,是可以实现的
    iseki
        2
    iseki  
       215 天前
    主要还是得考虑跨线程时怎么处理
    Zzhiter
        3
    Zzhiter  
    OP
       215 天前   ❤️ 1
    @iseki 对的,这个是比较难的一个点
    Zzhiter
        4
    Zzhiter  
    OP
       215 天前
    @foolishcrab 好的,谢谢大佬
    Mmahaha
        5
    Mmahaha  
       215 天前
    前段时间也在研究这个,方法和 1L 说的一样,用的是 javaassist
    Zzhiter
        6
    Zzhiter  
    OP
       215 天前
    @Mmahaha 对,我现在了解到有 ASM ,javassist ,bytebuddy ,还在想具体用哪一个
    Ayanokouji
        7
    Ayanokouji  
       215 天前
    如果只是调试,arthas 应该可以吧
    Zzhiter
        8
    Zzhiter  
    OP
       215 天前
    @Ayanokouji 嗯嗯,关键在于想把整个流程自动化,如果要是 arthas 有 api 就好了😂😂
    winv87
        9
    winv87  
       215 天前   ❤️ 1
    几年前看过 jvm sandbox ,Arthas 相当于成品,看看这个试试呢
    Ayanokouji
        10
    Ayanokouji  
       215 天前
    @winv87 arthas 有 api 的,但是不清楚满不满足你的需求
    Zzhiter
        11
    Zzhiter  
    OP
       215 天前
    @Ayanokouji 感谢!我去看一下
    mpi2018
        12
    mpi2018  
       215 天前
    wolfie
        13
    wolfie  
       215 天前   ❤️ 1
    感觉实现原理不是很难,需要增强全部 class ,skywalking 就在启动时指定 javaagent 并用 bytebuddy 增强的。

    https://github.com/apache/skywalking
    dyv9
        14
    dyv9  
       214 天前 via Android
    以前为了测试公司自研的框架事务不能回滚错在回哪里,俺用 AspectJ 读取 ejb-jar.xml / web.xml 里面的事务相关设置,用 AspectJ 把涉及到事务边界的地方拿来记录事件,在事务上下文切换时要检测在这事务边界内使用的 JDBC 连接等资源当前应该是绑定到哪个事务,为什么作为参数传递下去会越界,检测到 把一个在事务 A 中打开的连接传参到事务 B 中导致的事务不一致。这些类似的东西只能是操作字节码自动插入代码,用 AspectJ 静态编织很方便。
    Aresxue
        15
    Aresxue  
       213 天前   ❤️ 1
    这不就是 arthas 的 trace 嘛,直接搞过来。pinpoint 、jvm sandbox 等也可以抄一抄。
    xhd2015
        16
    xhd2015  
       208 天前 via iPhone
    这个在 go 中已经实现了,原理是代码重写。java 应该更容易,参考这个例子: https://github.com/xhd2015/xgo/blob/master/cmd/xgo/trace/testdata/stack_trace.jpg

    这是一个完整的调用堆栈
    Zzhiter
        17
    Zzhiter  
    OP
       208 天前
    @xhd2015 太厉害了,我学习一下,楼主竟然还是工大学长
    xhd2015
        18
    xhd2015  
       208 天前 via iPhone
    巧了。你的关于插入代码想法是正确的
    Zzhiter
        19
    Zzhiter  
    OP
       208 天前
    @xhd2015 我现在在想的问题是,A 中调用了很多次的 B ,比如 B 在一个循环中的话,B 是存几次,存一次感觉有点不精确,存多次好像又不太合理
    xhd2015
        20
    xhd2015  
       208 天前 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
    xhd2015
        21
    xhd2015  
       207 天前 via iPhone
    go 的原理可以参考我之前写的一篇文章: https://blog.xhd2015.xyz/zh/posts/xgo-monkey-patching-in-go-using-toolexec/
    Zzhiter
        22
    Zzhiter  
    OP
       207 天前
    @xhd2015 收到,感谢感谢!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1199 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 23:04 · PVG 07:04 · LAX 16:04 · JFK 19:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.