當前位置:
首頁 > 知識 > 快速認識Java內存區域劃分

快速認識Java內存區域劃分

快速認識Java內存區域劃分

Java內存區域

Java 內存區域中比較重要也是經常被提到的幾部分是:程序計數器,棧(Stack),堆(Heap)方法區,它們都定義在被稱作運行時數據區(Runing Data Area)的區域中。

其中程序計數器棧(Stack)是隨線程啟動而生,線程結束而滅的,也就屬於線程私有。而堆(Heap)方法區是由JVM啟動時創建切被所有線程共享的。


程序計數器

我們知道所有程序代碼在最底層都是要被轉化為機器指令才能夠被電腦識別並執行。當前程序不在是執行1+1或簡單的列印字元串(實際上執行列印字元串相對於1+1已經是比較複雜的功能了,包含多個指令),而是要完成更加複雜的功能時,其所包含的指令也就更多,那麼為了按邏輯順序執行這些指令,就需要一個計數器來幫助一條條提取指令或指出下一條指令的位置。這裡說的是CPU中的程序計數器的概念,換成JVM 程序計數器,其所承擔的任務是基本一樣的,只需要將指令換成位元組碼行號即可。

JVM的位元組碼解釋器通過改變程序計數器的當前值,來提取下一條需要執行位元組碼的行號(既被編譯為二進位的java代碼)。所有的完成分支,循環,跳轉,異常處理,線程恢復等的功能都是依賴它來完成的。

另外,由於Java的多線程特性(通過輪流切換並分配CPU的使用權,CPU在同一時間也只會執行一個線程中指令),為了在線程切換後能夠恢復到正確位置,所以每個線程都有自己的獨立的 程序計數器,這就是所謂的線程私有。

棧(Stack)

需要特別指出的是,這裡說的棧(Stack)是指虛擬機棧 (在jvm規範中,棧分為虛擬機棧也就是執行Java 方法時用到的,還有本地方法棧,兩者區別在與本地方法棧為執行Native方法服務,Sun公司的jvm 稱為HotSpot,它將虛擬機棧本地方法棧合二唯一了)。

相比程序計數器,棧(Stack)的出鏡率更高,也離開發人員更近。在棧(Stack)中包含了用於Java方法執行時所需要的局部變數表,操作數,動態鏈接以及方法出口等信息。由於操作數,我們常說的棧其實只是其中的局部變數表(至少我這個級別的coder是這樣),這主要是因為操作數,動態鏈接以及方法出口等與我們關係並不大,這也就造成了局部變數表成為棧(Stack)的代名詞。

之所以局部變數表被我們常常提到,是因為他的作用。局部變數表是用於存放編譯期間就已知的基本數據類型以及對象引用(地址指針或對象句柄)。

快速認識Java內存區域劃分

以上代碼中的 int a 與 User user 都是存放在局部變數表中。其中 a 是基本數據類型,它指向了一個值為1的內存空間,該內存空間的大小有類型 int限定。user則存放的是 new User()這個對象在堆(Heap)中的內存位置。另外,以上代碼之所以要聲明一個方法體,是為了強調局部變數概念,如果 a和 use是全局變數,那麼它們則在堆內存中屬於對象,而如果他們是加上關鍵static的靜態變數或者加上final的常量,則會在方法區的常量池中屬於類。

棧是線程私有的,隨線程結束而空間被回收。棧的大小是有限制的,當出現線程請求深度大於棧的最大深度則會出現StackOverFlow異常;而當Stack需要動態擴展而內存沒有足夠空間時則會出現OutOfMemoryError異常。


堆(Heap)

的唯一作用就是存放所有對象實例與數組的。它是線程共享的,是Jvm所有管理的內存中最大的一塊,也是垃圾收集器GC管理的主要區域。

為了GC更好的進行內存回收,大部分GC使用了分代收集演算法,它將堆劃分了新生代與老年代。其中新生代又被劃分為Eden空間、From Survivor空間和To Survivor空間(Eden是伊甸園,Survivor是倖存者,新創建的對象會優先在Eden中,當第一次GC清理時未被清理的對象則會移動到Survivor空間。這部分會在將來討論GC時細說)。

的空間大小也是有限制的。我們可以通過參數-Xmx與-Xms來制定最大與最小空間。當超出-Xmx所設置的量時,則出現OutOfMemoryError:heapSpace 異常;


方法區

方法區用於存儲虛擬機啟動時載入的類信息,常量和靜態變數。與堆一樣,方法區也是線程共享的。與其他版本的JVM不同,SUN 公司的Hotspot 虛擬機將方法區*劃分為永久代(Permanent Generation)。

大多數JAVA開發人員,尤其是會使用很多三方JAR的WEB開發人員都應該見過OutOfMemoryError:PermGen space 這個異常信息。出現原因便是方法區發生了內存溢出。雖然GC在方法區也會進行回收,但其目的是卸載類和回收常量池,大部分情況下,回收效果都不是很好。方法區的溢出在使用如Spring或Hibernate(這些框架會在運行時通過CGLib位元組碼技術來增強原有類),或者有大量JSP文件,又或者OSGI等會有大量動態生成的類被載入到方法區的應用中更容易出現。 在不能精簡載入的jar和應用本身包含的類或常量,靜態變數的情況下,可通過參數-XX:PermSize和-XX:MaxPermSize參數來設置方法區大小,來減少OutOfMemoryError:PermGen space異常的出現。


學習Java的同學注意了!!!

學習過程中遇到什麼問題或者想獲取學習資源的話,歡迎加入Java學習交流群495273252,我們一起學Java!

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Java團長 的精彩文章:

Java線程間通信之wait/notify
Java集合——ArrayList
Java知識點路線圖整理
淺談Java內存分配和回收策略
程序員,感覺技術停滯了怎麼辦?

TAG:Java團長 |

您可能感興趣

重新認識室內光源重要性—WiT Genie
五分鐘帶你認識Facebook
梳理Python基本認識基本類型,Python學習經驗分享
解讀 | 超級賬本 Brian Behlendorf 教你認識區塊鏈
設計大師 | 讓我們重新認識Clare Waight Keller
認識Photoshop
很高興認識你 moni卡 daily
Recognizing Shapes 認識形狀
加州網紅男模Salvatore Vita分享微整經歷,想認識他的醫生!
認識Adobe Photoshop
Solstice Public Affairs 帶你一起認識新的安省廳長
認識一個好玩的時間切片器-Time Brush Slicer
Cognizing Annoyances 認識煩惱
與Misendemeure相遇,帶你認識純正法式設計
認識canmake怎能不認識CEZANNE?人氣產品大揭秘!
白平衡、快門速度、ISO基本認識
認識windows中的命令符
對conda和pip的一點認識
認不認識G-Dragon?」雞涌在泰劇中出鏡!
FateGrand,Order,Saber,cosplay!小編一個不認識!