国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設計 > 正文

Java虛擬機之內(nèi)存簡介

2019-11-15 01:00:19
字體:
供稿:網(wǎng)友
java虛擬機之內(nèi)存簡介

本文主要介紹Java虛擬機的內(nèi)存分布以及對象的創(chuàng)建過程。

一、Java虛擬機的內(nèi)存分布

文章開始前讀者需要了解Java虛擬機的運行時數(shù)據(jù)區(qū)是怎樣劃分的。如下圖所示:

1、程序計數(shù)器PRogram Counter Register)

  程序計數(shù)器是一塊較小的內(nèi)存空間,它可以看作是當前線程所執(zhí)行的字節(jié)碼的行號指示器。

  由于Java虛擬機的多線程是通過線程輪流切換并分配處理器執(zhí)行時間的方式來實現(xiàn)的,所以在任何一個確定的時刻,一個處理器(對于多核處理器來說是一個內(nèi)核)都只會執(zhí)行一條線程中的指令。因此,為了線程切換后能夠恢復到正確的執(zhí)行位置,每條線程都需要有一個獨立的程序計數(shù)器。

  各條線程之間計數(shù)器互不影響,獨立存儲,我們稱這類內(nèi)存區(qū)域為“線程私有”的內(nèi)存。

  熟悉C++的讀者應該了解“現(xiàn)場保護”這個概念,雖然“現(xiàn)場保護”對應的是函數(shù)調(diào)用,而這里的程序計數(shù)器對應的是線程之間的切換,但筆者認為它們的作用有點相似:都是為了線程或函數(shù)執(zhí)行完后能夠恢復到正確的位置。

2、Java虛擬機棧(Java Virtual Machine Stacks)

  我們平時所說的棧區(qū)就是Java虛擬機棧。

  與程序計數(shù)器一樣,Java虛擬機棧也是線程私有的,生命周期與線程相同。

  虛擬機棧描述的是Java方法執(zhí)行的內(nèi)存模型:每個方法在執(zhí)行的同時都會創(chuàng)建一個棧楨(Stack Frame)用于存儲該方法的信息,如局部變量表、操作數(shù)棧、方法的出口等信息。

  每個方法從調(diào)用直至執(zhí)行完成的過程,就對應著一個棧楨入棧到出棧的過程。

  局部變量表存放了編譯期可知的各種基本數(shù)據(jù)類型(boolean、byte、char、short、int、float、long、double)、對象引用(reference類型,不是對象本身)和returnAddress類型(指向了一條字節(jié)碼指令的位置)。

  Java虛擬機規(guī)范中,對這個區(qū)域規(guī)定了兩種異常狀況:StackOverflowError異常和OutOfMemoryError異常。

3、Java堆(Java Heap)

  Java堆是Java虛擬機所管理的內(nèi)存中最大的一塊,該內(nèi)存是被所有線程共享的,在虛擬機啟動時創(chuàng)建。此內(nèi)存區(qū)域存在的唯一目的就是存放對象實例,幾乎所有的對象實例都在這里分配內(nèi)存。既然Java堆中存放了幾乎所有的實例,那么這里自然就成了垃圾收集器管理的主要區(qū)域。

  當堆中沒有內(nèi)存完成了實例分配,并且堆也無法再擴張時,將會拋出OutOfMemoryError異常。

4、方法區(qū)(Method Area)

  方法區(qū)與Java堆一樣,是各個線程共享的內(nèi)存區(qū)域。

  它用于存儲已被虛擬機加載的類信息、常量、靜態(tài)變量、即時編譯器編譯后的代碼等數(shù)據(jù)。

  方法區(qū)還包括了運行時常量池。

  當方法區(qū)無法滿足內(nèi)存分配需求時,將拋出OutOfMemoryError異常。

5、本地方法棧(Native Method Stack)

  本地方法棧與虛擬機棧的作用非常相似,它們的區(qū)別不過是虛擬機棧為虛擬機執(zhí)行Java方法(也就是字節(jié)碼)服務,而本地方法棧則為了虛擬機使用到的Native方法服務。

  在虛擬機規(guī)范中隊本地方法棧方法使用的語言、使用的算法與數(shù)據(jù)結(jié)構(gòu)并沒有強制規(guī)定,因此具體的虛擬機可以自由實現(xiàn)它。甚至有的虛擬機(如 Sun HotSpot 虛擬機)直接就把本地方法棧和虛擬機棧合二為一。

  該數(shù)據(jù)區(qū)拋出的異常和虛擬機棧相同:都會拋出StackOverflowError和OutOfMemoryError異常。

6、運行時常量池(Runtime Constant Pool)

  運行時常量池屬于方法區(qū)的一部分。雖然Java虛擬機沒有單獨為運行時常量池劃分內(nèi)存空間,但是由于該區(qū)域在平時開發(fā)中也是一個重要的部分,所以也為它單獨列一個條目。

  Class文件中除了有類的版本、字段、方法、接口的描述信息外,還有一項信息是常量池(Constant Pool Table),用于存放編譯期生成的各種字面量的引用,這部分內(nèi)容將在類加載后進入方法區(qū)的運行時常量池中存放。

  運行時常量池相對于Class文件常量池的另外一個重要特征是具有動態(tài)性,Java語言并不要求常量一定只有編譯期才能產(chǎn)生,也就是說并非預置入Class文件中常量池的內(nèi)容才能進入方法區(qū)運行時常量池,運行期間也可能將新的常量放入池中,如String類的intern()方法。

  既然運行時常量池是方法區(qū)的一部分,自然受到方法區(qū)內(nèi)存的限制,當常量池無法再申請到內(nèi)存是會拋出OutOfMemoryError異常。

二、對象的創(chuàng)建過程

  Java是一門面向?qū)ο蟮恼Z言,在Java程序運行過程中無時無刻都會有對象被創(chuàng)建出來。在語言層面上通產(chǎn)僅僅是一個new關鍵字,而在虛擬機中可就沒有這么簡單了:

  虛擬機遇到一條new指令時,首先將去檢查這個指令的參數(shù)是否能在常量池中定位到一個類的符號引用,并且檢查這個符號引用代表的類是否被加載、解析和初始化過。如果沒有,那必須先執(zhí)行相應的類加載過程。  在類加載檢查通過后,接下來虛擬機將為新生對象在Java堆中分配內(nèi)存(對象所需的內(nèi)存大小在內(nèi)加載完成后便可完全確定)。接下來,虛擬機要對對象進行一些必要的設置,如這個對象是哪個類的實例、對象的哈希碼、對象的GC分代年齡等信息。這些信息存放在對象的對象頭(Object Header)之中。

  在上面工作都完成之后,從虛擬機的視角來看:一個新的對象已經(jīng)產(chǎn)生了,但從Java程序的視角來看:對象創(chuàng)建才剛剛開始——<init>方法還沒有執(zhí)行,所有的字段都還為零。一般來說執(zhí)行new指令之后會接著執(zhí)行<init>方法,把對象按照程序員的意愿進行初始化。這樣一個真正可用的對象才算完全產(chǎn)生出來。

本文章系筆者的第一篇文章,文章中難免有錯誤和不足的地方,還請大家指正。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 阜平县| 深水埗区| 纳雍县| 凤翔县| 阿克| 绥宁县| 德安县| 郯城县| 米泉市| 那曲县| 五原县| 武穴市| 巴南区| 宣汉县| 金塔县| 延庆县| 济南市| 东阳市| 卢龙县| 乐东| 博罗县| 尚志市| 株洲市| 柯坪县| 宝山区| 惠东县| 清丰县| 康乐县| 贵南县| 木里| 岐山县| 桂东县| 东源县| 通城县| 二连浩特市| 卢氏县| 清水县| 高尔夫| 张家川| 小金县| 巴青县|