理解JVM運行時的數(shù)據(jù)區(qū)是Java編程中的進階部分。我們在開發(fā)中都遇到過一個很頭疼的問題就是OutOfMemoryError(內(nèi)存溢出錯誤),但是如果我們了解JVM的內(nèi)部實現(xiàn)和其運行時的數(shù)據(jù)區(qū)的工作機制,那么前面的問題就會迎刃而解。在這片文章中,我們將簡單了解JVM中有哪些運行時數(shù)據(jù)區(qū)以及這些數(shù)據(jù)區(qū)的工作機制。 JVM運行時數(shù)據(jù)區(qū)分類
有圖才能說按線程持有劃分查看上面的圖,可以得知以上六個數(shù)據(jù)區(qū)其實線程私有還是共享,可以分為如下兩種。
程序計數(shù)器在通用的計算機體系中,程序計數(shù)器用來記錄當前正在執(zhí)行的指令,在JVM中也是如此。程序計數(shù)器是線程私有,所以當一個新的線程創(chuàng)建時,程序計數(shù)器也會創(chuàng)建。由于Java是支持多線程,Java中的程序計數(shù)器用來記錄當前線程中正在執(zhí)行的指令。如果當前正在執(zhí)行的方法是本地方法,那么此刻程序計數(shù)器的值為undefined。注意這個區(qū)域是唯一一個不拋出OutOfMemoryError的運行時數(shù)據(jù)區(qū)。 JVM棧在介紹JVM棧之前,簡單介紹一個概念,棧幀 棧幀一個棧幀隨著一個方法的調(diào)用開始而創(chuàng)建,這個方法調(diào)用完成而銷毀。棧幀內(nèi)存放者方法中的局部變量,操作數(shù)棧等數(shù)據(jù)。 JVM棧只對棧幀進行存儲,壓棧和出棧操作。棧內(nèi)存的大小可以有兩種設置,固定值和根據(jù)線程需要動態(tài)增長。在JVM棧這個數(shù)據(jù)區(qū)可能會發(fā)生拋出兩種錯誤。
堆數(shù)據(jù)區(qū)堆數(shù)據(jù)區(qū)是用來存放對象和數(shù)組(特殊的對象)。堆內(nèi)存由多個線程共享。堆內(nèi)存隨著JVM啟動而創(chuàng)建。眾所周知,Java中有一個很好的特性就是自動垃圾回收。垃圾回收就操作這個數(shù)據(jù)區(qū)來回收對象進而釋放內(nèi)存。如果堆內(nèi)存剩余的內(nèi)存不足以滿足于對象創(chuàng)建,JVM會拋出OutOfMemoryError錯誤。 方法區(qū)在JVM規(guī)范中,方法區(qū)被視為堆內(nèi)存的一個邏輯部分。這一點可能由于具體的JVM實現(xiàn)而不同,甚至在方法區(qū)不實現(xiàn)垃圾回收處理也是可以的。方法區(qū)和堆內(nèi)存一樣被多個線程訪問,方法區(qū)中存放類的信息,比如類加載器引用,屬性,方法代碼和構造方法和常量等。當方法區(qū)的可用內(nèi)存無法滿足內(nèi)存分配需求時,JVM會拋出OutOfMemoryError錯誤。 運行時常量池運行時常量池創(chuàng)建在方法區(qū),當一個類或者一個接口被創(chuàng)建的時候,JVM會創(chuàng)建一個運行時常量池。一個運行時常量池實際上是一個類或者接口的class文件中常量池表(constant_pool table)的運行時展示形式。一個運行時常量池包含了多種類型的常量,從諸如運行時可以確定的數(shù)值型字面量到運行時才能決定的方法和屬性引用。當運行時常量池無法滿足于內(nèi)存分配需求時,JVM會拋出OutOfMemoryError錯誤。 本地方法棧一個支持native方法調(diào)用的JVM實現(xiàn),需要有這樣一個數(shù)據(jù)區(qū),就是本地方法棧,Java官方對于本地方法的定義為 譯文信息
注:本文介紹JVM運行時數(shù)據(jù)相對比較概括,以后會有更加詳細的針對單個數(shù)據(jù)區(qū)的介紹。 |
|