1. 程式人生 > >Java虛擬機系列之Java內存結構簡介

Java虛擬機系列之Java內存結構簡介

內存空間 指示器 私有 以及 並且 內存區域 在服務器 規範 基礎

本文我們將講解Java虛擬機中各個區域以及各個區域的作用。

一.程序計數器
什麽是程序計數器,有什麽作用?
程序技術器是一塊比較小的內存區域,主要當做是線程中所執行的字節碼的行號指示器,字節碼解釋器工作時就是通過改變這個計數器的值來選取下一個執行的字節碼命令,分支、循環、跳轉等基礎功能都是依賴這個程序計數器來完成。

有什麽特點?
Java虛擬機中的多線程是通過線程輪流切換分配處理器執行時間的方式來實現的,所以為了線程切換後能恢復到正確的執行位置,每條線程都需要一個獨立的程序計數器,各條線程之間計數器互不影響,獨立存儲,所以是線程私有的。

註意:
如果線程執行的是Java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令的地址;如果正在執行的是Native方法,這個計數器的值為空,此內存區域是唯一一個在Java虛擬機規範中沒有規定任何OutOfMemory的情況的區域

二.Java虛擬機棧
Java虛擬機棧是幹嘛的?
Java虛擬機棧描述的是Java內存模型,每個方法在執行的同時會創建一個棧幀用於存儲局部變量表、操作數棧、動態鏈接、方法返回地址等信息。每一個方法從調用到執行結束對應著一個棧幀在虛擬機棧中入棧出棧的過程。

有什麽特點?
Java虛擬機棧是線程私有的,而且生命周期和線程相同。

註意:
如果線程請求的棧的深度大於虛擬機所允許的深度,將拋出StackOverFlowError異常;如果虛擬機棧可以動態擴展,如果擴展時無法申請到足夠多的內存,就會拋出OutOfMemoryError異常。

三.本地方法棧
與虛擬機棧發揮的功能類似,區別不過是虛擬機棧為虛擬機執行Java方法,本地方法棧為虛擬機用到的Native方法服務。本地方法棧也會拋出StackOverFlowError和OutOfMemoryError異常。

四.Java堆
什麽是Java堆,有什麽作用?
Java堆是Java虛擬機中所管理內存中最大的,是所有線程共享的一塊內存區域,在虛擬機啟動的時候創建,目的是存放對象實例。

有什麽特點?
幾乎所有的對象實例都在這裏分配內存,因此這也是垃圾收集器管理最主要的區域,而且Java堆可以處於物理不連續的內存空間,只要邏輯連續即可

1、Java堆中還細分新生代和老年代,然後新生代中又分為Eden區域、From Survivor空間、To Survivor空間等。

2、這裏的Java堆的垃圾回收算法是使用了分代收集算法,即新生代中使用“復制”算法,而老年代中使用“標記-清理”算法或“標記-整理”算法。

註意:
當前主流虛擬機都是可擴展來實現的(通過-Xms和-Xmx來控制),如果堆中沒有內存完成實例,並且堆也無法再擴展時,會拋出OutOfMemoryError異常。

五.方法區
方法區的作用是什麽?
方法區是各個線程共享的內存區域,用於存儲已被虛擬機加載的類信息、常量、靜態變量、即使編譯器編譯後的代碼等數據。

為啥說方法區不等價於永久區?
方法區不等價於永久代,只是HotSpot虛擬機的設計團隊選擇把GC分代收集擴展至方法區,是為了HotSpot垃圾收集器可以像管理Java堆一樣管理這部分內存,能夠省去專門為方法區編寫內存管理代碼的工作,但是這樣也會更容易造成內存溢出的問題(永久代可以用-XX:MaxPermSize設置上限),所以在JDK1.7的HotSpot已經把永久代的字符串常量池移出,移到了Java Heap區,可在 《深入解析String#intern》 了解

運行時常量池有什麽作用?
運行時常量池也是方法區的一部分,用於存放編譯期生成的各種字面量和符號引用,這部分將在類加載後進入方法區的運行時存放。

運行時常量池的特點?
Java虛擬機對Class文件每一部分的格式都有嚴格規定,每一個字節用於存儲哪種數據都必須符合規範上的要求才會被虛擬機認可、裝載和執行,然而對於運行時常量池卻沒做任何要求
運行時常量具有動態性,可以在運行期間將新的常量放入池中,比如String的intern()方法
六.直接內存
直接內存是Java虛擬機的內存嗎?
直接內存並不是虛擬機運行時數據區的一部分,也不是Java虛擬機規範定義的內存區域,是使用本機的內存,又名堆外內存。

怎麽在Java中使用堆外內存?
在JDK1.4中的NIO類,引入了基於通道(Channel)與緩沖區(Buffer)的I/O方式,可以使用Native函數庫來直接分配堆外內存,然後在Java堆中使用DirectByteBuffer對象來作為這塊內存的引用進行操作。

註意:
雖然堆外內存不受Java堆大小的管理,但是受本機總內存以及處理器尋址空間的限制。在服務器管理員配置虛擬機參數的時候,可以通過-Xmx等來配置Java虛擬機最大內存,但經常忽略直接內存,導致各個內存區域總和大於物理內存限制,導致OutOfMemoryError異常。

如果本文有什麽疑問或者是錯誤,歡迎指出留言,互相學習

Java虛擬機系列之Java內存結構簡介