有一段时间前,我写了几篇关于 Java垃圾回收 和 Java是值传递 的文章。之后,我收到了很多电子邮件,要求解释 Java堆空间、Java栈内存、Java内存分配 以及它们之间的区别。在Java、Java EE的书籍和教程中,你会经常看到关于堆和栈内存的引用,但很少有对这两者在程序中的具体解释。
Java堆空间
Java堆空间被Java运行时用于为对象和JRE类分配内存。每当我们创建一个对象时,它总是在堆空间中创建。垃圾回收在堆内存上运行,以释放那些没有任何引用的对象占用的内存。在堆空间中创建的任何对象都具有全局访问权限,并且可以从应用程序的任何地方引用。
Java栈内存
Java堆栈内存用于执行线程。它们包含方法特定的短暂值和从方法引用的堆中其他对象的引用。堆栈内存总是按照后进先出(LIFO)的顺序引用。每当调用方法时,在堆栈内存中为该方法创建一个新块,用于保存本地基本值和方法中其他对象的引用。一旦方法结束,该块变为未使用状态,并变为下一个方法可用。与堆内存相比,堆栈内存大小非常小。
Java程序中的堆内存和栈内存
让我们通过一个简单的程序了解堆和栈内存的使用。
package com.journaldev.test;
public class Memory {
public static void main(String[] args) { // Line 1
int i=1; // Line 2
Object obj = new Object(); // Line 3
Memory mem = new Memory(); // Line 4
mem.foo(obj); // Line 5
} // Line 9
private void foo(Object param) { // Line 6
String str = param.toString(); //// Line 7
System.out.println(str);
} // Line 8
}
下面的图像显示了与上述程序相关的堆和栈内存以及它们用于存储基本值、对象和引用变量的方式。让我们了解程序执行的步骤。
- 一旦运行程序,它将所有运行时类加载到堆空间中。当在第1行找到main()方法时,Java运行时创建用于main()方法线程的堆栈内存。
- 我们在第2行创建了原始局部变量,因此它被创建并存储在main()方法的堆栈内存中。
- 由于我们在第3行创建了一个对象,它被创建在堆内存中,而堆栈内存包含了对它的引用。当我们在第4行创建Memory对象时,类似的过程发生。
- 现在当我们在第5行调用foo()方法时,一个堆栈顶部的块被创建,用于foo()方法。由于Java是按值传递的,因此在第6行在foo()堆栈块中创建了一个对对象的新引用。
- A string is created in the 7th line, it goes in the String Pool in the heap space and a reference is created in the foo() stack space for it.
- foo()方法在第8行终止,在这个时候堆栈中为foo()分配的内存块变为自由。
- 在第9行,main()方法终止,为main()方法创建的堆栈内存被销毁。此外,程序在此行结束,因此Java运行时释放所有内存并结束程序的执行。
Java堆空间和堆栈内存之间的区别
根据以上解释,我们可以轻松得出堆和栈内存之间的以下区别。
- 堆内存被应用程序的所有部分使用,而堆栈内存仅被一个执行线程使用。
- 每当创建一个对象时,它总是存储在堆空间中,而栈内存包含对它的引用。栈内存仅包含本地原始变量和对堆空间中对象的引用变量。
- 存储在堆中的对象是全局可访问的,而栈内存无法被其他线程访问。
- 栈中的内存管理以LIFO方式进行,而在堆内存中,由于其全局使用,情况更为复杂。堆内存分为年轻代、老年代等,更多细节请参阅Java垃圾回收。
- 栈内存的生命周期较短,而堆内存的生命周期从应用程序执行的开始到结束。
- 我们可以使用-Xms和-Xmx JVM选项定义堆内存的启动大小和最大大小。我们可以使用-Xss定义栈内存的大小。
- 当栈内存已满时,Java运行时会抛出
java.lang.StackOverFlowError
,而如果堆内存已满,则会抛出java.lang.OutOfMemoryError: Java Heap Space
错误。 - 与堆内存相比,栈内存的大小要小得多。由于内存分配的简单性(LIFO),栈内存比堆内存更快。
这就是关于Java Heap Space vs Stack Memory在Java应用程序方面的一切,我希望这能解答您对Java程序执行时内存分配的疑虑。
Source:
https://www.digitalocean.com/community/tutorials/java-heap-space-vs-stack-memory