每次我在Java中初始化一个列表时,我都会这样做:
List<Integer> list = new LinkedList<>();
我认为这将在堆上分配列表。不知道有没有办法在栈上分配列表?
每次我在Java中初始化一个列表时,我都会这样做:
List<Integer> list = new LinkedList<>();
我认为这将在堆上分配列表。不知道有没有办法在栈上分配列表?
所有对象,包括它们各自的属性,都存储在堆上。
所有本地变量及其参数都存储在栈上,因为它们包含原始值或引用。
然而,在特殊情况下,Java虚拟机可能执行逃逸分析并决定在堆栈上分配对象(包括您的LinkedList
),但这通常不会发生,也不是一个主要问题。
作为一般规则,如果您在堆栈上分配对象,则在调用引用该对象的函数时,将获得该对象的副本。相反,如果您在堆上分配对象,则在传递指向对象的指针时,将获得指针的副本(该指针指向完全相同的堆上的对象)。
理论上,JVM实现可以使用“逃逸分析”在堆栈上分配对象。如果可以确定对创建的对象的引用永远不会泄漏到堆之外,则JVM可以将其分配到堆栈上而不是堆上。这样做的好处是减少垃圾回收开销;当退出堆栈帧时,该内存可以立即被回收。它还可能提高速度,因为引用位置的局部性。
从Java 7开始,在Oracle的HotSpot Java运行时中引入了逃逸分析。通过此增强版本,HotSpot可能选择不分配未修改的堆栈本地对象;而不是将它们分配到堆栈上,它直接删除了分配。虽然这没有完全实现堆栈分配,但它表明这样的事情是可行的运行时优化。
然而,Java程序员没有办法直接控制这种行为。这是JIT编译器执行的优化。我不确定语言规范是否允许在编译时进行这种优化。它可能允许,但我没有研究过。
list
在栈上,但这是一个引用,实际的对象(或对象们)在堆上。 - Peter Lawrey