爲何要了解Java虛擬機
Java是目前用戶最多,使用最普遍的軟件開發語言之一。java
###Java的優勢程序員
Java在虛擬機層面隱藏了底層技術的複雜性以及機器和操做系統的差別。開發只須要關注具體業務邏輯。數組
###然而凡事都有兩面性。架構
- 某些領域,對程序的性能,穩定性和可拓展性方面都有極高的要求。程序可能10我的使用時徹底正常,可是1000我的同時使用就會緩慢、死鎖,設置崩潰。即便提高硬件也沒法等比例的提高運做性能和併發能力,甚至徹底沒有任何改善。
- 這裏有Java虛擬機的緣由,爲了達到平臺一致性的目的,犧牲了一些與硬件相關的性能特性。若是程序員不瞭解虛擬機的一些技術特性的運行原理,就沒法寫出最適合虛擬機運行和自由化的代碼。
###其實,虛擬機是能夠調優的。並且調優是三類人員必備的併發
- 使用Java技術體系中的中、高級開發人員。
- 系統調優師
- 系統架構師
###Java虛擬機運行時數據區 性能
####程序計數器(Program Counter Register)操作系統
- 它是一塊較小的內存空間,它的做用能夠看作是當先線程所執行的字節碼的信號指示器。
- 每一條JVM線程都有本身的PC寄存器,各條線程之間互不影響,獨立存儲,這類內存區域被稱爲「線程私有」內存
- 在任意時刻,一條JVM線程只會執行一個方法的代碼。該方法稱爲該線程的當前方法(Current Method)
- 若是該方法是java方法,那PC寄存器保存JVM正在執行的字節碼指令的地址
- 若是該方法是native,那PC寄存器的值是undefined。
- 此內存區域是惟一一個在Java虛擬機規範中沒有規定任何OutOfMemoryError狀況的區域。
Java虛擬機棧(Java Virtual Machine Stack)
- 與PC寄存器同樣,Java虛擬機棧也是線程私有的。每個JVM線程都有本身的java虛擬機棧,這個棧與線程同時建立,它的生命週期與線程相同。
- 虛擬機棧描述的是Java方法執行的內存模型:每一個方法被執行的時候都會同時建立一個棧幀(Stack Frame)用於存儲局部變量表、操做數棧、動態連接、方法出口等信息。每個方法被調用直至執行完成的過程就對應着一個棧幀在虛擬機棧中從入棧到出棧的過程。
- 局部變量表所需的內存空間在編譯期間完成分配。
- 若是縣城請求的棧深度大於虛擬機容許的最大深度,將拋出 StackOverflowError異常。
- 當前大部分的JVM均可以動態擴展,可是在嘗試擴展時沒法申請到足夠的內存時,將拋出OutOfMemoryError。
####本地方法棧(Native Method Stack)線程
- 本地方法棧與虛擬機棧做用類似,後者爲虛擬機執行Java方法服務,而前者爲虛擬機用到的Native方法服務。
- 本地方法棧也會拋出StackOverflowError和OutOfMemoryError異常。
####Java堆(Java Heap)對象
-
虛擬機管理的內存中最大的一塊,同時也是被全部線程所共享的,它在虛擬機啓動時建立。生命週期
-
此內存區域的惟一目的就是存放對象實例,幾乎全部的對象實例以及數組都要在這裏分配內存。
-
現代收集器基本都採用分代收集:Java堆還能夠分爲:新生代,老生代,永生代。其中新生代又分爲Eden區,From Survivor區,To Survivor區。
-
Java堆的容量能夠是固定大小,也能夠隨着需求動態擴展(-Xms和-Xmx),並在不須要過多空間時自動收縮。
-
Java堆所使用的內存不須要保證是物理連續的,只要邏輯上是連續的便可。
-
JVM實現應當提供給程序員調節Java 堆初始容量的手段,對於可動態擴展和收縮的堆來講,則應當提供調節其最大和最小容量的手段。
-
若是堆中沒有內存完成實例分配而且堆也沒法擴展,就會拋OutOfMemoryError。
####方法區(Method Area)
-
跟堆同樣是被各個線程共享的內存區域,用於存儲以被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。雖然這個區域被虛擬機規範把方法區描述爲堆的一個邏輯部分,可是它的別名叫非堆,用來與堆作一下區別。
-
方法區在虛擬機啓動的時候建立。
-
方法區的容量能夠是固定大小的,也能夠隨着程序執行的需求動態擴展,並在不須要過多空間時自動收縮。
-
方法區在實際內存空間中能夠是不連續的。
-
當方法區沒法知足內存分配需求時就會拋OutOfMemoryError。