java運(yùn)行時(shí)數(shù)據(jù)區(qū)域和類結(jié)構(gòu)詳解
Java運(yùn)行時(shí)數(shù)據(jù)區(qū)域
java運(yùn)行時(shí)數(shù)據(jù)區(qū)可以分為:方法區(qū)、虛擬機(jī)棧、本地方法棧、堆和程序計(jì)數(shù)器
線程私有:虛擬機(jī)棧、本地方法棧、程序計(jì)數(shù)器
線程共享:方法區(qū)、堆
程序計(jì)數(shù)器
一塊較小的內(nèi)存空間,當(dāng)前線程所執(zhí)行字節(jié)碼的行號(hào)指示器,它是程序控制流的指示器,分支、循環(huán)、跳轉(zhuǎn)、異常處理、線程恢復(fù)等基礎(chǔ)功能都需要依賴這個(gè)計(jì)數(shù)器來(lái)完成。
每條線程都擁有一個(gè)獨(dú)立的程序計(jì)數(shù)器。
Java虛擬機(jī)棧
線程私有的,它的生命周期與線程相同。
每個(gè)方法被執(zhí)行時(shí),java虛擬機(jī)都會(huì)創(chuàng)建一個(gè)棧幀,用于存儲(chǔ) 局部變量表、操作數(shù)棧、動(dòng)態(tài)鏈接、方法出口等信息
動(dòng)態(tài)鏈接:符號(hào)在運(yùn)行中轉(zhuǎn)化為直接引用的過(guò)程,就是動(dòng)態(tài)連接(預(yù)支對(duì)應(yīng)的靜態(tài)連接,是指類加載階段將靜態(tài)的符號(hào)引用轉(zhuǎn)成)。
本地方法棧
作用于java虛擬機(jī)棧類似,不過(guò)作用的是本地的native 方法。
java堆
線程共享的一塊內(nèi)存區(qū)域,用來(lái)存放對(duì)象實(shí)例?!皫缀酢彼械膶?duì)象都分配在堆中。
由于及時(shí)編譯,特別是逃逸分析技術(shù)日益請(qǐng)打,對(duì)象也不一定分配在堆中(可能棧上分配和標(biāo)量替換)。
java堆中可以劃分出多個(gè)線程私有的分配緩沖區(qū)(TLAB)來(lái)提高對(duì)象分配效率,這個(gè)TLAB只保證該線程才能在此分配,但是所有線程都是可以進(jìn)行訪問(wèn)的。
方法區(qū)
線程共享,存放虛擬機(jī)加載的類型信息、常量、靜態(tài)變量、即時(shí)編輯器編譯后的代碼緩存等數(shù)據(jù)。
方法區(qū)的運(yùn)行時(shí)常量池:存放 類加載器中加載Class文件中的常量池表。
java對(duì)象內(nèi)存分配
字節(jié)碼new 指令 -> 檢查常量池 ->類加載器(加載、連接(檢查、準(zhǔn)備、解析)、初始化)
檢查后,就要為新生對(duì)象進(jìn)行內(nèi)存分配了。分配策略:
逃逸分析
分析對(duì)象的作用域是否在本方法中,如果只有在本方法中,那么他可以棧上分配,逃逸分析jdk7以后是默認(rèn)開啟的。
new 的對(duì)象不一定在堆中,他可能在棧上分配和標(biāo)量替換
棧上分配:JVM調(diào)優(yōu)方式之一,方法的對(duì)象如果不逃逸在外,那么它可以分配在棧上,他的生命周期與方法調(diào)用一致,減小GC的壓力。
標(biāo)量替換:如果對(duì)象不存在逃逸,JVM可能不會(huì)創(chuàng)建該對(duì)象,而是將該對(duì)象變量分解成若干個(gè)成員變量所替換,這樣就可以在棧幀或寄存器上分配(不用連續(xù)的空間),jdk7默認(rèn)開啟。標(biāo)量替換優(yōu)先于棧上分配。
TLAB:線程本地分配緩存區(qū)(也是堆中)
Eden中分配內(nèi)存時(shí),如果多個(gè)線程都同時(shí)分配內(nèi)存,會(huì)造成指針碰撞情況,為了提高對(duì)象分配效率,使用TLAB。
線程初始化時(shí),會(huì)申請(qǐng)一點(diǎn)指定大小的內(nèi)存,只提供當(dāng)前線程進(jìn)行內(nèi)存分配,這樣每個(gè)線程都單獨(dú)擁有一個(gè)空間。
TLAB是虛擬機(jī)在堆內(nèi)存的eden劃分出來(lái)的一塊專用空間。
TLAB沒(méi)有沒(méi)有足夠空間來(lái)滿足操作時(shí),需要向當(dāng)前線程重新申請(qǐng)新的TLAB
java類文件結(jié)構(gòu)
class 字節(jié)碼的文件結(jié)構(gòu),嚴(yán)格按照順序記性解析
類型 | 名稱 | 備注 |
---|---|---|
u4 | magic | 魔數(shù),識(shí)別Class文件格式,值為:0XCAFEBABE |
u2 | minor_version | 副版本號(hào) |
u2 | major_version | 主版本號(hào),45-?,JDK13為57,JDK8為52 |
u2 | constant_pool_count | 常量池計(jì)算器 |
cp_info | constant_pool | 常量池,class資源庫(kù) |
u2 | access_flags | 訪問(wèn)標(biāo)志,public、final等9個(gè)標(biāo)志。有16個(gè)標(biāo)志位,每一位標(biāo)識(shí)一種訪問(wèn)標(biāo)志。 |
u2 | this_flags | 類索引,常量池中的索引值 |
u2 | super_class | 父類索引,常量池中的索引值 |
u2 | interfaces_count | 接口計(jì)數(shù)器 |
u2 | interfaces | 接口索引集合,常量池中的索引值 |
u2 | fields_count | 字段個(gè)數(shù) |
field_info | fields | 字段集合, 字段標(biāo)志(public、static等)、字段名常量索引、描述常量索引(類型) |
u2 | methods_count | 方法計(jì)數(shù)器 |
method_info | methods | 方法集合,和字段集合差不多,方法標(biāo)志、方法名索引、方法描述索引(返回類型、方法參數(shù)列表) |
u2 | attributes_count | 附加屬性計(jì)數(shù)器 |
attribute_info | attributes | 附加屬性集合 |
常量池
常量池分為:字面量和符號(hào)引用
字面量:文本字符串、final常量值等
符號(hào)引用:
- 類、接口全限定名
- 字段、方法的名稱和描述符
- 方法句柄和類型
- 動(dòng)態(tài)調(diào)用點(diǎn)和動(dòng)態(tài)常量
常量池項(xiàng)目類型:
屬性表
Class 文件、字段表、方法表都可以攜帶自己的屬性表集合,描述某些場(chǎng)景專有的信息
屬性(部分)有:
比如Code屬性,
類加載機(jī)制
類加載過(guò)程:
加載 -> 鏈接 (驗(yàn)證、準(zhǔn)備、解析) -> 初始化
加載:用類加載器加載字節(jié)碼
驗(yàn)證:驗(yàn)證字節(jié)碼的合法性(滿足約束條件)
準(zhǔn)備:被加載類的靜態(tài)字段分配內(nèi)存
解析:符號(hào)引用解析成實(shí)際引用。
初始化:初始化常量、靜態(tài)類
類加載器:
啟動(dòng)類加載器:加載最基礎(chǔ)的最重要的類,如JRE的lib下的jar包中的類
擴(kuò)展類加載器:他的弗雷是啟動(dòng)類加載器,主要加載相對(duì)次要但又通用的類,如JRE的lib/ext下的jar的類
應(yīng)用類加載器:他的父類是擴(kuò)展類加載器,負(fù)責(zé)加載應(yīng)用程序路徑下的類。(指虛擬機(jī)參數(shù) -cp/-classpath、系統(tǒng)變量 java.class.path或環(huán)境變量 CLASSPATH 所指定的路徑)
同一字節(jié)流經(jīng)過(guò)不同類加載器加載,也會(huì)得到兩個(gè)不同的類。
雙親委派模式:讓父加載器盡量加載
雙親委派模式的破壞:
1)如果上層類加載器加載的類 加載 下層的類加載器加載的類
java引入了上下文類加載器,可以打通弗雷加載器去請(qǐng)求子類加載器加載的行為。如JNDI調(diào)用服務(wù)代碼的時(shí)候。
2)OSGI熱部署,使用網(wǎng)狀的類加載模式。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java線程池隊(duì)列LinkedTransferQueue示例詳解
這篇文章主要為大家介紹了Java線程池隊(duì)列LinkedTransferQueue示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12使用Spring?Cloud?Stream處理事件的示例詳解
Spring?Cloud?Stream?是基于?Spring?Boot?的用于構(gòu)建消息驅(qū)動(dòng)微服務(wù)的框架,本文主要介紹了如何使用?Spring?Cloud?Stream?來(lái)處理事件,需要的可以參考一下2023-06-06SpringBoot基于AbstractRoutingDataSource實(shí)現(xiàn)多數(shù)據(jù)源動(dòng)態(tài)切換
本文主要介紹了SpringBoot基于AbstractRoutingDataSource實(shí)現(xiàn)多數(shù)據(jù)源動(dòng)態(tài)切換,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-05-05深扒Java中POJO、VO、DO、DTO、PO、BO、AO、DAO的概念和區(qū)別以及如何應(yīng)用
po vo bo dto dao 和 pojo 是軟件開發(fā)中經(jīng)常使用的一些概念,用于設(shè)計(jì)和實(shí)現(xiàn)對(duì)象模型,下面將分別解釋這些概念的含義及其在開發(fā)中的應(yīng)用,這篇文章主要給大家介紹了關(guān)于Java中POJO、VO、DO、DTO、PO、BO、AO、DAO的概念和區(qū)別以及如何應(yīng)用的相關(guān)資料,需要的朋友可以參考下2024-08-08基于params、@PathVariabl和@RequestParam的用法與區(qū)別說(shuō)明
這篇文章主要介紹了方法參數(shù)相關(guān)屬性params、@PathVariabl和@RequestParam用法與區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08java統(tǒng)計(jì)漢字字?jǐn)?shù)的方法示例
這篇文章主要介紹了java統(tǒng)計(jì)漢字字?jǐn)?shù)的方法,結(jié)合實(shí)例形式分析了java正則判定、字符串遍歷及統(tǒng)計(jì)相關(guān)操作技巧,需要的朋友可以參考下2017-05-05java數(shù)據(jù)結(jié)構(gòu)與算法之插入算法實(shí)現(xiàn)數(shù)值排序示例
這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)與算法之插入算法實(shí)現(xiàn)數(shù)值排序的方法,結(jié)合簡(jiǎn)單實(shí)例形式分析了插入算法的節(jié)點(diǎn)操作與排序相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2016-08-08IDEA創(chuàng)建SpringBoot的maven項(xiàng)目的方法步驟
這篇文章主要介紹了IDEA創(chuàng)建SpringBoot的maven項(xiàng)目的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04