深入理解Java虚拟机——java内存区域与内存溢出异常(一)
Java虛擬機在執(zhí)行Java程序的過程中會把它所管理的內(nèi)存劃分為若干個不同的數(shù)據(jù)區(qū)域。這些區(qū)域都有各自的用途,以及創(chuàng)建和銷毀時間。Java虛擬機所管理的內(nèi)存包括以下幾個運行時數(shù)據(jù)區(qū)域:
1)程序計數(shù)器: 可以看作是當前線程所之行的字節(jié)碼的行號指示器。字節(jié)碼解釋器就是通過改變計數(shù)器的值來選取下一條需要執(zhí)行的字節(jié)碼指令。Java虛擬機的多線程是通過線程輪流切換并分配處理器執(zhí)行時間的方式實現(xiàn)的。在任何一個確定的時刻,一個處理器都只會執(zhí)行一條線程中的指令。因此每個線程都需要一個獨立的程序計數(shù)器。
2)Java虛擬棧:與程序計數(shù)器一樣,也是線程私有的。生命周期和線程相同。
3)本地方法棧:為虛擬機使用到的Native方法服務(wù)。
4)Java堆:Java堆十倍所有線程共享的一塊內(nèi)存區(qū)域,在虛擬機啟動時創(chuàng)建。此內(nèi)存區(qū)域用于存放對象實例。Java堆是垃圾收集器管理的主要區(qū)域。
5)方法區(qū):同樣也是所有線程共享的區(qū)域,用于存儲已被虛擬機加載的數(shù)據(jù)。
6)運行時常量池:是方法區(qū)的一部分。用于存放編譯期生成的各種字面量和符號引用。
7)直接內(nèi)存:
虛擬機遇到一條new指令時,首先將去檢查這個指令的參數(shù)是否能在常量池中定位到一個類的符號引用,并且檢查這個符號引用代表的類是否已經(jīng)被加載、解析和初始化過。如果沒有,則必須先執(zhí)行相應(yīng)的類加載過程。(p45)
線程安全與非線程安全
非線程安全是指多線程操作同一個對象可能會出現(xiàn)問題。而線程安全則是多線程操作同一個對象不會有問題。線程安全必須要使用很多synchronized關(guān)鍵字來同步控制,所以必然會導致性能的降低。所以在使用的時候,如果是多個線程操作同一個對象,那么使用線程安全的Vector;否則,就使用效率更高的ArrayList。
非線程安全!=不安全
對象的內(nèi)存布局
在HotSpot虛擬機中,對象在內(nèi)存中存儲的布局可以分為3塊區(qū)域:對象頭(Header)、示例數(shù)據(jù)(Instance Data)和對齊填充(Padding)。
對象的訪問定位:
1)使用句柄訪問:Java堆中劃分出一塊內(nèi)存作為句柄池,reference中存儲的就是對象的句柄地址。而句柄中包含了對象示例數(shù)據(jù)和類型數(shù)據(jù)各自的具體地址信息;
? 優(yōu)勢:在對象被移動時只會改變句柄中的示例數(shù)據(jù)指針,而reference本身不需要修改。
2)使用直接指針訪問:此時reference中存儲的就是對象地址。
? 優(yōu)勢:速度快,節(jié)省了一次指針定位的時間開銷。
OutOfMemoryError異常:
除了程序計數(shù)器外,虛擬機內(nèi)存的其他幾個運行時區(qū)域都有發(fā)生該異常的可能。
I)Java堆溢出:Java堆用于存儲對象實例
如果線程請求的棧深度大于虛擬機所允許的最大深度,將拋出StackOverflowError異常;
如果虛擬機在擴展時無法申請到足夠的內(nèi)存空間,將拋出OutOfMemoryError異常。
?
?
?
?
?
?
?
?
?
?
?
?
?
? ?轉(zhuǎn)載于:https://www.cnblogs.com/lchzlp/p/7347458.html
總結(jié)
以上是生活随笔為你收集整理的深入理解Java虚拟机——java内存区域与内存溢出异常(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: webpack 配置
- 下一篇: Java IO流及应用(一)