JVM:可以操纵帧堆栈吗?

时间:2014-12-01 14:51:03

标签: java jvm quasar

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

请注意我不能指望任务本身的合作,它们可以被简称为java.lang.Runnable对象

现在,我认为理想的程序看起来像是

  1. 在循环中执行所有任务。如果某个任务请求外部值,请记住这一点,暂停该任务并切换到下一个任务。
  2. 一次获取上一步所请求的值。
  3. 删除所有已完成的任务(暂停的任务不算完成)。
  4. 如果还有剩下的任务,请转到步骤1,但不是执行任务,而是从暂停状态继续执行
  5. 据我所知,“挂起”和“恢复”的唯一方法是从JVM堆栈中删除相关的帧,将它们存储在某处,然后将它们推回堆栈并让JVM继续。 / p>

    是否有任何标准(不涉及低于JVM字节码的黑客攻击)方式?

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

3 个答案:

答案 0 :(得分:3)

可以使用像quasar之类的东西通过代理进行堆叠切片。任务的某种程度的合作是有帮助的,但是可以使用AOP从外部插入悬挂点。

(IMO最好明确说明发生了什么(使用例如FutureForkJoinPool)。如果某些普通代码在一个线程上运行了一段时间,然后,它被神奇地"暂停并跳转到另一个线程,这对于调试或推理来说可能非常混乱。对于现代语言和库,明确关于异步边界的开销不应该是压倒性的。如果你的任务根据通用类型编写,然后很容易传递像scalaz Future这样的东西。但这不符合你给出的要求。

答案 1 :(得分:1)

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

答案 2 :(得分:-1)

你可以试试这个

你需要

  1. 保存任务当前状态的机制,因为当任务返回其帧时,将从调用堆栈中弹出。基于返回值或类似的东西,您可以确定它已完成或未完成的天气,因为您需要从它离开的位置重新执行它,因此您需要保留状态信息。

  2. 为每项任务创建一个请求数据结构。当一个任务想要请求某事时它会在那里记录它,数据结构应该支持一个任务可以做出的所有请求。

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

  4. 将资源放入DS中。从返回状态开始执行任务。

  5. 任务查询DS获取资源。

  6. 任务在使用外部资源时应使用此DS。

  7. 您需要设计一个特殊考虑请求资源的方法,因为当您再次重新执行任务时,您需要自己调用此方法,以便任务可以从它离开的位置执行。

    * DS - >数据结构

    希望它有所帮助。