Java虛擬機-1-JVM內存分佈

一、JVM內存分佈

1、JVM內存模型

JVM內存模型主要包括:類加載器,運行時數據區域,本地方法庫、本地方法接口,執行引擎和垃圾回收器

運行時數據區域主要包括:【線程獨享】:虛擬機棧、本地方法棧、程序計數器,【線程共享】:堆、方法區

2、類加載器

類加載器用於懶加載字節碼文件(.class文件),爲程序執行做準備

如果程序執行某個行爲所需要的類還沒有被加載到內存當中,則會經過三個步驟來完成類的初始化

  1. 加載:加載字節碼文件到內存當中
  2. 連接
    1. 驗證:字節碼文件是否有正確的結構
    2. 準備:分配類的一些信息到內存區域
    3. 解析:將類的二進制數據中的符號引用替換爲直接引用
  3. 初始化:創建對象的實例

JVM的類加載器分爲

  1. BootstrapClassLoader(啓動類加載器):加載JRE運行時類,位於$JAVA_HOME/jre/lib/rt.jar
  2. ExtClassLoader(擴展類加載器):加載JRE擴展類,位於$JAVA_HOME/jre/lib/ext目錄下
  3. AppClassLoader(應用程序類加載器):加載Java程序的類
  4. User ClassLoader(自定義加載器)

雙親委派模型:當類加載器加載類時,先嚐試由父類加載器加載,如果父類加載器無法完成,則再由子類加載器來完成

沙箱安全機制:由於雙親委派模型的存在,所以我們無法自己創建類似於JDK自帶的類(全類名完全相同)

雙親委派模型的破壞:Apache Tomcat是一個Web容器,用於部署Web應用,它就破壞了雙親委派模型,把類的加載直接交給Web應用類加載器(WebappClassLoader)來完成,如果Web應用類加載器(WebappClassLoader)無法完成,再由通用類加載器(CommonClassLoader)來完成。這樣做的目的主要是爲了保證每一個Web應用都是相互獨立的,不會因爲依賴着相同的類(全類名),而版本的不同造成混亂

Tomcat的類加載器分爲

  1. BootstrapClassLoader:加載基本的JVM環境的類,位於$JAVA_HOME/lib目錄下
  2. SystemClassLoader:加載Tomcat的啓動類,位於$CATALINA_HOME/bin目錄下
  3. CommonClassLoader:加載Tomcat的通用類,位於$CATALINA_HOME/lib目錄下
  4. WebappClassLoader:加載Web應用的類,位於WEB-INF/lib目錄和WEB-INF/classes目錄下。僅對當前Web應用可訪問

3、虛擬機棧

Java Stack,主要用於存放基本數據類型和實例對象的引用等

4、本地方法棧

Native Method Stack,和Java Stack類似,爲運行native方法而準備的

5、程序計數器

Program Counter Register,用於保存要執行的下一條指令

6、堆

Heap,主要用於存放對象的實例、數組和字符串常量池等

垃圾回收的主要區域,分爲新生代和老年代,默認比例爲1:2,可以通過修改JVM參數-XX:NewRatio=2來調整

新生代又分爲伊甸園區、from區和to區,默認比例爲8:1:1。可以通過修改JVM參數-XX:SurvivorRatio=8來調整

發生在新生代的GC稱之爲Minor GC,發生在老年代的GC稱之爲Major GC,發生在整個堆的GC稱之爲Full GC(包括對永久代的回收)

7、方法區

Method Area,主要用於存放類的信息(靜態變量、構造方法、方法聲明等)和運行時常量池(常量等)等

JVM規範將方法區描述爲堆的一個邏輯部分,但是它卻有一個別名叫做Non-Heap(非堆),目的是和堆區分開來

在HotSpot虛擬機上,方法區又被稱之爲永久代(Permanent Generation),這僅僅是因爲HotSpot用永久代來實現方法區而已,在其他虛擬機上(BEA JRockit、IBM J9等)來說,是不存在永久代的概念的。但是這種實現做法容易遇到內存溢出的問題(OOM),可以通過修改JVM參數 [JDK7]-XX:PermSize=???-XX:MaxPermSize=???[JDK8]-XX:MetaspaceSize=???-XX:MaxMetaspaceSize=???來調整

發佈了155 篇原創文章 · 獲贊 89 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章