Java 內(nèi)存區(qū)域
創(chuàng)新互聯(lián)建站服務(wù)項目包括沽源網(wǎng)站建設(shè)、沽源網(wǎng)站制作、沽源網(wǎng)頁制作以及沽源網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,沽源網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到沽源省份的部分城市,未來相信會繼續(xù)擴大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!Heap
線程公有
存放實例對象
是GC主要管理區(qū)域,因此可以更細致的劃分為:新生代、老年代
再細致一點劃分:Eden區(qū)、From Survivor區(qū)、To Survivor區(qū)
內(nèi)存空間:可以物理上不連續(xù)、邏輯上連續(xù)即可。
Method Area
線程公有
主要存儲:類信息、常量、靜態(tài)變量、編譯后的代碼
運行時常量池
主要存儲:編譯期的字面量以及符號引用
具有動態(tài)性,即可以在運行時將常量放入池中。
VM Stack
線程私有
主要包括:
局部變量表:存放編譯期的各種基本數(shù)據(jù)類型、對象引用、returnAddress類型
操作數(shù)棧:每一個元素可以為任意的java類型,32位數(shù)據(jù)類型所占容量為1,64位數(shù)據(jù)類型所占容量為2
動態(tài)連接:class文件的常量池中有大量的符號引用,這些符號引用有一部分是在類加載階段或者在第一次使用的時候就轉(zhuǎn)換為直接引用,這部分成為靜態(tài)解析。另一部分是每一次運行的時候轉(zhuǎn)化為直接引用,這部分即為動態(tài)連接。
方法出口:例如A方法中調(diào)用了B方法,B方法的返回值壓入A方法的棧幀中。
Native Method Stack
線程私有
與VM Stack相似,唯一區(qū)別在于該棧為Native方法服務(wù)。
Hot Spot 將VM Stack 與 Native Method Stack 合而為一。
Program Counter Register
線程私有
用于記錄線程執(zhí)行字節(jié)碼的指令的地址。
Direct Memory
NIO中使用直接內(nèi)存,提高效率。
對象創(chuàng)建過程
首先當虛擬機遇到一條new指令時,先去檢查該符號引用代表的類是否已經(jīng)完成類加載,若未完成,則執(zhí)行以下步驟
類加載
為對象分配內(nèi)存
分配方式:指針碰撞/空閑列表
線程安全:CAS解決
虛擬機初始化內(nèi)存空間
虛擬機對對象進行必要的設(shè)置
執(zhí)行完成初始化
對象創(chuàng)建完成
對象內(nèi)存布局
第一部分用于存儲對象自身的運行時數(shù)據(jù),如哈希碼(HashCode)、GC 分代年齡、鎖狀態(tài)標志、線程持有的鎖、偏向線程 ID、偏向時間戳、對象分代年齡,這部分信息稱為“Mark Word”;Mark Word 被設(shè)計成一個非固定的數(shù)據(jù)結(jié)構(gòu)以便在極小的空間內(nèi)存儲盡量多的信息,它會根據(jù)自己的狀態(tài)復(fù)用自己的存儲空間。
第二部分是類型指針,即對象指向它的類元數(shù)據(jù)的指針,虛擬機通過這個指針來確定這個對象是哪個類的實例;
如果對象是一個 Java 數(shù)組,那在對象頭中還必須有一塊用于記錄數(shù)組長度的數(shù)據(jù)。因為虛擬機可以通過普通 Java 對象的元數(shù)據(jù)信息確定 Java 對象的大小,但是從數(shù)組的元數(shù)據(jù)中無法確定數(shù)組的大小。
在 32 位系統(tǒng)下,存放 Class 指針的空間大小是 4 字節(jié),Mark Word 空間大小也是4字節(jié),因此頭部就是 8 字節(jié),如果是數(shù)組就需要再加 4 字節(jié)表示數(shù)組的長度。
在 64 位系統(tǒng)及 64 位 JVM 下,開啟指針壓縮,那么頭部存放 Class 指針的空間大小還是4字節(jié),而 Mark Word 區(qū)域會變大,變成 8 字節(jié),也就是頭部最少為 12 字節(jié),如下表所示:
鄭州人流醫(yī)院 http://mobile.zzzzyy120.com/
壓縮指針:開啟指針壓縮使用算法開銷帶來內(nèi)存節(jié)約,Java 對象都是以 8 字節(jié)對齊的,也就是以 8 字節(jié)為內(nèi)存訪問的基本單元,那么在地理處理上,就有 3 個位是空閑的,這 3 個位可以用來虛擬,利用 32 位的地址指針原本最多只能尋址 4GB,但是加上 3 個位的 8 種內(nèi)部運算,就可以變化出 32GB 的尋址。
對象訪問定位
兩種方式:
句柄池:引用中存儲的是句柄地址,當實例對象移動時,只需要改變句柄對應(yīng)的指針,不需要改變引用本身,比較穩(wěn)定。
直接指針:速度快,節(jié)省了一次指針定位的開銷。
常用指令
invokeinterface:用以調(diào)用接口方法,在運行時搜索一個實現(xiàn)了這個接口方法的對象,找出適合的方法進行調(diào)用。
invokevirtual:指令用于調(diào)用對象的實例方法,根據(jù)對象的實際類型進行分派
invokestatic:用以調(diào)用類方法
invokespecial:指令用于調(diào)用一些需要特殊處理的實例方法,包括實例初始化方法、私有方法和父類方法。
invokedynamic:JDK1.7新加入的一個虛擬機指令,相比于之前的四條指令,他們的分派邏輯都是固化在JVM內(nèi)部,而invokedynamic則用于處理新的方法分派:它允許應(yīng)用級別的代碼來確定執(zhí)行哪一個方法調(diào)用,只有在調(diào)用要執(zhí)行的時候,才會進行這種判斷,從而達到動態(tài)語言的支持。
基于棧的指令集 && 基于寄存器的指令集
java采用的是基于棧的指令集,這種指令集依賴操作數(shù)棧進行工作
優(yōu)點:
可移植:由于寄存器是由硬件直接提供的,所以程序如果依賴寄存器不可避免的會受到硬件的約束
程序代碼緊湊
編譯器實現(xiàn)簡單
缺點:
速度慢
指令數(shù)量多:完成相同功能所需的指令比寄存器架構(gòu)多,因為光是入棧、出棧就已經(jīng)很多指令了
內(nèi)存訪問多:頻繁的棧訪問意味著頻繁的內(nèi)存訪問,而對于處理器來說,內(nèi)存始終是速度的瓶頸。
Java內(nèi)存溢出異常
內(nèi)存溢出
堆上無內(nèi)存可完成實例分配且堆無法擴展時:java.lang.OutOfMemoryError: Java heap space
方法區(qū)以及內(nèi)存的常量池?zé)o法滿足內(nèi)存分配需求時:java.lang.OutOfMemoryError: PermGen space
棧擴展時無法申請足夠內(nèi)存:java.lang.StackOverflowError
內(nèi)存泄漏
代碼設(shè)計引起的程序動態(tài)分配的內(nèi)存沒有釋放,導(dǎo)致該部分內(nèi)存不可用
內(nèi)存溢出與內(nèi)存泄漏的區(qū)別
內(nèi)存泄漏是導(dǎo)致內(nèi)存溢出的原因之一,內(nèi)存泄漏積累起來就會導(dǎo)致內(nèi)存溢出
內(nèi)存泄漏可以通過完善代碼來解決,內(nèi)存溢出無法徹底避免,只能通過配置來減少發(fā)生的頻率
內(nèi)存泄漏內(nèi)存溢出的檢查
性能監(jiān)測工具:
JProfiler
Optimizeit Profiler
Eclipse Memory Analyzer
EclipseMAT
JProbe
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。