真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

JVM的內(nèi)存區(qū)域劃分-創(chuàng)新互聯(lián)

學過C語言的朋友都知道C編譯器在劃分內(nèi)存區(qū)域的時候經(jīng)常將管理的區(qū)域劃分為數(shù)據(jù)段和代碼段,數(shù)據(jù)段包括堆、棧以及靜態(tài)數(shù)據(jù)區(qū)。那么在Java語言當中,內(nèi)存又是如何劃分的呢?

在港北等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務理念,為客戶提供成都網(wǎng)站建設(shè)、網(wǎng)站建設(shè) 網(wǎng)站設(shè)計制作按需開發(fā)網(wǎng)站,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站建設(shè),成都全網(wǎng)營銷,外貿(mào)營銷網(wǎng)站建設(shè),港北網(wǎng)站建設(shè)費用合理。

由于Java程序是交由JVM執(zhí)行的,所以我們在談Java內(nèi)存區(qū)域劃分的時候事實上是指JVM內(nèi)存區(qū)域劃分。在討論JVM內(nèi)存區(qū)域劃分之前,先來看一下Java程序具體執(zhí)行的過程:

JVM的內(nèi)存區(qū)域劃分

如上圖所示,首先Java源代碼文件(.java后綴)會被Java編譯器編譯為字節(jié)碼文件(.class后綴),然后由JVM中的類加載器加載各個類的字節(jié)碼文件,加載完畢之后,交由JVM執(zhí)行引擎執(zhí)行。在整個程序執(zhí)行過程中,JVM會用一段空間來存儲程序執(zhí)行期間需要用到的數(shù)據(jù)和相關(guān)信息,這段空間一般被稱作為Runtime Data Area(運行時數(shù)據(jù)區(qū)),也就是我們常說的JVM內(nèi)存。因此,在Java中我們常常說到的內(nèi)存管理就是針對這段空間進行管理(如何分配和回收內(nèi)存空間)。

在知道了JVM內(nèi)存是什么東西之后,下面我們就來討論一下這段空間具體是如何劃分區(qū)域的,是不是也像C語言中一樣也存在棧和堆呢?

一.運行時數(shù)據(jù)區(qū)包括哪幾部分?

根據(jù)《Java虛擬機規(guī)范》的規(guī)定,運行時數(shù)據(jù)區(qū)通常包括這幾個部分:程序計數(shù)器(Program Counter Register)、Java棧(VM Stack)、本地方法棧(Native Method Stack)、方法區(qū)(Method Area)、堆(Heap)。

JVM的內(nèi)存區(qū)域劃分

如上圖所示,JVM中的運行時數(shù)據(jù)區(qū)應該包括這些部分。在JVM規(guī)范中雖然規(guī)定了程序在執(zhí)行期間運行時數(shù)據(jù)區(qū)應該包括這幾部分,但是至于具體如何實現(xiàn)并沒有做出規(guī)定,不同的虛擬機廠商可以有不同的實現(xiàn)方式。

二.運行時數(shù)據(jù)區(qū)的每部分到底存儲了哪些數(shù)據(jù)?

下面我們來了解一下運行時數(shù)據(jù)區(qū)的每部分具體用來存儲程序執(zhí)行過程中的哪些數(shù)據(jù)。

1.程序計數(shù)器

程序計數(shù)器(Program Counter Register),也有稱作為PC寄存器。想必學過匯編語言的朋友對程序計數(shù)器這個概念并不陌生,在匯編語言中,程序計數(shù)器是指CPU中的寄存器,它保存的是程序當前執(zhí)行的指令的地址(也可以說保存下一條指令的所在存儲單元的地址),當CPU需要執(zhí)行指令時,需要從程序計數(shù)器中得到當前需要執(zhí)行的指令所在存儲單元的地址,然后根據(jù)得到的地址獲取到指令,在得到指令之后,程序計數(shù)器便自動加1或者根據(jù)轉(zhuǎn)移指針得到下一條指令的地址,如此循環(huán),直至執(zhí)行完所有的指令。

雖然JVM中的程序計數(shù)器并不像匯編語言中的程序計數(shù)器一樣是物理概念上的CPU寄存器,但是JVM中的程序計數(shù)器的功能跟匯編語言中的程序計數(shù)器的功能在邏輯上是等同的,也就是說是用來指示 執(zhí)行哪條指令的。

由于在JVM中,多線程是通過線程輪流切換來獲得CPU執(zhí)行時間的,因此,在任一具體時刻,一個CPU的內(nèi)核只會執(zhí)行一條線程中的指令,因此,為了能夠使得每個線程都在線程切換后能夠恢復在切換之前的程序執(zhí)行位置,每個線程都需要有自己獨立的程序計數(shù)器,并且不能互相被干擾,否則就會影響到程序的正常執(zhí)行次序。因此,可以這么說,程序計數(shù)器是每個線程所私有的。

在JVM規(guī)范中規(guī)定,如果線程執(zhí)行的是非native方法,則程序計數(shù)器中保存的是當前需要執(zhí)行的指令的地址;如果線程執(zhí)行的是native方法,則程序計數(shù)器中的值是undefined。

由于程序計數(shù)器中存儲的數(shù)據(jù)所占空間的大小不會隨程序的執(zhí)行而發(fā)生改變,因此,對于程序計數(shù)器是不會發(fā)生內(nèi)存溢出現(xiàn)象(OutOfMemory)的。

2.Java棧

Java棧也稱作虛擬機棧(Java Vitual Machine Stack),也就是我們常常所說的棧,跟C語言的數(shù)據(jù)段中的棧類似。事實上,Java棧是Java方法執(zhí)行的內(nèi)存模型。為什么這么說呢?下面就來解釋一下其中的原因。

Java棧中存放的是一個個的棧幀,每個棧幀對應一個被調(diào)用的方法,在棧幀中包括局部變量表(Local Variables)、操作數(shù)棧(Operand Stack)、指向當前方法所屬的類的運行時常量池(運行時常量池的概念在方法區(qū)部分會談到)的引用(Reference to runtime constant pool)、方法返回地址(Return Address)和一些額外的附加信息。當線程執(zhí)行一個方法時,就會隨之創(chuàng)建一個對應的棧幀,并將建立的棧幀壓棧。當方法執(zhí)行完畢之后,便會將棧幀出棧。因此可知,線程當前執(zhí)行的方法所對應的棧幀必定位于Java棧的頂部。講到這里,大家就應該會明白為什么 在 使用 遞歸方法的時候容易導致棧內(nèi)存溢出的現(xiàn)象了以及為什么棧區(qū)的空間不用程序員去管理了(當然在Java中,程序員基本不用關(guān)系到內(nèi)存分配和釋放的事情,因為Java有自己的垃圾回收機制),這部分空間的分配和釋放都是由系統(tǒng)自動實施的。對于所有的程序設(shè)計語言來說,棧這部分空間對程序員來說是不透明的。下圖表示了一個Java棧的模型:

JVM的內(nèi)存區(qū)域劃分

局部變量表,顧名思義,想必不用解釋大家應該明白它的作用了吧。就是用來存儲方法中的局部變量(包括在方法中聲明的非靜態(tài)變量以及函數(shù)形參)。對于基本數(shù)據(jù)類型的變量,則直接存儲它的值,對于引用類型的變量,則存的是指向?qū)ο蟮囊?。局部變量表的大小在編譯器就可以確定其大小了,因此在程序執(zhí)行期間局部變量表的大小是不會改變的。

操作數(shù)棧,想必學過數(shù)據(jù)結(jié)構(gòu)中的棧的朋友想必對表達式求值問題不會陌生,棧最典型的一個應用就是用來對表達式求值。想想一個線程執(zhí)行方法的過程中,實際上就是不斷執(zhí)行語句的過程,而歸根到底就是進行計算的過程。因此可以這么說,程序中的所有計算過程都是在借助于操作數(shù)棧來完成的。

指向運行時常量池的引用,因為在方法執(zhí)行的過程中有可能需要用到類中的常量,所以必須要有一個引用指向運行時常量。

方法返回地址,當一個方法執(zhí)行完畢之后,要返回之前調(diào)用它的地方,因此在棧幀中必須保存一個方法返回地址。

由于每個線程正在執(zhí)行的方法可能不同,因此每個線程都會有一個自己的Java棧,互不干擾。

3.本地方法棧

本地方法棧與Java棧的作用和原理非常相似。區(qū)別只不過是Java棧是為執(zhí)行Java方法服務的,而本地方法棧則是為執(zhí)行本地方法(Native Method)服務的。在JVM規(guī)范中,并沒有對本地方發(fā)展的具體實現(xiàn)方法以及數(shù)據(jù)結(jié)構(gòu)作強制規(guī)定,虛擬機可以自由實現(xiàn)它。在HotSopt虛擬機中直接就把本地方法棧和Java棧合二為一。

4.堆

在C語言中,堆這部分空間是唯一一個程序員可以管理的內(nèi)存區(qū)域。程序員可以通過malloc函數(shù)和free函數(shù)在堆上申請和釋放空間。那么在Java中是怎么樣的呢?

Java中的堆是用來存儲對象本身的以及數(shù)組(當然,數(shù)組引用是存放在Java棧中的)。只不過和C語言中的不同,在Java中,程序員基本不用去關(guān)心空間釋放的問題,Java的垃圾回收機制會自動進行處理。因此這部分空間也是Java垃圾收集器管理的主要區(qū)域。另外,堆是被所有線程共享的,在JVM中只有一個堆。

5.方法區(qū)

方法區(qū)在JVM中也是一個非常重要的區(qū)域,它與堆一樣,是被線程共享的區(qū)域。在方法區(qū)中,存儲了每個類的信息(包括類的名稱、方法信息、字段信息)、靜態(tài)變量、常量以及編譯器編譯后的代碼等。

在Class文件中除了類的字段、方法、接口等描述信息外,還有一項信息是常量池,用來存儲編譯期間生成的字面量和符號引用。

在方法區(qū)中有一個非常重要的部分就是運行時常量池,它是每一個類或接口的常量池的運行時表示形式,在類和接口被加載到JVM后,對應的運行時常量池就被創(chuàng)建出來。當然并非Class文件常量池中的內(nèi)容才能進入運行時常量池,在運行期間也可將新的常量放入運行時常量池中,比如String的intern方法。

在JVM規(guī)范中,沒有強制要求方法區(qū)必須實現(xiàn)垃圾回收。很多人習慣將方法區(qū)稱為“永久代”,是因為HotSpot虛擬機以永久代來實現(xiàn)方法區(qū),從而JVM的垃圾收集器可以像管理堆區(qū)一樣管理這部分區(qū)域,從而不需要專門為這部分設(shè)計垃圾回收機制。不過自從JDK7之后,Hotspot虛擬機便將運行時常量池從永久代移除了。

以上為個人看法和觀點,如有不正之處希望諒解并歡迎指正。

另外有需要云服務器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。


新聞標題:JVM的內(nèi)存區(qū)域劃分-創(chuàng)新互聯(lián)
分享路徑:http://weahome.cn/article/joihs.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部