對於吃貨出身又須要保持體重的我,出門必定要帶男票,由於這樣就能夠把見到的好吃的都買給他吃,就當是本身吃了[汗]。偶爾作夢仍是會夢到本身一個角落裏偷吃東西,聽到有腳步聲,擡起頭,大哭起來:「我餓了。」 而後就這樣一直哭醒。前端
做爲程序媛,對於程序的愛好,必須高於對吃的癡迷。雖然這對於吃貨而言很難,但相比減肥都不是難事,由於我已是一名膩害的程序媛了。java
我在作項目的時候,將本身全部涉及到的項目編譯和運行JAVA版本都升級到了1.7。告訴其餘人說:咱們要好好利用JVM升級帶來的免費性能福利。有人跟我說:其實服務器上是1.7啊,只是jenkins部署的時候用的1.6而已。我嘆了口氣,這個問題,要我詳細講的話,我能夠講上兩天,如下是精簡的部分。程序員
你們都知道,JAVA官網下載下來的包安裝后里面有兩個文件夾,一個是JDK(Java Development Kit),這是Java語言的軟件開發工具包(SDK)。另外一個是JRE(Java Runtime Environment),就是JAVA的運行時環境。若是JDK的文件夾是jdk1.7.XXX,那麼相應的JRE的文件夾就是jre7。因此你們提到java版本的時候,有人習慣說java1.7,但還有人習慣說java7。面試
JDK的文件夾裏包含了JRE。因此正常服務器上只安裝JDK。Windows™裏會看到JRE文件夾裏大多數的文件擴展名是DLL(Dynamic Link Library),這是動態連接庫文件。在Windows™中,許多應用程序並非一個完整的可執行文件,而是被分割成一些相對獨立的DLL。一個應用程序可使用多個DLL,一個DLL也可能被不一樣的應用程序使用。而Linux®裏的JRE文件夾下由於是完整的可執行文件,因此文件數會少一些。並且Linux®一切皆文件,因此是沒有擴展名的。數組
看了上面的兩段,累了吧。我累的時候喜歡坐在路邊長椅上一邊喝酸奶(健康不長胖,耶!)一邊看着如花的姑娘們從眼前走過。豐滿的姑娘好似茶花,圓潤可愛;濃妝的姑娘好似曼陀羅,美麗卻有毒,讓人想靠近又不敢靠太近;還有一種會讓人聯想到芍藥的姑娘,秀麗的氣質裏藏不住更美的內在……安全
言歸正傳啦,jenkins部署的時候通常包含兩個步驟:一個是構建(build),還有一個是部署(deploy)。部署就是扔到實際運行服務器上。構建是先將所須要的資源按照指定的連接下載到本地,而後用JDK編譯。那麼用低版本的JDK進行編譯有什麼影響呢?服務器
由於線上是能運行的,咱們就刨去兼容問題不談,只談性能。eclipse
JAVA的編譯期包括前端編譯(將.java文件變成.class文件,.class文件就是字節碼文件啦);提早編譯(AOT ,ahead of time compiler,直接將.java文件編譯成本地機器代碼);運行期編譯(JIT, just in time compiler,把字節碼轉變成機器碼)。而jenkins部署的時候只作了前端編譯。工具
咱們經常使用的前端編譯器:部署的時候用sun的javac,BTW(by the way),javac是純java寫的,有興趣的童鞋能夠研究一下源碼。開發的時候,因爲筆者本人是eclipse的鐵粉兒,用的是 eclipse JDT中的增量式編譯器(ECJ, Eclipse Compiler for Java)。其實javac這類編譯器對代碼的運行效率擊鼓沒有任何優化(在JDK1.3以後,javac的-O優化參數就再也不有意義了)。虛擬機設計團隊把對性能的優化集中到了即時編譯中,這樣可讓那些不是javac產生的class文件也一樣能享受到編譯器優化帶來的好處。性能
好吧,人家說的是對的,jenkins用1.6編譯對性能沒有多大影響。畢竟我大樂視人才輩出,不是隨便一句話就能夠忽悠人家的。可是javac作了許多針對編碼過程的優化措施來改善程序員的編碼風格和提升編碼效率。至關多新生的java語法特性,都是靠編譯器的語法糖(Syntactic Sugar,對功能沒有影響,更方便程序員使用的語法)來實現,而不是依賴虛擬機的底層改進來支持,能夠說,java中即時編譯在運行期的優化過程對於程序運行來講更重要,而前端編譯器在編譯期的優化過程對於程序編碼來講關係更加密切。
JAVA最初是經過解釋器進行解釋執行的,當虛擬機發現某人方法或代碼塊的運行特別頻繁,就會把這些代碼認定爲「熱點代碼」而將它們編譯成本地機器碼,並進行各類層次的優化,完成這個任務的編譯器就是即時編譯器。
即時編譯器也有不一樣的版本,比較經常使用的是HotSpot虛擬器的C1(clientcompiler用來獲取更高的編譯速度),C2(servercompiler獲取更好的編譯質量)編譯器。它是解釋器和編譯器並存,保留解釋器的緣由是,加快啓動時間,當即執行,當運行環境中內存資源限制較大時,解釋器能夠節約內存,解釋器還能夠做爲激進優化的編譯器的「逃生門」(稱爲逆優化Deoptimization),而編譯器能把愈來愈多的代碼編譯成遍地代碼後,獲取更高的執行效率。HotSpot會根據自身版本和宿主機器的性能自動選擇C1仍是C2,用戶也可使用-client或者-server來自行決定。用戶還可使用-Xint強制虛擬機使用解釋模式,也可使用-Xcomp強制編譯模式。
JDK設計團隊幾乎把代碼的全部優化措施都集中在了即時編譯器上,因此通常來講即時編譯器產生的本地代碼會比Javac產生的字節碼更優秀。經常使用的優化技術有:公共子表達式消除,數組邊界檢查消除,方法內聯,逃逸分析。有興趣的童鞋能夠本身研究一下,面試時很加分[勝利].
最開始還提到了提早編譯。提早編譯與即時編譯的基本思想是相同的。在程序執行前生成Java方法的本地代碼,以便在程序運行時直接使用本地代碼。目的在於避免即時編譯器的運行時性能消耗或內存消耗,或者避免解釋程序的早期性能開銷。
有人喜歡拿JAVA和C/C++對比。早期的Java運行時所提供的性能級別遠低於C和C++。可是即時編譯的出現使得現代的JIT編譯器能夠產生於C或C++靜態編譯至關的應用程序性能。可是,JAVA在輸出本地代碼上仍是有一些劣勢。首先,由於即時編譯器運行佔用的是用戶程序的運行時間,具備很大的時間壓力,優化手段也嚴重受制於編譯成本。其次,Java語言是動態的類型安全語言,須要由虛擬機來確保程序不會違反語言的寓意或者訪問非結構化內存。第三,Java語言中雖然沒有virtual關鍵字,可是使用虛方法(多態方法)的頻率卻遠遠大於C和C++語言。這意味着運行時對方法接受者進行多態選擇的頻率要遠遠大於C和C++語言,這加大的優化難度。第四,Java語言是能夠動態擴展的語言,運行時加載新的類可能改變程序類型的繼承關係,編譯器不得不時刻注意並隨着類型的變化而在運行時撤銷或從新進行一些優化。第五,Java語言中對象的內存分配都是在堆上進行的,只有方法中的局部變量才能在棧上分配。可是Java語言的這些性能上的劣勢都是爲了換取開發效率上的優點,動態安全,動態擴展,垃圾回收這些特性都爲Java語言的開發效率作出了很大的貢獻。
小知識:聰明的你已經注意到了文章中Windows™和Linux®的角標。™是trade mark(商業標記)的縮寫。表示此商標正在受理註冊中,尚未取得商標證。®表示商標已經註冊並取得了商標證。
建議:你們在用英文簡寫的時候把簡寫表示的意思都解釋一下,由於一個簡寫有不少意思,讀者們須要用很長的反射弧才能想明白。