每个线程都有堆栈空间吗?

如果我理解正确,那么堆栈是针对本地原始的,并且是对堆中对象的引用。 那么如果你有多个线程会发生什么?

它们是否同时共享相同的堆栈空间(但不同的区域),或者JRE切换上下文并在线程之间切换时加载 – 卸载堆栈内容?

或者JRE是否为每个线程分配单独的堆栈?

或者JRE是否为每个线程分配单独的堆栈?

概念上是的。 (例如,请参阅此JVM规范链接 。)

如何在特定的JVM中实现规范的概念化是……特定于实现的。 但是,我的理解是当前生成(例如Hotspot)JVM将每个线程堆栈分配到从OS请求的单独的内存块中; 例如,使用mmap系统调用1

当发生线程切换时,肯定没有批量复制堆栈内容。 但是,线程上下文切换确实需要保存和加载寄存器,并且(间接地)对内存高速缓存和TLB条目进行额外加载。 这可能很重要……这就是为什么过多的线程上下文切换(例如由锁争用或过度等待/通知引起)可能对性能不利。


1 – 我的回忆是,一些JVM在每个堆栈段的末尾都包含一个只读的“红区”页面。 (这意味着线程堆栈溢出会触发内存错误,并且JVM不需要在每次方法调用时显式检查堆栈溢出,这将是一次重大的性能损失。)无论如何,我的理解是“红区” “页面需要使用mmap请求线程堆栈。

或者JRE是否为每个线程分配单独的堆栈?

是。 指定JVM是这样做的 :

每个Java虚拟机线程都有一个私有Java虚拟机堆栈 ,与线程同时创建。 Java虚拟机堆栈存储帧。 […]因为除了推送和弹出帧之外,永远不会直接操作Java虚拟机堆栈,因此帧可能是堆分配的。

每个线程都有自己的堆栈,为每个在该线程上执行的方法保存一个框架,如“Per Thread”部分所示。

Java线程由线程对象表示,每个线程被分配一个单独的线程堆栈,用于存储运行时数据。 线程堆栈具有特定大小(可以使用VM选项java -Xss1m Application进行设置)。

如果在运行时期间,线程尝试存储的日期多于堆栈大小允许的日期,则会发生堆栈溢出错误。