Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java调用堆栈检查和操作_Java_Jvm_Stack Trace - Fatal编程技术网

Java调用堆栈检查和操作

Java调用堆栈检查和操作,java,jvm,stack-trace,Java,Jvm,Stack Trace,我的问题是:是否可以(以任何方式)在运行时分析和修改调用堆栈(包括帧内容和堆栈内容) 我正在寻找任何可能性——低级的、不安全的或内部的API,编写C扩展的可能性,等等。唯一的限制:它应该在标准运行时可用,无需调试或分析模式。这是我在做研究的重点“可能吗?”,而不是“这是个好主意吗?” 我希望从一个帧中收集所有本地数据,将其存储在某个位置,然后从堆栈中删除该帧,并可能在以后恢复该帧。实际上,这给了我们JVM中的连续性,它们将允许快速异步框架(如python中的gevents)和生成器构造(如pyt

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

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

我希望从一个帧中收集所有本地数据,将其存储在某个位置,然后从堆栈中删除该帧,并可能在以后恢复该帧。实际上,这给了我们JVM中的连续性,它们将允许快速异步框架(如python中的gevents)和生成器构造(如python中的构造)出现

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

我再说一遍:这是提出新的语言特性建议过程中的研究步骤。我不想冒险破坏JVM中的任何东西——我在寻找可能性,然后我将分析可能的风险并注意它们。我知道手工操作堆栈很难看,但使用ommiting constructor创建实例也很难看——这是Objensis的基础。肮脏的黑客可能是肮脏的,但他们可能有助于引入一些很酷的东西

另外,我知道这一点,并且确实存在,但是,如上所述,这些都是以并发为中心的框架

编辑


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

在这个工具中不确定,但您可以检查


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

我认为有一种方法可以使用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();}一旦到达redefine方法,就用它们的原始代码重新定义所有类。然后你就有了你想要的堆栈。

我还没有用过它,但也许你可以用它做点什么。有一些,谢谢!这看起来很有希望,但不幸的是,它只允许弹出帧(甚至不在弹出后提供),并获得一些原始帧信息。这还不足以存储和恢复完整的执行上下文。恐怕您不能使用超过JVMTI允许的堆栈。要做您想要做的事情,需要JVM支持。即使您碰巧使用直接内存访问成功地操纵了堆栈,下一次JVM更新也可能很容易打破这一点。我将对未来的兼容性做一些澄清,以避免评论和回答警告我JVM更新;)尽管如此,也许有人知道一些事情……“为什么决定不允许它”——事实并非如此。双方都没有决定允许这样做。直接操纵堆栈的动机尚不清楚。如果你想在Java中继续,有很多方法可以实现。我知道什么是调试器。我特别指出,我正在寻找一种无需任何特殊模式即可完成此操作的可能性。如果我做对了:您想在类加载时修改方法/类,以使用一些附加代码来完成它吗?这太复杂了,我可以用至少3种不同的方式轻松添加穷人方面。我的问题在于存储和恢复上下文-所有局部变量和参数,指令计数器(“我们在方法体中的位置是什么?”,程序计数器,但对于单线程),等等。不必包装它,只需全新定义它,以重现您想要的堆栈。然后,一旦有了堆栈,就用它们的原始代码重新定义所有方法,并让它们继续。这样,您还可以恢复参数和该指针(通过y的序列化方法)