前言
近幾個月學習了儒猿技術窩的專欄《從 0 開始帶你成為JVM實戰(zhàn)高手》后睁冬,基于課程講解的知識憾股,做了提煉乡数、歸納、擴展,整理出當前文章脆贵。
感謝專欄傳授的知識!專欄中從零開始,一步一圖的方式振坚,加上大量真實線上案例講解,讓我收獲很多斋扰。
一渡八、內(nèi)存區(qū)域整體介紹
1 JDK1.7至JDK1.8的內(nèi)存區(qū)域演變
主要改變
元數(shù)據(jù)空間取代了方法區(qū),方法區(qū)是在虛擬機中传货,而元數(shù)據(jù)空間在本地內(nèi)存中屎鳍。
2 JDK1.8內(nèi)存區(qū)域的詳細劃分
3.代碼執(zhí)行時的完整的流程
示例代碼
執(zhí)行流程
二、內(nèi)存區(qū)域劃分
1 方法區(qū)
JDK1.8以前叫方法區(qū)问裕,1.8以后叫"Metaspace"元數(shù)據(jù)空間.
(1)是否線程共享
線程共享辟拷。
(2)功能
存放已被虛擬機加載的類信息、常量掐隐、靜態(tài)變量、即時編譯器編譯后的代碼等數(shù)據(jù)卖宠。
(3)JDK1.8的改動
JDK1.8后,元空間替換了永久代忧饭,
主要改動
元空間使用的是本地內(nèi)存扛伍,即不在JVM內(nèi)存區(qū)域中。
字符串常量由永久代轉移到堆中
和永久代相關的JVM參數(shù)已移除
可參考:
Metaspace 之一:Metaspace整體介紹(永久代被替換原因词裤、元空間特點刺洒、元空間內(nèi)存查看分析方法)【非常好的文章】
2 程序計數(shù)器
(1)線程是否共享
線程獨享
(2)功能
JAVA代碼會被翻譯成字節(jié)碼,對應各種字節(jié)碼指令吼砂。
如果線程正在執(zhí)行一個JAVA方法逆航,計數(shù)器記錄當前線程執(zhí)行到了哪一條字節(jié)碼指令;
如果是正在執(zhí)行的是Native方法渔肩,計數(shù)器的值為Undefined因俐。
此內(nèi)存區(qū)域是唯一一個在JAVA虛擬機規(guī)范中沒有規(guī)定任何OutOfMemoryError情況的區(qū)域。
3 JAVA虛擬機棧
3.1 整體介紹
(1) 是否線程共享
線程獨享
(2) 功能
每當線程啟動的時候周偎,就會分配一個Java虛擬機棧抹剩。
(3) JAVA虛擬機棧作用
執(zhí)行方法時,會給方法創(chuàng)建棧幀然后入棧栏饮,在棧幀里存放這個方法對應的局部變量之類的數(shù)據(jù)吧兔。
方法執(zhí)行完后,方法對應的棧幀從虛擬機棧中出棧袍嬉。(后面再深入學習入棧境蔼、出棧)
(4) 可能發(fā)生的錯誤
StackOverflowError: 線程請求的棧深度大于虛擬機所允許的深度,JDK1.8默認棧最大大小是1M伺通。
OutOfMemoryError: 如果虛擬機椆客粒可以動態(tài)擴展,而擴展時無法申請到足夠的內(nèi)存罐监。(后面再深入學這兩個Error)
3.1 棧幀
(1) 功能
線程執(zhí)行了一個方法吴藻,會對這個方法調(diào)用創(chuàng)建對應的一個棧幀。
棧幀里包含這個方法的局部變量表弓柱、操作樹棧沟堡、動態(tài)鏈接、方法出口矢空。
局部變量表:存放了編譯期可知的各種基本類型(int航罗、float等)、對象引用(指向堆內(nèi)存的地址)屁药、returnAddress類型(指向了一條字節(jié)碼指令的地址)粥血。
示例代碼中main線程執(zhí)行時的虛擬機棧內(nèi)存情況:
4 JAVA堆內(nèi)存
(1) 是否線程共享
線程共享。
(2) 功能
主要存放對象實例和數(shù)組。
可以物理上不連續(xù)复亏,但邏輯上要連續(xù)趾娃。
局部變量表的局部變量指向堆內(nèi)存的對象:
(3) 創(chuàng)建的對象在堆內(nèi)存中占用多少內(nèi)存?
一個對象對堆內(nèi)存空間的占用缔御,大致分為兩塊:
(1)對象自己本身的一些信息
比如對象頭抬闷,在64位的Linux操作系統(tǒng)上,會占用16個字節(jié)刹淌。
(2)對象的實例變量作為數(shù)據(jù)占用的空間
各個實例變量占用的內(nèi)存饶氏,例如int類型占用4個字節(jié)讥耗,long類型占用8個字節(jié)有勾。還有數(shù)組、Map之類的會占用更多內(nèi)存古程。
5 本地方法棧
5.1 整體介紹
(1) 是否線程共享
線程獨享
(2) 功能
本地方法棧是為虛擬機使用到的Native方法服務蔼卡。Java虛擬機棧是為執(zhí)行Java方法(也就是字節(jié)碼)服務。
(3) 可能發(fā)生的錯誤
和虛擬機棧一樣挣磨,也會有StackOverflowError和OutOfMemoryError錯誤雇逞。
6 直接內(nèi)存
(1) 是否線程共享
線程共享
(2) 功能
為虛擬機運行時數(shù)據(jù)區(qū)的部分。
在JDK1.4中新加入NIO(New Input/Output)類茁裙,引入了一種基于通道(Channel)和緩存(Buffer)的I/O方式塘砸,它可以使用Native函數(shù)庫直接分配堆外內(nèi)存,然后通過一個存儲在Java堆中的DirectByteBuffer對象作為這塊內(nèi)存的引用進行操作晤锥。
Netty框架就是使用了直接內(nèi)存掉蔬。
(3) 作用
可以避免在Java堆和Native堆中來回的耗時操作。
(4) 可能發(fā)生的錯誤
OutOfMemoryError: 會受到本機內(nèi)存限制矾瘾,如果內(nèi)存區(qū)域總和大于物理內(nèi)存限制從而導致動態(tài)擴展時出現(xiàn)該異常女轿。
參考:
Java虛擬機(JVM)你只要看這一篇就夠了! https://blog.csdn.net/qq_41701956/article/details/81664921