Java可以在堆栈上分配列表吗?
Posted
技术标签:
【中文标题】Java可以在堆栈上分配列表吗?【英文标题】:Can Java allocate a list on stack? 【发布时间】:2014-06-10 00:20:10 【问题描述】:每当我在java中启动一个列表时,我都会这样做
List<Integer> list = new LinkedList<>();
我假设这将在堆上分配列表。想知道我是否可以在堆栈上分配列表?
【问题讨论】:
为什么要在栈上分配? 这纯粹是学术性的吗? @LuiggiMendoza PermGen 不是堆栈内存。它是为 JVM 进程的其余部分分配预期存在的类和其他结构的地方;将这些移动到单独的空间使常规堆中的垃圾收集更加有效。随着类卸载变得越来越常规,这种效率提升变得不那么明显了。list
在堆栈上,但这是一个引用,实际对象在堆上。
@PeterLawrey 但前提是它是局部变量。如果它是一个成员变量,它也会在堆上。
【参考方案1】:
所有对象,包括它们各自的属性,都存储在堆上。
所有局部变量及其参数都存储在堆栈中,因为它们包含原始值或引用。
但是,在特殊情况下,java 虚拟机可能会执行逃逸分析并决定在堆栈上分配对象(包括您的 LinkedList
),但这通常不会发生,也不是主要问题。
一般来说,如果你在堆栈上分配一个对象,当你调用一个引用它的函数时,你会得到一个对象的副本。相反,如果您在堆上分配一个对象,当您将指针传递给该对象时,您将获得指针的副本(它指向堆上的同一个对象。)
【讨论】:
那么C++呢?似乎 C++ 可以通过执行“list理论上,JVM 实现可以使用“逃逸分析”在堆栈上分配对象。如果可以确定对已创建对象的引用永远不会从堆栈中泄漏,则 JVM 可以将其分配在堆栈上而不是堆上。这样做的好处是减少垃圾收集开销;当堆栈帧退出时,可以立即回收该内存。由于参考的局部性,它也可能会提高速度。
从 Java 7 开始,在 Oracle 的 HotSpot Java 运行时中引入了逃逸分析。有了这个增强,HotSpot 可以选择不分配未修改的堆栈本地对象;它不是在堆栈上分配它们,而是完全删除分配。虽然这没有堆栈分配,但它确实证明了这样的事情是允许的运行时优化。
但是,Java 程序员无法直接控制这种行为。这是由 JIT 编译器执行的优化。我不确定语言规范是否允许在编译时进行这种优化。可能有,但我没研究过。
【讨论】:
据我所知EscapeAnalysis出现在Java 6 17版。有detailed investigation of condition以上是关于Java可以在堆栈上分配列表吗?的主要内容,如果未能解决你的问题,请参考以下文章