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

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

我想从一个框架中收集所有本地数据,将其存储在某个地方,然后从堆栈中删除该框架,并可能在以后进行恢复。有效地使我们可以继续使用JVM,它们将允许出现快速异步框架(例如python中的gevent)和生成器构造(例如python中的gevent)。

这可能看起来像是重复的问题,但我只发现了用“use Thread.currentThread().getStackTrace()”或“应使用调试工具完成的问题”回答的问题。有similiar question to mine,但仅在询问者想做什么的背景下回答(异步计算工作),而我需要更通用的(面向Java堆栈的)回答。 This question也很相似,但是像以前一样,它专注于并行化,而答案也专注于并行化。

我再说一遍:这是提出新语言功能建议的研究步骤。我不想冒险破坏JVM中的任何内容-我在寻找可能性,然后我将分析可能的风险并寻找它们。我知道手工操作堆栈很丑陋,但是创建带有遗漏容器的实例也很麻烦-这是目标的基础。肮脏的骇客可能很脏,但它们可能有助于引入一些很棒的东西。

PS。我知道QuasarLightwolf存在,但是如上所述,它们是关注于并发的框架。

编辑

无需多说:我正在寻找与将来的JVM和库版本兼容的东西。最好是我们谈论的是被认为是稳定的公共(public)API的东西,但是如果解决方案位于内部但几乎是标准的东西或在内部之后成为标准的东西(例如sun.misc.Unsafe),那么它也会这样做。如果通过仅使用C JVM API的C-扩展即可实现-可以。如果可以通过字节码操作做到这一点-也可以(我认为ASM可以实现)。

最佳答案

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

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

例如:假设您要还原仅A称为B且B称为C的堆栈。
加载A后,将代码更改为直接调用B。加载B后,立即将其重新定义为直接调用C;否则,将其重新定义为直接调用C。调用最顶层的方法(A);一旦调用C(现在应该很快),就将A和B重新定义为其原始代码。

如果涉及多个线程并且必须还原参数值,则它会变得稍微复杂一些,但仍可使用JVMTI来实现。但是,这将值得另一个问题;-)。

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

编辑:
尽管我认为这是可行的,但我也认为这是很多工作(!!!),尤其是当您要还原参数,局部变量和调用上下文(如指针,持有的锁等)时。

根据要求进行编辑:假定与上述相同(A调用B调用C)。尽管A,B和C内有任意代码,但可以像这样重新定义它们:void A(){B(); } void B(){C(); } void C(){redefine(); }一旦到达redefine方法,请使用其原始代码重新定义所有类。这样便有了所需的堆栈。

07-24 09:39
查看更多