堆是堆(heap),棧是棧(stack),堆棧是棧。
棧中分配的是基本類型和自定義對象的引用。
堆中分配的是對象,也就是new出來的東西。 被所有線程共享。
方法區/靜態區 存放的是類信息和static變量、常量。 被所有線程共享。
也可以這么理解:堆是用來存放對象的,棧是用來運行程序的。
堆:java的垃圾回收器會自動的回收這些不用的數據。缺點是由於要動態的分配內存,存儲效率會比較的慢。
棧:棧的優勢是存取效率比較快,僅次於寄存器,棧數據可以共享。但缺點是棧中的數據大小和生存期的固定的,缺乏靈活性。
一般每個方法的調用都會獨立有一個棧來保存對象的引用變量,在方法返回后,棧會清空,當在一段代碼塊定義一個變量時,Java就在棧中為這個變量分配內存空間,當超過變量的作用域后,Java會自動釋放掉為該變量所分配的內存空間,該內存空間可以立即被另作他用。



JAVA的JVM的內存可分為3個區:堆(heap)、棧(stack)和方法區(method)
- 棧區:
- 每個線程包含一個棧區,棧中只保存方法中(不包括對象的成員變量)的基礎數據類型和自定義對象的引用(不是對象),對象都存放在堆區中
- 每個棧中的數據(原始類型和對象引用)都是私有的,其他棧不能訪問。
- 棧分為3個部分:基本類型變量區、執行環境上下文、操作指令區(存放操作指令)。
- 堆區:
- 存儲的全部是對象實例,每個對象都包含一個與之對應的class的信息(class信息存放在方法區)。
- jvm只有一個堆區(heap)被所有線程共享,堆中不存放基本類型和對象引用,只存放對象本身,幾乎所有的對象實例和數組都在堆中分配。
- 方法區:
- 又叫靜態區,跟堆一樣,被所有的線程共享。它用於存儲已經被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯后的代碼等數據。
這個“堆”並不是數據結構意義上的堆(Heap (data structure),一種有序的樹),而是動態內存分配意義上的堆——用於管理動態生命周期的內存區域。
JVM規范讓每個Java線程擁有自己的獨立的JVM棧,也就是Java方法的調用棧。
JVM規范為了允許native代碼可以調用Java代碼,以及允許Java代碼調用native方法,還規定每個Java線程擁有自己的獨立的native方法棧。
並不是說具體的JVM實現真的要給每個Java線程開兩個獨立的棧。以Oracle JDK / OpenJDK的HotSpot VM為例,它使用所謂的“mixed stack”——在同一個調用棧里存放Java方法的棧幀與native方法的棧幀,所以每個Java線程其實只有一個調用棧,融合了JVM規范的JVM棧與native方法棧這倆概念。
