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