如果我理解正确,那么堆栈是针对本地原始的,并且是对堆中对象的引用。那么如果你有多个线程会发生什么?
它们是否同时共享相同的堆栈空间(但是区域不同),或者JRE切换上下文并在线程之间切换时加载 - 卸载堆栈内容?
或者JRE是否为每个线程分配了不同的堆栈?
答案 0 :(得分:5)
或者JRE是否为每个线程分配了不同的堆栈?
概念上是的。 (例如,见JVM spec link。)
如何在特定JVM中实现规范的概念化是......特定于实现的。但是,我的理解是当前生成(例如,Hotspot)JVM将每个线程堆栈分配在从OS请求的单独的存储器块中;例如使用{{1}}系统调用 1 。
当发生线程切换时,肯定没有批量复制堆栈内容。但是,线程上下文切换确实需要保存和加载寄存器,并且(间接地)对内存高速缓存和TLB条目进行额外加载。这可能很重要......这就是为什么过多的线程上下文切换(例如由锁争用或过度等待/通知引起)可能对性能不利。
1 - 我的回忆是,有些JVM包含只读"红区"每个堆栈段末尾的页面。 (这意味着线程堆栈溢出会触发内存错误,并且JVM不需要在每次方法调用时显式检查堆栈溢出,这将是一个重大的性能损失。)无论如何,我的理解是&# 34;红色区"页面需要使用mmap请求线程堆栈。功能
答案 1 :(得分:3)
每个线程都有自己的堆栈,为每个在该线程上执行的方法保存一个框架,如“Per Thread”部分所示,您可以看到here。
答案 2 :(得分:3)
或者JRE是否为每个线程分配了不同的堆栈?
是 The JVM is specified to do so:
每个Java虚拟机线程都有一个私有的 Java虚拟机堆栈,与线程同时创建。 Java虚拟机堆栈存储帧。 [...]因为除了推送和弹出帧之外,永远不会直接操作Java虚拟机堆栈,所以帧可能是堆分配的。
答案 3 :(得分:1)
Java线程由线程对象表示,每个线程被分配一个单独的线程堆栈,用于存储运行时数据。线程堆栈具有特定大小(可以使用VM选项java -Xss1m Application
设置)。
如果在运行时期间,线程尝试存储的日期多于堆栈大小允许的日期,则会发生堆栈溢出错误。