JAVA虛擬機內存結構及分析

JAVA虛擬機自動化兩大構成,內存動態分配和垃圾收集技術。內存自動分配和GC的相互協作運行,減少JAVA編程內存泄漏和內存溢出的問題。但內存泄漏和內存出,我們也偶爾會碰到。兩者的區別有時怎樣的呢?


內存泄漏和內存溢出的區別?

  • 內存泄漏:程序中動態分配的內存,某些數據或對象,沒有及時得到釋放和回收,沒有足夠的內存空間得到使用。
  • 內存溢出:程序運行過程中,無法申請到足夠的內存。將見OutOrMemoryError:PermGen space 或jJava heap space
  • 內存泄漏是內存溢出的誘因之一,堆棧內存設置的較小,也會造成內存溢出。


曾經部署項目時出現的問題,多個項目部署到同一個Tomcat服務器中,服務器已啓動,就泡了異常OutOrMemoryError:PermGen space 。整個Java相關的服務停擺了,必須通過kill tomcat進程,才能重啓啓動。 再內存足夠的情況下,可以修改Tomcat中的啓動配置,如下:

Linux在Tomcat目錄下/bin/catalina.sh ,vi 編輯,將 JAVA_OPTS='-Xms1024m -Xmx1024m -XX:PermSize=256M -XX:MaxNewSize=512m -XX:MaxPermSize=512m'      添加到最上方



運行時數據區

運行時數據區,也就是JAVA虛擬機在執行Java程序的過程中將其管理的內存劃分爲不同性質的數據區域,各區域分工協作,各司其職。主要包括程序計數器、虛擬機棧、本地方法棧、JAVA堆、方法區(包括運行時常量池)。

數據區域以其生命週期分類兩類:一、線程獨立,與線程生命週期一致(程序計數器、虛擬機棧、本地方法棧),隨線程釋放,不涉及到垃圾回收;二、線程共享——GC垃圾回收管理的重要區域(Java堆和方法區)


1.程序計數器

程序計數器是當前線程所執行的字節碼行號指示器, 內存較小。字節碼解釋器通過程序計數器,循環、跳轉、分支、異常處理、線程恢復等功能的實現依據。唯一規定OutOfMemoryError的內存區域


2.Java 虛擬機棧(局部變量表-基本數據類型,對象引用

虛擬機棧描述的是Java方法執行的內存模型:每個方法在執行的同時都會創建一個棧幀,存儲局部變量表、操作棧、動態鏈接、方法出入口信息。方法執行的過程,也伴隨着棧數據入棧和出棧的過程。

虛擬機棧中存儲了我們熟知的的基本數據類型(boolean,byte,short,int,float,long,double)和對象引用和returnAddress類型的數據。局部變量表所需的內存空間在編譯期間完成分配,所以程序運行這塊內存變化較小。


3.本地方法棧

本地方法棧與JAVA虛擬機棧發揮作用非常相似。Java虛擬機棧爲虛擬機執行Java方法服務,本地方法棧執行Native方法服務。Native方法是指非Java代碼的接口,虛擬機的實現,如HotSpot是通過C,C++和一些彙編語言和java語言編寫而成,所以Native方法跟虛擬機使用何種語言相關


4.JAVA堆(對象實例

JAVA區域唯一的目的是存放對象實例,幾乎所有對象實例存儲在此。JAVA堆是內存最大的一塊,被所有線程共享的內存區域,也是垃圾收集器管理的主要區域。

以內存回收可以將JAVA堆分爲新生代和老年代,方法區又被稱爲持久代。也是對象和相應數據在內存中的生命週期長度。


5.方法區(類信息、常量、靜態變量

方法區用於存儲已被虛擬機記載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據,也是所有線程共享的內存區域。Java虛擬機規範將方法區描述爲堆的一個邏輯部分,但也稱Non-Heap(非堆),爲了與Java堆區分開。在垃圾回收的內存劃分區域中,方法區又稱爲“永久代”,這塊區域內存回收的目標主要是常量池的回收和類的卸載。

5.1運行時常量池(字面量、符號引用

運行時常量池是方法區的一部分,編譯期生成Class文件中的各種字面量和符號引用,將在類加載後進入運行時常量池,以及運行期間產生的新的常量。所以也是運行時常量池具有動態性的表現。


類加載機制:虛擬機將描述類的數據從Class文件加載到內存,對數據進行校驗、轉換解析和初始化,實例化爲被虛擬機直接使用的Java類型對象

類加載將如何對新生對象進行內存的分配呢?

  • 當虛擬機遇到new指令時,首先檢查常量池中是否存在此類的符號引用,以及是否被加載、解析和初始化過。
  • 當類加載檢查通過後,將新生對象分配內存,對象所需內存確定。通過“指針碰撞”或“空閒列表”將其分配和規整。
  • 內存分配完後,虛擬機將分配的內存空間都初始化爲零值


對象的訪問定位?兩種方式(句柄訪問和直接指針)

1.句柄訪問:Java堆中劃分一塊內存作爲句柄池,對象引用(reference)存儲的是對象的句柄地址,句柄中包含對象實例數據與數據類型各自的具體信息。

2.直接指針訪問:對象引用(reference)存儲的是對象地址,必須考慮放置類型數據的相關信息

3.句柄訪問的最大好處reference中存儲的是穩定的句柄地址,直接訪問的最大好處是速度快


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章