【问题标题】:Is it possible to force JVM to create an object in stack other than heap?是否可以强制 JVM 在堆栈以外的堆栈中创建对象?
【发布时间】:2014-10-23 01:56:19
【问题描述】:

我读到一些地方,有时 JVM 会识别一些对象并尝试在堆栈中创建它而不是在堆中创建它,因为堆栈上的内存分配比堆中的内存分配便宜,堆栈上的释放是空闲的,堆栈是由运行时有效地管理。 那么堆栈中的这种对象分配是如何工作的,有没有办法强制 JVM 这样做?

【问题讨论】:

  • 没有人无法控制 JVM 的 oplects 放置策略。无法将持久性数据放入堆栈,因为堆栈上的数据将在某些类执行后释放。
  • 请注意,即使最终发生堆栈分配,它也只会对检测为“热”且值得 JIT 编译的代码路径执行此操作。
  • 当人们使用诸如 Java 之类的 VM 平台时,它总是让我感到困惑,它非常小心地向您隐藏这些低级细节,这样您就可以专注于重要的事情(应用程序),然后他们想要无论如何都要关心这些细节。如果您想要控制,请不要使用基于 VM 的高级平台,例如 Java。

标签: java jvm heap-memory stack-memory


【解决方案1】:

没有办法强制 JVM 在任何地方分配对象。您不应该关心 Java 实际分配对象的位置,因为规范中没有定义它。话虽如此,JVM 变得更加智能,并使用了一种称为escape analysis 的技术 如果它愿意,它可以在堆栈上分配一个对象。然而,没有办法强制 JVM 在特定位置分配对象,并且规范并不要求发生这种行为。

【讨论】:

    【解决方案2】:

    如果谈论 HotSpot JVM,它永远不会在堆栈上分配 Java 对象。但是有一个优化:当 Escape Analysis 可以证明对象引用没有超出正在编译的范围时,JIT 完全消除了分配并用局部变量替换了对象字段。

    注意:我们不能在堆栈上声明这是一个分配,因为该对象不存在,例如无法调用 hashCodewait 等 Object 的方法。

    只要 JVM 可以消除分配,它就会自动消除。
    如果它不能 - 没有办法强迫它。

    【讨论】:

    • 您的注释是错误的:我们很可能在 Object 上调用 hashCode,甚至调用 wait,这不会对 Escape Analysis 产生影响,因为 EA 需要确定 无论如何 在堆栈分配中规则的确切对象类型。当你知道确切的对象类型时,你可以内联它的所有方法调用,当你这样做时,你可以让它们的实现引用堆栈位置。
    • 顺便说一句,非转义对象上的wait(timeout)可以实现为简单的sleep(timeout);对于无参数wait() 调用---无限阻塞也可以做类似的事情。
    • @MarkoTopolnik 您的理论假设是正确的,但我现在谈论的是具体实现,即 HotSpot JVM。好吧,抽象的JVM可以在任何地方以任何方式分配对象,但是如果引用了对象头,HotSpot不会消除分配。
    • 那么锁省略呢?如果省略了锁定,则在调用 wait() 时不会引用标头。我想当您将wait 应用于当前版本的HotSpot 时,您的观点会更加微妙。无论哪种方式,这都不适用于在覆盖默认 hashCode() 的对象上调用 hashCode()
    • @MarkoTopolnik 是的,如果 hashCode 被覆盖,对象仍可被消除。对非转义对象的锁定也是如此。我的观点是 “堆栈分配” 不是正确的术语,因为没有实际的“分配”,而是用局部变量替换字段。 IE。这些变量需要进一步优化:它们可以保存在寄存器中,甚至可以折叠为常量。我们同样可以将其命名为“寄存器内分配”:)
    猜你喜欢
    • 2019-09-22
    • 2023-03-18
    • 2021-08-01
    • 2017-06-21
    • 2010-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多