在java中的堆栈内存上创建对象?

Posted

技术标签:

【中文标题】在java中的堆栈内存上创建对象?【英文标题】:Creating Objects on the stack memory in java ? 【发布时间】:2014-11-12 05:49:00 【问题描述】:

出于好奇,这只是一个简单的理论问题。我一直像个java迷。但有一件事让我想知道为什么 java 不提供在堆栈上创建对象的机制?如果我可以只在堆栈上创建小的 Point(int x,int y) 对象而不是像在 C# 上创建结构那样在堆上创建对象,那不是更有效吗? java中的这个限制背后有什么特殊的安全原因吗? :)

【问题讨论】:

将其放入不在堆栈中的容器中会发生什么?当您返回时,容器现在具有对已释放内存的引用。 @Max:大概,该语言还需要包含允许编译器对此进行检查的结构。 @Max:容器没有对原始的引用,它要么有它的副本,要么有它的盒装副本。 .NET/C# 在过去的 15 年里已经有了这个。 msdn.microsoft.com/en-us/library/yz2be5wk.aspx 【参考方案1】:

这里的策略是,Java 不会将此决定泄漏到语言中,而是让 JVM/Hotspot/JIT/运行时决定它要在哪里以及如何分配内存。

正在进行的研究使用“转义分析”来找出哪些对象实际上不需要进入堆并改为堆栈分配它们。我不确定这是否已经成为主流 JVM。但如果是这样,它将由运行时控制(thing -XX:something),而不是开发人员。

这样做的好处是,即使是旧代码也可以从这些未来的增强功能中受益,而无需对其自身进行更新。

如果您喜欢手动管理它(但仍然让编译器检查它是否保持“安全”),请查看 Rust。

【讨论】:

docs.oracle.com/javase/7/docs/technotes/guides/vm/… 在 6u23 及更高版本中启用 @jtahlborn:+1。不过,我认为当前的优化并没有达到实际在堆栈上分配对象的程度。从发行说明来看,这听起来像是消除了现有对象的锁和冗余副本。 +1 来自 jtahlborn 发布的链接:“它不会将堆分配替换为非全局转义对象的堆栈分配。”这意味着 ArgEscapeNoEscape 将在堆栈上分配。但话又说回来,它没有被明确提及...... @alfasin:是的,不太清楚。我将其读作“用完全没有分配的冗余防御副本替换堆分配”(改为重新使用现有对象),这似乎在他们给出的示例中发生了。 如何确保我的对象通过堆栈传递?应用了哪些规则?【参考方案2】:

这将暂时出现在 Java 中,没有为此设置真正的 ETA,所以你只能希望它会在 Java 10 中出现。

该提案称为值类型,您可以关注它in the mailing list of Project Valhalla。

我不知道是否有任何先前的原因说明为什么它最初没有出现在语言中,也许最初它被认为是不需要的,或者根本没有时间来实现它。

【讨论】:

好的! Java 会“暂时”赶上 C#? “有时”(tm) @skiwi 你能简单解释一下什么是值类型吗?【参考方案3】:

一个常见的问题是使用在堆栈上创建的对象来初始化一些全局引用。当创建对象的方法退出时你指向什么?

据说对象是在 Java 中的堆栈上创建的,它只是在您背后使用 escape analysis 完成,这样可以确保不会发生上述情况。

【讨论】:

以上是关于在java中的堆栈内存上创建对象?的主要内容,如果未能解决你的问题,请参考以下文章

Java 堆栈内存分配

Java 堆栈内存分配

Java堆栈的区别

为啥堆栈内存大小如此有限?

堆栈Java堆和栈的区别

java中的堆栈