經過 java -version 可查看 JVM 所處的模式,並能夠經過修改配置文件進行配置,那它們有什麼區別呢?java
Server:-Server 模式啓動時,速度較慢,可是啓動以後,性能更高,適合運行服務器後臺程序程序員
Client:-Client 模式啓動時,速度較快,啓動以後不如 Server,適合用於桌面等有界面的程序數組
理解服務器
當虛擬機發現某個方法或代碼塊的運行特別頻繁時,就會把這些代碼認定爲「熱點代碼」。架構
熱點代碼的分類性能
一個方法只被調用過一次或少許的幾回,可是方法體內部存在循環次數較多的循環體,這樣循環體的代碼也被重複執行屢次,所以這些代碼也應該認爲是「熱點代碼」。優化
上面提到的屢次是一個不具體的詞語,那究竟是多少次才能成爲熱點代碼呢?操作系統
如何檢測熱點代碼線程
判斷一段代碼是不是熱點代碼,是否須要觸發即便編譯,這樣的行爲稱爲熱點探測,熱點探測並不必定知道方法具體被調用了多少次,目前主要的熱點探測斷定方式有兩種:翻譯
缺點:不精確,容易由於由於受到線程阻塞或別的外界因素的影響而擾亂熱點探測
缺點:實現麻煩,須要爲每一個方法創建並維護計數器,不能直接獲取到方法的調用關係
HotSpot使用第二種 - 基於計數器的熱點探測方法。
肯定了檢測熱點代碼的方式,如何計算具體的次數呢?
計數器的種類(兩種共同協做)
當編譯工做完成以後,這個方法的調用入口地址就會被系統自動改爲新的,下一次調用該方法時就會使用已編譯的版本。
字節碼是指日常所瞭解的 .class 文件,Java 代碼經過 javac 命令編譯成字節碼
機器碼和本地代碼都是指機器能夠直接識別運行的代碼,也就是機器指令
字節碼是不能直接運行的,須要通過 JVM 解釋或編譯成機器碼才能運行
此時你要問了,爲何 Java 不直接編譯成機器碼,這樣不是更快嗎?
1. 機器碼是與平臺相關的,也就是操做系統相關,不一樣操做系統能識別的機器碼不一樣,若是編譯成機器碼那豈不是和 C、C++差很少了,不能跨平臺,Java 就沒有那響亮的口號 「一次編譯,處處運行」;
2.之因此不一次性所有編譯,是由於有一些代碼只運行一次,不必編譯,直接解釋運行就能夠。而那些「熱點」代碼,反覆解釋執行確定很慢,JVM 在運行程序的過程當中不斷優化,用JIT編譯器編譯那些熱點代碼,讓他們不用每次都逐句解釋執行;
3.還有一方面的緣由是後文講解的解釋器與編譯器共存的緣由。
爲了提升熱點代碼的執行效率,在運行時,虛擬機將會把這些代碼編譯成與本地平臺相關的機器碼,並進行各類層次的優化,完成這個任務的編譯器稱爲即時編譯器(Just In Time Compiler),簡稱 JIT 編譯器
編譯器:把源程序的每一條語句都編譯成機器語言,並保存成二進制文件,這樣運行時計算機能夠直接以機器語言來運行此程序,速度很快;
解釋器:只在執行程序時,才一條一條的解釋成機器語言給計算機來執行,因此運行速度是不如編譯後的程序運行的快的;
經過javac
命令將 Java 程序的源代碼編譯成 Java 字節碼,即咱們常說的 class 文件。這是咱們一般意義上理解的編譯。
字節碼並非機器語言,要想讓機器可以執行,還須要把字節碼翻譯成機器指令。這個過程是Java 虛擬機作的,這個過程也叫編譯。是更深層次的編譯。(實際上就是解釋,引入 JIT 以後也存在編譯)
此時又有疑惑了,Java 不是解釋執行的嗎?
沒錯,Java 須要將字節碼逐條翻譯成對應的機器指令而且執行,這就是傳統的 JVM 的解釋器的功能,正是因爲解釋器逐條翻譯並執行這個過程的效率低,引入了 JIT 即時編譯技術。
必須指出的是,無論是解釋執行,仍是編譯執行,最終執行的代碼單元都是可直接在真實機器上運行的機器碼,或稱爲本地代碼
附一張圖來理解
編譯原理參考:[深刻分析Java的編譯原理](www.hollischuang.com/archives/23…)
解釋器與編譯器二者各有優點
解釋器:當程序須要迅速啓動和執行的時候,解釋器能夠首先發揮做用,省去編譯的時間,當即執行。
編譯器:在程序運行後,隨着時間的推移,編譯器逐漸發揮做用,把愈來愈多的代碼編譯成本地代碼以後,能夠獲取更高的執行效率。
二者的協做:在程序運行環境中內存資源限制較大時,可使用解釋執行節約內存,反之可使用編譯執行來提高效率。當經過編譯器優化時,發現並無起到優化做用,,能夠經過逆優化退回到解釋狀態繼續執行。
即時編譯器並非虛擬機必需的部分,Java 虛擬機規範並無規定 Java 虛擬機內必需要有即時編譯器的存在,更沒有限定或指導即時編譯器應該如何去實現。
可是,即時編譯器編譯性能的好壞、代碼優化程度的高低倒是衡量一款商用虛擬機優秀與否的最關鍵的指標之一。它也是虛擬機中最核心且最能體現虛擬機技術水平的部分。
在 HotSpot 中,解釋器和 JIT 即時編譯器是同時存在的,他們是 JVM 的兩個組件。對於不一樣類型的應用程序,用戶能夠根據自身的特色和需求,靈活選擇是基於解釋器運行仍是基於 JIT 編譯器運行。HotSpot 爲用戶提供了幾種運行模式供選擇,可經過參數設定,分別爲:解釋模式、編譯模式、混合模式,HotSpot 默認是混合模式,須要注意的是編譯模式並非徹底經過 JIT 進行編譯,只是優先採用編譯方式執行程序,可是解釋器仍然要在編譯沒法進行的狀況下介入執行過程。
產生的緣由:因爲即時編譯器編譯本地代碼須要佔用程序運行時間,要編譯出優化程度更高的代碼,所花費的時間可能更長;並且要想編譯出優化程度更高的代碼,解釋器可能還要替編譯器收集性能監控信息,這對解釋執行的速度也有影響。爲了在程序啓動響應速度與運行效率之間達到最佳平衡,HotSpot 虛擬機啓用分層編譯的策略
分層編譯根據編譯器編譯、優化的規模與耗時,劃分出不一樣的編譯層次:
Java 程序員有一個共識,以編譯方式執行本地代碼比解釋執行方式更快,之因此有這樣的共識,除去虛擬機解釋執行字節碼時額外消耗時間的緣由外,還有一個重要的緣由就是虛擬機設計團隊幾乎把對代碼的全部優化措施都集中在了即時編譯器中,所以通常來講,即時編譯器產生的本地代碼會比 javac 產生的字節碼更優秀。如下是具備表明性的 HotSpot 虛擬機的即時編譯器在生成代碼時採用的代碼優化技術:
若是能證實一個對象不會逃逸到方法或線程以外,也就是別的方法或線程沒法經過任何途徑訪問到這個對象,則能夠爲這個變量進行一些高效的優化:
按本身理解整理的,知識點順序不知是否合適,還請你們指導。
參考來源:
《深刻理解 Java 虛擬機》