Java调用栈检查和操作

Fil*_*zak 16 java jvm stack-trace

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

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

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

这可能看起来像重复的问题,但我只发现了用"使用Thread.currentThread().getStackTrace()"或"应该用调试工具完成"的问题.我有类似的问题,但它只是在询问人们想要做什么(处理异步计算)的背景下回答,而我需要更一般的(面向Java堆栈)答案.这个问题也是类似的,但和以前一样,它专注于并行化,答案也集中于此.

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

PS.我知道QuasarLightwolf存在,但是,如上所述,那些是以并发为中心的框架.

编辑

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

loo*_*une 6

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

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

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

如果涉及多个线程且必须恢复的参数值,它会变得更复杂,但仍然可以使用JVMTI.然而,这将是值得另一个问题;-).

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

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

按要求编辑:假设与上面相同的堆栈(呼叫B呼叫C).虽然A,B和C里面有任意代码,但只需将它们重新定义为:

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

一旦到达redefine方法,请使用原始代码重新定义所有类.然后你有你想要的堆栈.