序言html
轉載請聲明,轉自【http://www.javashuo.com/article/p-bkfkxpsc-er.html】,謝謝!java
筆者從事Anroid開發有些年頭了,深知掌握Anroid性能優化方面的知識的必要性,這是一個程序員必須修煉的內功。在面試中,它是面試官的摯愛,在工做中,它是代碼質量的攔路虎,其重要性可見一斑。在團隊中,性能優化的工做又每每由經驗豐富的老師傅來完成,可見要作好性能優化,毫不是一件容易的事情。android
性能優化方面涉及的知識點比較廣,有理論基礎知識,也有實際操做技能,筆者將經過一系列的文章來進行整理,將主要包括Java虛擬機、內存分配、垃圾回收,android虛擬機、進程管理、內存優化、內存泄漏,經常使用內存分析及優化工具介紹等。因爲筆者水平和經驗有限,也是在邊研究邊整理,有不當之處,請不吝賜教。程序員
當前系列內容已完成以下篇章:面試
【朝花夕拾】Android性能篇之(二)Java內存分配安全
【朝花夕拾】Android性能篇之(三)Java內存回收性能優化
【朝花夕拾】Android性能篇之(五)Android虛擬機編輯器
【朝花夕拾】Android性能篇之(六)Android進程管理機制
前言
之因此第一篇要先介紹JVM,是由於當前Android開發的主流語言是java,而JVM又是java程序進程生命誕生的地方。JVM就像盤古同樣開天闢地,在機器上開闢了一個虛擬的空間,而後纔有了java生存的土壤。JVM也是中高級程序員,架構師,系統調優師等職位所必需要了解甚至深刻掌握的知識點。固然,本系列的重點是內存及性能上的優化,因此本文只對JVM作必定概略性的講解,不作太深刻的研究。本文主要內容以下:
1、什麼是JVM?
我們這裏借鑑百度百科的解釋:
JVM是Java Virtual Machine 的縮寫,即Java虛擬機,它是一種用於計算設備的規範,經過在實際的計算機上仿真模擬各類計算機功能來實現,能夠簡單理解爲,它是一個在實際計算機中虛構出來的寄生計算機。Java源文件通過編譯器編譯成.class文件(字節碼文件)後,由JVM來執行。JVM擁有一套支持java字節碼文件(.class文件)執行的環境,能夠將.class文件解釋成具體平臺上的機器指令並執行。Java程序只須要生成.class文件,便可以在任何裝有JVM的設備上運行,而不須要理會具體操做系統平臺相關的信息。此時的JVM就像一個翻譯官同樣鏈接鏈接着.class文件和系統平臺。Java的這個特性叫作平臺無關性,實現了「一次編譯,處處運行」,JVM就是實現Java這個功能的大功臣。
2、JDK,JRE,JVM是什麼關係?
以下截圖爲JDK安裝包結構
一、JDK
Java Development Kit 的縮寫,即 Java開發工具包,提供了開發java程序所須要的基本條件。在上圖JDK安裝包截圖的紅色邊框中
二、JRE
Java Runtime Environment的縮寫,即Java運行環境,下圖爲JRE文件夾的內容。注意,JRE是運行環境,而不是開發環境。
三、JVM
執行.class文件。
四、結論
這三者的關係能夠經過下圖(摘自某網站)來理解:JDK包含了JRE,JRE又包含了JVM(對於比較懶得童鞋,能夠先記住這個結論)。圖中提到的Java開發工具,集成有類庫和編譯工具,只需關聯jre便可。
3、JVM的工做
一、Java文件執行流程圖
下圖顯示了JVM在java程序工做流中的位置,能夠結合前面的內容來看。
二、JVM實際工做內容
實際上JVM的執行過程當中,主要作了三個工做:
(1)加載並執行.class文件;
(2)管理並分配內存(推薦閱讀:【朝花夕拾】Android性能篇之(二)Java內存分配);
(3)執行垃圾回收(推薦閱讀:【朝花夕拾】Android性能篇之(三)Java內存回收)。
4、JVM生命週期
一個JVM實例對應一個獨立運行的Java程序,是屬於進程級別的,也有本身的生命週期:
一、啓動
當啓動一個Java程序的時候,就產生了一個JVM實例。咱們還記得Java的入口函數 public static void main(String[] args)嗎?每一個擁有該函數的.class均可以做爲JVM實例運行的起點。
二、運行
main()做爲起點,啓動主線程,其餘任何線程都在該線程中啓動。JVM有兩種線程:User Thread(用戶線程)和Daemon Thread(守護線程:爲用戶線程服務的線程),main()線程爲用戶線程,而守護線程一般由JVM本身使用。
三、消亡
當程序中的全部用戶線程都終止時,JVM纔會退出,守護線程無線程須要服務了,也就跟着退出了歷史的舞臺。若安全管理器容許,程序也可使用Runtime或者System.exit()來退出。
5、JVM架構及工做原理
上圖更詳細地展現了JVM的架構,由圖可知,JVM主要是劃分爲三個子系統 :(1)類加載器子系統 (2)運行時數據區 (3)執行引擎 和Java本地接口、本地方法庫。
一、類加載子系統(Class Loader SubSystem)
Java的動態類加載功能由該子系統處理,當它在運行時(不是編譯時)首次引用一個類時,它加載、連接並初始化該類文件(.class文件)。
(1)加載(Loading)
類的加載在此組件中完成,加載過程主要由下面三個加載器實現:
1)啓動類加載器(BootStrap class Loader)。負責從啓動類路徑中加載類,無非就是rt.jar。這個加載器會被賦予最高優先級。
2)擴展類加載器(Extension class Loader)。負責加載ext目錄(jre\lib)內的類。
3)應用程序類加載器(Application class Loader)。負責加載應用程序級別類路徑,涉及到路徑的環境變量等。
這三個類加載器會遵循委託層次算法(Delegation Hierarchy Algorithm)加載類文件。
(2)連接(Linking)
該過程主要完成如下三個步驟:
1)校驗(Verify)。字節碼校驗器會校驗生成的字節碼是否正確,若是校驗失敗,咱們會獲得校驗錯誤。
2)準備(Prepare)。分配內存並初始化默認值給全部的靜態變量。
3)解析(Resolve)。全部符號內存引用被方法區(Method Area)的原始引用所替代。
(3)初始化(Initialization)
這是類加載的最後階段,這裏全部的靜態變量會賦初始值,而且靜態塊將被執行。
二、運行時數據區(Runtime Data Area)
該部分將在後續的文章(【朝花夕拾】Android性能篇之(二)Java內存分配)中詳細講述,這裏不作贅述。
三、執行引擎(Execution Engine)。
分配給運行時數據區的字節碼將由執行引擎執行,執行引擎讀取字節碼並逐段執行。它包含了以下三個部分:解釋器、編譯器、垃圾回收器。
(1)解釋器(interpreter)。
解釋器可以快速地解釋字節碼,但執行卻很慢。它的一個缺點就是,當一個方法被調用屢次,每次都須要從新解釋。
(2)JIT編譯器。
JIT編譯器消除了解釋器的缺點,執行引擎利用解釋器轉換字節碼,但若是是重複的代碼,則使用JIT編譯器將所有字節碼編譯成本機代碼,本機代碼將直接用於重複的方法調用,這樣提升了系統的性能。它的工做由下面4個工具協同完成:
1)中間代碼生成器。負責生成中間代碼。
2)代碼優化器。負責優化上面生成的中間代碼。
3)目標代碼生成器。負責生成機器代碼或本機代碼。
4)探測器(Profiler)。一個特殊的組件,負責尋找被屢次調用的方法。
(3)垃圾回收器。
蒐集並刪除未引用的對象。能夠經過調用「System.gc()」來觸發垃圾回收,但並不保證會確實進行垃圾回收。JVM的垃圾回收只收集那些由new關鍵字建立的對象。因此,若是不是用new建立的對象,你可使用finalize函數來執行清理。
四、Java本地接口(JNI,Native Method Interface)
JNI會與本地方法庫進行交互並提供執行引擎所需的本地庫。
五、本地方法庫(Native Method Library)
它是一個執行引擎的本地庫集合。
推薦閱讀
最後推薦一本術,周志明著的《深刻理解Java虛擬機——JVM高級特性與最佳實踐》,業內評價很高,口碑很是好。