Java虛擬機的堆、棧、堆棧如何去理解?


Java虛擬機的堆、棧、堆棧如何去理解?

 

堆是堆(heap),棧是棧(stack),堆棧是棧。

 

棧中分配的是基本類型和自定義對象的引用。

堆中分配的是對象,也就是new出來的東西。                 被所有線程共享。

方法區/靜態區 存放的是類信息和static變量、常量。      被所有線程共享。

 

也可以這么理解:堆是用來存放對象的,棧是用來運行程序的。

堆:java的垃圾回收器會自動的回收這些不用的數據。缺點是由於要動態的分配內存,存儲效率會比較的慢。

棧:棧的優勢是存取效率比較快,僅次於寄存器,棧數據可以共享。但缺點是棧中的數據大小和生存期的固定的,缺乏靈活性。

一般每個方法的調用都會獨立有一個棧來保存對象的引用變量,在方法返回后,棧會清空,當在一段代碼塊定義一個變量時,Java就在棧中為這個變量分配內存空間,當超過變量的作用域后,Java會自動釋放掉為該變量所分配的內存空間,該內存空間可以立即被另作他用。

 

 

 

 

JAVA的JVM的內存可分為3個區:堆(heap)、棧(stack)和方法區(method)

  • 棧區: 
  1. 每個線程包含一個棧區,棧中只保存方法中(不包括對象的成員變量)的基礎數據類型自定義對象的引用(不是對象),對象都存放在堆區中
  2. 每個棧中的數據(原始類型和對象引用)都是私有的,其他棧不能訪問。
  3. 棧分為3個部分:基本類型變量區、執行環境上下文、操作指令區(存放操作指令)。
  • 堆區: 
  1. 存儲的全部是對象實例,每個對象都包含一個與之對應的class的信息(class信息存放在方法區)。
  2. jvm只有一個堆區(heap)被所有線程共享,堆中不存放基本類型和對象引用,只存放對象本身,幾乎所有的對象實例和數組都在堆中分配。
  • 方法區: 
  1. 又叫靜態區,跟堆一樣,被所有的線程共享。它用於存儲已經被虛擬機加載的類信息常量靜態變量、即時編譯器編譯后的代碼等數據。

 

這個“堆”並不是數據結構意義上的堆(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方法棧這倆概念。

 
JVM的堆被同一個JVM實例中的所有Java線程共享。它通常由某種自動內存管理機制所管理,這種機制通常叫做“ 垃圾回收”(garbage collection,GC)。JVM規范並不強制要求JVM實現采用哪種GC算法。
 
linux 中一個進程的虛擬內存分布:
 
 
以32位地址操作系統為例,一個進程可擁有的虛擬內存地址范圍為0-2^32。分為兩部分,一部分留給kernel使用(kernel virtual memory),剩下的是進程本身使用, 即圖中的process virtual memory。
 
 
一個程序本質上都是由 bss段、data段、text段三個組成的
bss段(Block Started by Symbol segment)通常是指用來存放程序中未初始化的全局變量的一塊內存區域,一般在初始化時bss 段部分將會清零。bss段屬於靜態內存分配,即程序一開始就將其清零了。
在C語言之類的程序編譯完成之后,已初始化的全局變量保存在.data 段中,未初始化的全局變量保存在.bss 段中。
text和data段都在可執行文件中(在嵌入式系統里一般是固化在鏡像文件中),由系統從可執行文件中加載;而bss段不在可執行文件中,由系統初始化。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM