Stack/Heap 在 JVM 中
Stack/Heap in JVM
本人来自C/C++背景,其中一个进程内存分为:
- 每个线程堆栈
- 堆
- 说明
- 数据
我试图了解 JVM 的工作原理,我查看了不同的资源,我了解到 JVM 内存也分为堆和栈以及其他一些东西。
我想绕过这个问题,当我阅读 JVM 中的堆和堆栈时,我们在谈论堆栈和堆的概念吗?并且整个 JVM 的实际内存驻留在堆上(这里我指的是堆的 C++ 概念)?
I want to wrap my mind around this, when I read heap and stack in JVM are we talking about concepts of stack and heap?
是的,大体上是这样的。每个线程都有自己的per-thread栈,用于在栈帧中存放局部变量(对应方法调用)。堆栈不需要位于与 OS 级别的每线程堆栈相关的位置。如果堆栈试图增长超过 -Xss
指定的大小或实现设置的默认值,将抛出 WhosebugError
。
堆栈可以存在于C/C++堆内存中,不需要连续(JVM spec v7):
Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread. A Java Virtual Machine stack stores frames (§2.6). A Java Virtual Machine stack is analogous to the stack of a conventional language such as C: it holds local variables and partial results, and plays a part in method invocation and return. Because the Java Virtual Machine stack is never manipulated directly except to push and pop frames, frames may be heap allocated. The memory for a Java Virtual Machine stack does not need to be contiguous.
Java 堆是一种存储对象的方法,包括当无法通过强引用访问对象时自动进行垃圾回收。它在 JVM 上的所有线程 运行 之间共享。
The Java Virtual Machine has a heap that is shared among all Java Virtual Machine threads. The heap is the run-time data area from which memory for all class instances and arrays is allocated.
堆是在虚拟机启动时创建的。对象的堆存储由自动存储管理系统(称为垃圾收集器)回收;对象永远不会显式释放。 Java 虚拟机假设没有特定类型的自动存储管理系统,可以根据实施者的系统要求选择存储管理技术。堆可以是固定大小的,也可以根据计算的需要进行扩展,如果不需要更大的堆,则可以收缩。堆的内存不需要是连续的。
通过简单地调用构造函数(例如 HashMap foo = new HashMap()
),JVM 将在堆上为此对象分配必要的内存(如果不可能,则抛出 OutOfMemoryError)。同样重要的是要注意对象永远不会存在于堆栈中——只有对它们的引用才会存在。此外,非原始字段也始终包含对对象的引用。
也可以通过某些 JVM 上的 sun.misc.Unsafe
、分配直接缓冲区的某些 NIO 类 以及通过使用 JNI 来分配堆外内存。此内存不是 JVM 堆的一部分,也不会进行自动垃圾收集(这意味着它需要通过 delete
等方式释放,但它可能是堆内存的一部分,因为 C++ 可能会引用它。
本人来自C/C++背景,其中一个进程内存分为:
- 每个线程堆栈
- 堆
- 说明
- 数据
我试图了解 JVM 的工作原理,我查看了不同的资源,我了解到 JVM 内存也分为堆和栈以及其他一些东西。
我想绕过这个问题,当我阅读 JVM 中的堆和堆栈时,我们在谈论堆栈和堆的概念吗?并且整个 JVM 的实际内存驻留在堆上(这里我指的是堆的 C++ 概念)?
I want to wrap my mind around this, when I read heap and stack in JVM are we talking about concepts of stack and heap?
是的,大体上是这样的。每个线程都有自己的per-thread栈,用于在栈帧中存放局部变量(对应方法调用)。堆栈不需要位于与 OS 级别的每线程堆栈相关的位置。如果堆栈试图增长超过 -Xss
指定的大小或实现设置的默认值,将抛出 WhosebugError
。
堆栈可以存在于C/C++堆内存中,不需要连续(JVM spec v7):
Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread. A Java Virtual Machine stack stores frames (§2.6). A Java Virtual Machine stack is analogous to the stack of a conventional language such as C: it holds local variables and partial results, and plays a part in method invocation and return. Because the Java Virtual Machine stack is never manipulated directly except to push and pop frames, frames may be heap allocated. The memory for a Java Virtual Machine stack does not need to be contiguous.
Java 堆是一种存储对象的方法,包括当无法通过强引用访问对象时自动进行垃圾回收。它在 JVM 上的所有线程 运行 之间共享。
The Java Virtual Machine has a heap that is shared among all Java Virtual Machine threads. The heap is the run-time data area from which memory for all class instances and arrays is allocated.
堆是在虚拟机启动时创建的。对象的堆存储由自动存储管理系统(称为垃圾收集器)回收;对象永远不会显式释放。 Java 虚拟机假设没有特定类型的自动存储管理系统,可以根据实施者的系统要求选择存储管理技术。堆可以是固定大小的,也可以根据计算的需要进行扩展,如果不需要更大的堆,则可以收缩。堆的内存不需要是连续的。
通过简单地调用构造函数(例如 HashMap foo = new HashMap()
),JVM 将在堆上为此对象分配必要的内存(如果不可能,则抛出 OutOfMemoryError)。同样重要的是要注意对象永远不会存在于堆栈中——只有对它们的引用才会存在。此外,非原始字段也始终包含对对象的引用。
也可以通过某些 JVM 上的 sun.misc.Unsafe
、分配直接缓冲区的某些 NIO 类 以及通过使用 JNI 来分配堆外内存。此内存不是 JVM 堆的一部分,也不会进行自动垃圾收集(这意味着它需要通过 delete
等方式释放,但它可能是堆内存的一部分,因为 C++ 可能会引用它。