深入jvm虚拟机第4版_深入理解JVM虚拟机
自動(dòng)內(nèi)存管理機(jī)制
Java虛擬機(jī)原理
所謂虛擬機(jī),就是一臺(tái)虛擬的機(jī)器。他是一款軟件,用來(lái)執(zhí)行一系列虛擬計(jì)算指令,大體上虛擬機(jī)可以分為
系統(tǒng)虛擬機(jī)和程序虛擬機(jī), 大名鼎鼎的Visual Box、Vmare就屬于系統(tǒng)虛擬機(jī),他們完全是對(duì)物理計(jì)算的仿真,
提供了一個(gè)可以運(yùn)行完整操作系統(tǒng)的軟件平臺(tái)。
程序虛擬機(jī)典型代碼就是Java虛擬機(jī),它專門(mén)為執(zhí)行單個(gè)計(jì)算程序而計(jì)算,在Java虛擬機(jī)中執(zhí)行的指令我們成為Java
自己碼指令。無(wú)論是系統(tǒng)虛擬機(jī)還是程序虛擬機(jī),在上面運(yùn)行的軟件都被限制于虛擬機(jī)提供的資源中。
Java發(fā)展至今,出現(xiàn)過(guò)很多虛擬機(jī),做初Sun使用的一款叫ClassIc的Java虛擬機(jī),到現(xiàn)在引用最廣泛的是HotSpot虛擬
機(jī),除了Sum意外,還有BEA的Jrockit,目前Jrockit和HostSopt都被oralce收入旗下,大有整合的趨勢(shì)。
Java內(nèi)存結(jié)構(gòu)
1、類加載子系統(tǒng):負(fù)責(zé)從文件系統(tǒng)或者網(wǎng)絡(luò)加載Class信息,加載的信息存放在一塊稱之方法區(qū)的內(nèi)存空間。
2、方法區(qū):就是存放類的信息、常量信息、常量池信息、包括字符串字面量和數(shù)字常量等。
3、Java堆:在Java虛擬機(jī)啟動(dòng)的時(shí)候建立Java堆,它是Java程序最主要的內(nèi)存工作區(qū)域,幾乎所有的對(duì)象實(shí)例都存放到
Java堆中,堆空間是所有線程共享。
4、直接內(nèi)存:JavaNio庫(kù)允許Java程序直接內(nèi)存,從而提高性能,通常直接內(nèi)存速度會(huì)優(yōu)于Java堆。讀寫(xiě)頻繁的場(chǎng)合可能會(huì)考慮使用。
5、每個(gè)虛擬機(jī)線程都有一個(gè)私有棧,一個(gè)線程的Java棧在線程創(chuàng)建的時(shí)候被創(chuàng)建,Java棧保存著局部變量、方法參數(shù)、同事Java的方法調(diào)用、
返回值等。
6、本地方法棧,最大不同為本地方法棧用于本地方法調(diào)用。Java虛擬機(jī)允許Java直接調(diào)用本地方法(通過(guò)使用C語(yǔ)言寫(xiě))
7、垃圾收集系統(tǒng)是Java的核心,也是不可少的,Java有一套自己進(jìn)行垃圾清理的機(jī)制,開(kāi)發(fā)人員無(wú)需手工清理,下一節(jié)課詳細(xì)講。
8、PC(Program Couneter)寄存器也是每個(gè)線程私有的空間, Java虛擬機(jī)會(huì)為每個(gè)線程創(chuàng)建PC寄存器,在任意時(shí)刻,
一個(gè)Java線程總是在執(zhí)行一個(gè)方法,這個(gè)方法稱為當(dāng)前方法,如果當(dāng)前方法不是本地方法,PC寄存器總會(huì)執(zhí)行當(dāng)前正在被執(zhí)行的指令,
如果是本地方法,則PC寄存器值為Underfined,寄存器存放如果當(dāng)前執(zhí)行環(huán)境指針、程序技術(shù)器、操作棧指針、計(jì)算的變量指針等信息。
9、虛擬機(jī)核心的組件就是執(zhí)行引擎,它負(fù)責(zé)執(zhí)行虛擬機(jī)的字節(jié)碼,一般戶先進(jìn)行編譯成機(jī)器碼后執(zhí)行。
堆、棧、方法區(qū)概念區(qū)別
Java堆
堆內(nèi)存用于存放由new創(chuàng)建的對(duì)象和數(shù)組。在堆中分配的內(nèi)存,由java虛擬機(jī)自動(dòng)垃圾回收器來(lái)管理。在堆中產(chǎn)生了一個(gè)數(shù)組或者對(duì)象后,還可以在棧中定義一個(gè)特殊的變量,這個(gè)變量的取值等于數(shù)組或者對(duì)象在堆內(nèi)存中的首地址,在棧中的這個(gè)特殊的變量就變成了數(shù)組或者對(duì)象的引用變量,以后就可以在程序中使用棧內(nèi)存中的引用變量來(lái)訪問(wèn)堆中的數(shù)組或者對(duì)象,引用變量相當(dāng)于為數(shù)組或者對(duì)象起的一個(gè)別名,或者代號(hào)。
根據(jù)垃圾回收機(jī)制的不同,Java堆有可能擁有不同的結(jié)構(gòu),最為常見(jiàn)的就是將整個(gè)Java堆分為
新生代和老年代。其中新聲帶存放新生的對(duì)象或者年齡不大的對(duì)象,老年代則存放老年對(duì)象。
新生代分為den區(qū)、s0區(qū)、s1區(qū),s0和s1也被稱為from和to區(qū)域,他們是兩塊大小相等并且可以互相角色的空間。
絕大多數(shù)情況下,對(duì)象首先分配在eden區(qū),在新生代回收后,如果對(duì)象還存活,則進(jìn)入s0或s1區(qū),之后每經(jīng)過(guò)一次
新生代回收,如果對(duì)象存活則它的年齡就加1,對(duì)象達(dá)到一定的年齡后,則進(jìn)入老年代。
Java棧
Java棧是一塊線程私有的空間,一個(gè)棧,一般由三部分組成:局部變量表、操作數(shù)據(jù)棧和幀數(shù)據(jù)區(qū)
局部變量表:用于報(bào)錯(cuò)函數(shù)的參數(shù)及局部變量
操作數(shù)棧:主要保存計(jì)算過(guò)程的中間結(jié)果,同時(shí)作為計(jì)算過(guò)程中的變量臨時(shí)的存儲(chǔ)空間。
幀數(shù)據(jù)區(qū):除了局部變量表和操作數(shù)據(jù)棧以外,棧還需要一些數(shù)據(jù)來(lái)支持常量池的解析,這里幀數(shù)據(jù)區(qū)保存著
訪問(wèn)常量池的指針,方便計(jì)程序訪問(wèn)常量池,另外當(dāng)函數(shù)返回或出現(xiàn)異常時(shí)賣(mài)虛擬機(jī)子必須有一個(gè)異常處理表,方便發(fā)送異常
的時(shí)候找到異常的代碼,因此異常處理表也是幀數(shù)據(jù)區(qū)的一部分。
Java方法區(qū)
Java方法區(qū)和堆一樣,方法區(qū)是一塊所有線程共享的內(nèi)存區(qū)域,他保存系統(tǒng)的類信息。
比如類的字段、方法、常量池等。方法區(qū)的大小決定系統(tǒng)可以保存多少個(gè)類。如果系統(tǒng)
定義太多的類,導(dǎo)致方法區(qū)溢出。虛擬機(jī)同樣會(huì)拋出內(nèi)存溢出的錯(cuò)誤。方法區(qū)可以理解
為永久區(qū)。
虛擬機(jī)參數(shù)配置
什么是虛擬機(jī)參數(shù)配置
在虛擬機(jī)運(yùn)行的過(guò)程中,如果可以跟蹤系統(tǒng)的運(yùn)行狀態(tài),那么對(duì)于問(wèn)題的故障
排查會(huì)有一定的幫助,為此,在虛擬機(jī)提供了一些跟蹤系統(tǒng)狀態(tài)的參數(shù),使用
給定的參數(shù)執(zhí)行Java虛擬機(jī),就可以在系統(tǒng)運(yùn)行時(shí)打印相關(guān)日志,用于分析實(shí)際
問(wèn)題。我們進(jìn)行虛擬機(jī)參數(shù)配置,其實(shí)就是圍繞著堆、棧、方法區(qū)、進(jìn)行配置。
你說(shuō)下 你熟悉那些jvm參數(shù)調(diào)優(yōu)
堆的參數(shù)配置
-XX:+PrintGC 每次觸發(fā)GC的時(shí)候打印相關(guān)日志
-XX:+UseSerialGC 串行回收
-XX:+PrintGCDetails 更詳細(xì)的GC日志
-Xms 堆初始值
-Xmx 堆最大可用值
-Xmn 新生代堆最大可用值
-XX:SurvivorRatio 用來(lái)設(shè)置新生代中eden空間和from/to空間的比例.
含以-XX:SurvivorRatio=eden/from=den/to
總結(jié):在實(shí)際工作中,我們可以直接將初始的堆大小與最大堆大小相等,
這樣的好處是可以減少程序運(yùn)行時(shí)垃圾回收次數(shù),從而提高效率。
-XX:SurvivorRatio 用來(lái)設(shè)置新生代中eden空間和from/to空間的比例.
設(shè)置最大堆內(nèi)存
參數(shù): -Xms5m -Xmx20m -XX:+PrintGCDetails -XX:+UseSerialGC -XX:+PrintCommandLineFlags
/**
* jvm參數(shù)設(shè)置
*
* @author Administrator
*
*/
public class JvmDemo01 {
public static void main(String[] args) throws InterruptedException {
byte[] b1 = new byte[1 * 1024 * 1024];
System.out.println("分配了1m");
jvmInfo();
Thread.sleep(3000);
byte[] b2 = new byte[4 * 1024 * 1024];
System.out.println("分配了4m");
Thread.sleep(3000);
jvmInfo();
}
/**
* 轉(zhuǎn)換為m
*
* @param maxMemory
* @return
*/
static private String toM(long maxMemory) {
float num = (float) maxMemory / (1024 * 1024);
DecimalFormat df = new DecimalFormat("0.00");// 格式化小數(shù)
String s = df.format(num);// 返回的是String類型
return s;
}
static private void jvmInfo() {
// 最大內(nèi)存
long maxMemory = Runtime.getRuntime().maxMemory();
System.out.println("maxMemory:" + maxMemory +
總結(jié)
以上是生活随笔為你收集整理的深入jvm虚拟机第4版_深入理解JVM虚拟机的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 安卓连接mysql代码_用Eclipse
- 下一篇: storm apache java_Ap