Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/333.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 JVM:可以操纵帧堆栈吗?_Java_Jvm_Quasar - Fatal编程技术网

Java JVM:可以操纵帧堆栈吗?

Java JVM:可以操纵帧堆栈吗?,java,jvm,quasar,Java,Jvm,Quasar,假设我需要在同一个线程中执行N个任务。这些任务有时可能需要外部存储器中的一些值。我事先不知道哪项任务可能需要这样一个值,何时需要。一次获取M个值要比在M个查询中将相同的M个值获取到外部存储器快得多 请注意,我不能期望任务本身的合作,它们只能被简化为java.lang.Runnable对象 在我看来,理想的程序应该是 在循环中执行所有任务。如果任务请求外部值,请记住这一点,挂起该任务并切换到下一个任务 一次获取上一步请求的值 删除所有已完成的任务(挂起的任务不算已完成) 如果仍有任务,请转至步骤1

假设我需要在同一个线程中执行N个任务。这些任务有时可能需要外部存储器中的一些值。我事先不知道哪项任务可能需要这样一个值,何时需要。一次获取M个值要比在M个查询中将相同的M个值获取到外部存储器快得多

请注意,我不能期望任务本身的合作,它们只能被简化为java.lang.Runnable对象

在我看来,理想的程序应该是

  • 在循环中执行所有任务。如果任务请求外部值,请记住这一点,挂起该任务并切换到下一个任务
  • 一次获取上一步请求的值
  • 删除所有已完成的任务(挂起的任务不算已完成)
  • 如果仍有任务,请转至步骤1,但不要执行任务,而是从挂起状态继续执行任务
  • 据我所见,“挂起”和“恢复”某些内容的唯一方法是从JVM堆栈中删除其相关帧,将它们存储在某个位置,然后将它们推回到堆栈上,让JVM继续

    是否有任何标准(不涉及比JVM字节码更低级别的黑客攻击)方法可以做到这一点?


    或者,您可以建议另一种可能的方法来实现这一点(除了启动N个线程或使任务以某种方式协作之外)?

    可以使用类似于通过代理进行堆栈切片的方法。来自任务的某种程度的合作是有帮助的,但是可以使用AOP从外部插入暂停点


    (在我看来,最好明确说明正在发生的事情(例如使用
    Future
    ForkJoinPool
    )。如果一些普通代码在一个线程上运行了一段时间,然后“神奇地”挂起并跳转到另一个线程,这可能会使调试或推理非常混乱。对于现代语言和库,明确异步边界的开销应该不会太大。如果您的任务是按照泛型类型编写的,那么很容易通过scalaz
    Future之类的程序。但这不能满足您给定的要求。

    您可以试试这个

    你需要

  • 保存任务当前状态的机制,因为当任务返回其帧时,将从调用堆栈中弹出。根据返回值或类似的内容,您可以确定它是否完成,因为您需要从它离开的位置重新执行它,因此您需要保留状态信息

  • 为每个任务创建一个请求数据结构。当一个任务想要请求它记录在那里的东西时,数据结构应该支持一个任务可以发出的所有可能的请求

  • 将这些DS存储在地图中。在循环结束时,您可以查询此DS以确定每个任务所需的资源类型

  • 获取资源并将其放入DS中。从任务返回时的状态启动任务

  • 任务查询DS以获取资源

  • 当任务希望使用外部资源时,应使用此DS

  • 您需要特别考虑设计请求资源的方法,因为当您再次重新执行任务时,您需要自己调用此方法,以便任务可以从它离开的地方执行

    *DS->数据结构


    希望能有所帮助。

    如前所述,它使用字节码转换实现了这一点(它通常在M个线程上调度N个光纤,但您可以将M设置为1)。它甚至为每个任务(也称为“光纤”)提供了自己的堆栈跟踪,因此您可以转储它并获得完整的堆栈跟踪,而不会受到共享线程的任何其他任务的干扰。

    谢谢,我一定会看这个。看起来它需要Java 7。我们的项目目前使用6,所以我将推迟到以后。不幸的是,这似乎不满足我的约束条件,因为我基本上需要将每个可能被挂起的方法及其调用方标记为抛出异常或带有注释。您看到“自动插装”部分了吗?这听起来像是通过使用AOP(虽然它被标记为实验性的)来解决的。是的,但这意味着一半的程序可能会被检测,假设实验性的特性甚至不会出错。在我的例子中,我使用光纤不是为了并行性,而是为了能够暂停并在以后恢复。这里的任务可以是任何东西,包括跨越数百个方法和多个类的大型任务。