Java 调用堆栈检查和操作

2022-09-03 16:05:49

我的问题是:是否有可能(以任何方式)在运行时分析和修改调用堆栈(帧内容和堆栈内容)?

我正在寻找任何可能性 - 低级,不安全或内部API,编写C扩展的可能性等。唯一的约束:它应该在标准运行时中可用,无需调试或分析模式。这就是我做研究“有可能吗?”,而不是“这是个好主意吗?”。

我想从一个帧中收集所有本地数据,将其存储在某个位置,然后从堆栈中删除该帧,以便以后可以恢复它。实际上,这为我们提供了JVM的延续,它们将允许快速异步框架(如python中的gevents)和生成器结构(如python中的那些)出现。

这可能看起来像重复的问题,但我只找到了用“使用”或“应该用调试工具完成”来回答的问题。有与我类似的问题,但它只在询问者想要做什么(在异步计算上工作)的背景下得到回答,而我需要更一般的(面向java堆栈)的答案。这个问题也类似,但和以前一样,它专注于并行化,答案也集中在并行化上。Thread.currentThread().getStackTrace()

我再说一遍:这是提出新语言功能提案的研究步骤。我不想冒险破坏JVM中的任何东西 - 我正在寻找可能性,然后我将分析可能的风险并寻找它们。我知道手工操纵堆栈是丑陋的,但是创建省略的conrtuctor的实例也是如此 - 它是淫秽的基础。肮脏的黑客可能是肮脏的,但它们可能有助于引入一些很酷的东西。

PS.我知道类星体光狼存在,但是,如上所述,这些都是以并发为中心的框架。

编辑

小小的澄清:我正在寻找与未来的JVM和库版本兼容的东西。最好我们谈论的是被认为是稳定的公共API的东西,但是如果解决方案在于内部的东西,但几乎是标准的,或者在内部之后成为标准(如sun.misc.Unsafe) - 那也会这样做。如果只能通过仅使用C JVM API的C扩展来实现 - 那没关系。如果这可以通过字节码操作来实现 - 那也没关系(我认为ASM可能是可能的)。


答案 1

我认为有一种方法可以使用JVMTI实现您想要的目标。

虽然您不能直接执行所需的操作(如上面的注释中所述),但您可以在运行时检测/重新定义方法(或整个类)。因此,您可以定义每个方法以直接调用另一个方法来“恢复执行上下文”,并且一旦拥有所需的堆栈,就使用原始代码重新定义它们。

例如:假设您要恢复一个堆栈,其中只有A调用B,B调用C。加载 A 时,将代码更改为直接调用 B。加载 B 后,重新定义它以直接调用 C;调用最顶层方法 (A);一旦C被调用(现在应该非常快),将A和B重新定义为它们的原始代码。

如果涉及多个线程并且必须恢复参数值,则会变得有点复杂,但使用JVMTI仍然可以实现。但是,这将值得另一个问题;-)。

希望这有帮助。如果您需要澄清任何事情,请随时与我联系或发表评论。

编辑:虽然我认为这是可行的,但我也认为这是很多(!!!)的工作,特别是当你想恢复参数,局部变量和调用上下文(比如这个指针,持有的锁,...)时。

按要求编辑:假设与上面相同的堆栈(A 调用 B 调用 C)。尽管 A、B 和 C 内部有任意代码,但只需像这样对它们进行重新定义:

void A() { B(); } void B() { C(); } void C() { redefine(); }

到达重定义方法后,立即使用其原始代码重新定义所有类。然后你有你想要的堆栈。


答案 2

不确定此工具,但您可以检查 http://en.wikipedia.org/wiki/GNU_Debugger

GDB为跟踪和更改计算机程序的执行提供了广泛的工具。用户可以监视和修改程序内部变量的值,甚至可以独立于程序的正常行为调用函数。


推荐