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