一、Java 虛擬機(jī)的概念
所謂虛擬機(jī),就是一臺虛擬的機(jī)器,它是一款軟件,用來執(zhí)行一系列虛擬計算機(jī)指令。大體上虛擬機(jī)可以分為系統(tǒng)虛擬機(jī)和程序虛擬機(jī)。Virtual Box、VMWare 就屬于系統(tǒng)虛擬機(jī),它們完全是對物理計算機(jī)的仿真,提供了一個可運(yùn)行完整操作系統(tǒng)的軟件平臺。程序虛擬機(jī)的典型代表就是 Java 虛擬機(jī),它專門為執(zhí)行單個計算機(jī)程序而設(shè)計,在 Java 虛擬機(jī)中執(zhí)行的指令我們稱為 Java 字節(jié)碼指令。
二、Java 虛擬機(jī)的結(jié)構(gòu)
類加載子系統(tǒng)
負(fù)責(zé)從文件系統(tǒng)或者網(wǎng)絡(luò)中加載 Class 信息,加載的信息存放在一塊稱之為方法區(qū)的內(nèi)存空間。方法區(qū)
存放類信息、常量信息、常量池信息,包括字符串字面量和數(shù)字常量等。Java 堆
在 Java 虛擬機(jī)啟動的時候建立 Java 堆,它是 Java 程序最主要的內(nèi)存工作區(qū)域,幾乎所有的對象實(shí)例都存放到 Java 堆中,堆空間是所有線程共享。直接內(nèi)存
Java 的 NIO 庫允許 Java 程序使用直接內(nèi)存,從而提高性能,通常直接內(nèi)存的速度會優(yōu)于 Java 堆,讀寫頻繁的場合可能會考慮使用。Java 棧
每個虛擬機(jī)線程都有一個私有的棧,一個線程的 Java 棧在線程創(chuàng)建的時候被創(chuàng)建,Java 棧中保存著局部變量,方法參數(shù),方法調(diào)用、返回值等。本地方法棧
本地方法棧與 Java 棧非常類似,最大不同是,本地方法棧用于本地方法調(diào)用,Java 虛擬機(jī)運(yùn)行 Java 直接調(diào)用本地方法(通常使用 C 編寫)。垃圾收集系統(tǒng)
PC(Program Counter) 寄存器
PC 寄存器也是每個線程私有的空間,Java 虛擬機(jī)會為每個線程創(chuàng)建 PC 寄存器。在任意時刻,一個 Java 線程總在執(zhí)行一個方法,這個方法被稱為當(dāng)前方法,如果當(dāng)前方法不是本地方法,PC 寄存器就會執(zhí)行當(dāng)前正在被執(zhí)行的指令;如果是本地方法,則 PC 寄存器值為 undefined。寄存器存放如當(dāng)前執(zhí)行環(huán)境指針,程序計數(shù)器,操作棧指針,計算的變量指針等信息。執(zhí)行引擎
虛擬機(jī)最核心的組件就是執(zhí)行引擎了,它負(fù)責(zé)執(zhí)行虛擬機(jī)的字節(jié)碼。
堆、棧、方法區(qū)的區(qū)別與聯(lián)系:
堆解決的是數(shù)據(jù)存儲的問題,即數(shù)據(jù)怎么放,放在哪兒。
棧解決的是程序運(yùn)行的問題,即程序如何運(yùn)行,或者說如何處理數(shù)據(jù)。
方法區(qū)則是輔助堆棧的快永久區(qū)(Perm),解決堆棧信息的產(chǎn)生,是先決條件。
例如,我們創(chuàng)建一個新的對象 User。那么,User 類的一些信息(類信息、靜態(tài)信息都存在于方法區(qū)中);而 User 對象被實(shí)例化出來以后,被存儲到 Java 堆中,一塊內(nèi)存空間;當(dāng)我們?nèi)ナ褂玫臅r候,都是使用 User 對象引用,形如 User user = new User() 這里的 user 就是存放在 Java 棧中的,即 User 真實(shí)對象的一個引用。
根據(jù)垃圾回收機(jī)制的不同,Java 堆有可能擁有不同的結(jié)構(gòu)。最為常見的就是將整個 Java 堆分為新生代和老年代。其中新生代存放新生的或者年齡不大的對象,老年代則存放老年對象。新生代分為 Eden 區(qū)、s0 區(qū)、s1 區(qū),s0 區(qū)、s1 區(qū)是兩塊大小相等且可以互換角色的空間。
Java 棧一塊線程私有的內(nèi)存空間,棧一般由三部分組成:局部變量表、操作數(shù)棧和幀數(shù)據(jù)區(qū)。
Java 方法區(qū)和堆一樣,是一塊所有線程共享的內(nèi)存區(qū)域,它保存系統(tǒng)的類信息,比如類的字段、方法、常量池等。方法區(qū)的大小決定了系統(tǒng)可以保存多少個類,如果系統(tǒng)定義太多的類,會導(dǎo)致方法區(qū)溢出,虛擬機(jī)也會拋出內(nèi)存溢出錯誤。方法區(qū)可以理解為永久區(qū)(Perm)。
三、JVM 參數(shù)
- 堆分配參數(shù)
-XX:+UseSerialGC:配置串行回收期
-Xms:設(shè)置 Java 程序啟動時初始堆大小
-Xmx:設(shè)置 Java 程序能獲得的最大堆大小
-Xmn:設(shè)置新生代的大小。新生代大小一般會設(shè)置為整個堆空間的 1/3 到 1/4 左右。
-XX:SurvivorRatio:設(shè)置新生代中 Eden 區(qū)域和 s0/s1 區(qū)域的比例。
四、垃圾回收及其算法
引用計數(shù)算法
無法處理循環(huán)引用的情況,且每次進(jìn)行加減操作比較浪費(fèi)系統(tǒng)性能。標(biāo)記-清除算法
會產(chǎn)生空間碎片.復(fù)制算法
標(biāo)記壓縮算法
五、垃圾收集器
串行垃圾收集器
并行垃圾收集器
ParallelGC,吞吐量優(yōu)先收集器CMS 收集器
G1 收集器