JVM

內(nèi)存區(qū)域

程序計數(shù)器、虛擬機棧、本地方法棧這三個是線程私有的;堆、方法區(qū)是線程公有的;

程序計數(shù)器:記錄線程走到字節(jié)碼的哪一行;

虛擬機棧:由棧幀組成,每個棧幀包含局部變量表、操作數(shù)棧、動態(tài)鏈接、方法返回地址,當(dāng)執(zhí)行到一個方法的時候,就會把這個方法以棧幀形式壓入棧

本地方法棧:與虛擬機棧差不多,只不過這個棧是給本地方法用的

堆:堆的垃圾回收算法常用的是分代回收法,所以堆被劃分出新生代,老年代;

方法區(qū): 1.7之前方法區(qū)的實現(xiàn)是永久代,會存儲已被虛擬機加載的 類信息、字段信息、方法信息、常量、靜態(tài)變量、即時編譯器編譯后的代碼緩存等數(shù)據(jù)。****1.8之后方法區(qū)的實現(xiàn)變成了元空間,字符串常量池和靜態(tài)變量等移出到堆內(nèi)存中,其余的(主要是類型信息)被移到了元空間中。

元空間和永久代的區(qū)別就在于永久代會受JVM的總空間大小的限制,而元空間受限制的是內(nèi)存的總大小。

常量池:常量池中主要存放兩類數(shù)據(jù),一是字面量、二是符號引用。

字面量:比如String類型的字符串值或者定義為final類型的常量的值。
符號引用:
1.類或接口的全限定名(包括他的父類和所實現(xiàn)的接口)
2.變量或方法的名稱
3.變量或方法的描述信息
4.this

當(dāng)類的字節(jié)碼被加載到內(nèi)存中后,他的常量池信息就會集中放入到一塊內(nèi)存,這塊內(nèi)存就稱為運行時常量池,并且把里面的符號地址變?yōu)檎鎸嵉刂贰?/strong>

垃圾回收

判斷對象是否能夠回收有兩個辦法:引用計數(shù)法可達性分析

垃圾收集的算法:標(biāo)記-清除、標(biāo)記-整理、標(biāo)記-復(fù)制、分代回收法

分代回收法

在內(nèi)存中,分為新生代,老年代,永久代;這里的永久代也有叫方法區(qū)。新生代又分為Eden區(qū),S0區(qū),和S1區(qū)。一個對象創(chuàng)建,存儲在Eden區(qū),當(dāng)Eden區(qū)滿了,就會觸發(fā)Minor GC,存活的對象將進入S0區(qū),S0區(qū)滿了之后會觸發(fā)Minor GC,清空S0區(qū)內(nèi)存,將存活的對象復(fù)制到S1區(qū);S1滿了也是GC清空到S0。倒來倒去,當(dāng)次數(shù)達到16(可改)次時,會進入老年代;老年代滿了會觸發(fā)Full GC(會stop the world)。再滿就會OOM了。

Full GC用的一般是標(biāo)記整理和標(biāo)記清除算法,所以不會轉(zhuǎn)移,而Minor GC一般用的是標(biāo)記-復(fù)制算法,所以會轉(zhuǎn)移來轉(zhuǎn)移去,同理,如果對象太大,會直接進老年代。

類加載過程

  • 加載:
  1. 通過全類名獲取定義此類的二進制字節(jié)流
  2. 將字節(jié)流所代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)換為方法區(qū)的運行時數(shù)據(jù)結(jié)構(gòu)
  3. 在內(nèi)存中生成一個代表該類的 Class 對象,作為方法區(qū)這些數(shù)據(jù)的訪問入口
  • 驗證:

驗證文件格式、元數(shù)據(jù)、符號引用、字節(jié)碼

  • 準(zhǔn)備:

準(zhǔn)備階段是正式為類變量分配內(nèi)存并設(shè)置類變量初始值的階段,會給類變量一個默認值,不對成員變量做內(nèi)存分配。

從概念上講,類變量所使用的內(nèi)存都應(yīng)當(dāng)在方法區(qū)中進行分配。不過有一點需要注意的是:JDK 7 之前,HotSpot 使用永久代來實現(xiàn)方法區(qū)的時候,實現(xiàn)是完全符合這種邏輯概念的。 而在 JDK 7 及之后,HotSpot 已經(jīng)把原本放在永久代的字符串常量池、靜態(tài)變量等移動到堆中,這個時候類變量則會隨著 Class 對象一起存放在 Java 堆中。

  • 解析:

解析階段是虛擬機將常量池內(nèi)的符號引用替換為直接引用的過程,也就是得到類或者字段、方法在內(nèi)存中的指針或者偏移量。

  • 初始化:
  1. 給靜態(tài)變量賦值,給成員變量分配內(nèi)存,賦值

類加載器

JVM 中內(nèi)置了三個重要的 ClassLoader,除了 BootstrapClassLoader 其他類加載器均由 Java 實現(xiàn)且全部繼承自java.lang.ClassLoader

  1. BootstrapClassLoader(啟動類加載器) :最頂層的加載類,由 C++實現(xiàn),負責(zé)加載 %JAVA_HOME%/lib目錄下的 jar 包和類或者被 -Xbootclasspath參數(shù)指定的路徑中的所有類。
  2. ExtensionClassLoader(擴展類加載器) :主要負責(zé)加載 %JRE_HOME%/lib/ext 目錄下的 jar 包和類,或被 java.ext.dirs 系統(tǒng)變量所指定的路徑下的 jar 包。
  3. AppClassLoader(應(yīng)用程序類加載器) :面向我們用戶的加載器,負責(zé)加載當(dāng)前應(yīng)用 classpath 下的所有 jar 包和類。

雙親委派機制: 自底向上檢查類是否被上層加載器加載,再從最頂向下嘗試加載類

雙親委派機制的好處:

  1. 避免類的重復(fù)加載
  2. 保護Java核心API不被篡改
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容