1991年4月,由James Gosling主導的團隊創造了Oak語言,java的前身,1995年5月23號,Oak語言改名Java,而且提出那句註明的:」write Once,Run Anywhere」的口號.1996年1月23日,JDK1.0發佈.前端
當時正好遇上瀏覽器快速崛起,發展的浪潮,你們發現java一處編譯處處使用的特性和瀏覽器很契合,同一個頁面不可能每個操做系統我都寫一遍.用如今的話說java正好站在這個風口上.致使它飛速發展纔有了今天的江湖地位.java
JVM是Java Virtual Machine(Java虛擬機)的縮寫,JVM是一種用於計算設備的規範,它是一個虛構出來的計算機,是經過在實際的計算機上仿真模擬各類計算機功能來實現的。Java虛擬機包括一套字節碼指令集、一組寄存器、一個棧、一個垃圾回收堆和一個存儲方法域。 JVM屏蔽了與具體操做系統平臺相關的信息,使Java程序只需生成在Java虛擬機上運行的目標代碼(字節碼),就能夠在多種平臺上不加修改地運行。JVM在執行字節碼時,實際上最終仍是把字節碼解釋成具體平臺上的機器指令執行。程序員
Java語言的一個很是重要的特色就是與平臺的無關性。而使用Java虛擬機是實現這一特色的關鍵。通常的高級語言若是要在不一樣的平臺上運行,至少須要編譯成不一樣的目標代碼。而引入Java語言虛擬機後,Java語言在不一樣平臺上運行時不須要從新編譯。Java語言使用Java虛擬機屏蔽了與具體平臺相關的信息,使得Java語言編譯程序只需生成在Java虛擬機上運行的目標代碼(字節碼),就能夠在多種平臺上不加修改地運行。Java虛擬機在執行字節碼時,把字節碼解釋成具體平臺上的機器指令執行。這就是Java的可以「一次編譯,處處運行」的緣由。面試
咱們先把JVM這個虛擬機畫出來,以下圖所示:算法
從這張圖中咱們能夠看出,JVM是運行在操做系統之上的,它與硬件沒有直接的交互,咱們再來看JVM由哪些部分組成,以下圖所示:編程
一、Class Loader 類加載器瀏覽器
類加載器的做用是加載類文件到內存,好比編寫一個HelloWord.java 程序,而後經過javac 編譯成class 文件,那怎麼才能加載到內存中被執行呢?Class Loader 承擔的就是這個責任,那不可能隨便創建一個.class 文件就能被加載的,Class Loader 加載的class 文件是有格式要求。緩存
Class Loader 只管加載,只要符合文件結構就加載,至於說能不能運行,則不是它負責的,那是由Execution Engine 負責的。安全
二、Execution Engine 執行引擎性能優化
執行引擎也叫作解釋器(Interpreter) ,負責解釋命令,提交操做系統執行。
三、Native Interface 本地接口
本地接口的做用是融合不一樣的編程語言爲Java 所用,它的初衷是融合C/C++ 程序,Java 誕生的時候是C/C++ 橫行的時候,要想立足,必須有一個聰明的、睿智的調用C/C++ 程序,因而就在內存中專門開闢了一塊區域處理標記爲native 的代碼,它的具體作法是Native Method Stack 中登記native 方法,在Execution Engine 執行時加載native libraies 。目前該方法使用的是愈來愈少了,除非是與硬件有關的應用,好比經過Java 程序驅動打印機,或者Java 系統管理生產設備,在企業級應用中已經比較少見,由於如今的異構領域間的通訊很發達,好比可使用Socket 通訊,也可使用Web Service 等等,很少作介紹。
四、 Runtime data area 運行數據區
運行數據區是整個JVM 的重點。咱們全部寫的程序都被加載到這裏,以後纔開始運行,Java 生態系統如此的繁榮,得益於該區域的優良自治。
整個JVM 框架由加載器加載文件,而後執行器在內存中處理數據,須要與異構系統交互是能夠經過本地接口進行,瞧,一個完整的系統誕生了!
全部的數據和程序都是在運行數據區存放,它包括如下幾部分:
一、 Stack 棧
棧也叫棧內存,是Java程序的運行區,是在線程建立時建立,它的生命期是跟隨線程的生命期,線程結束棧內存也就釋放,對於棧來講不存在垃圾回收問題,只要線程一結束,該棧就Over。問題出來了:棧中存的是那些數據呢?又什麼是格式呢?
棧中的數據都是以棧幀(Stack Frame)的格式存在,棧幀是一個內存區塊,是一個數據集,是一個有關方法(Method)和運行期數據的數據集,當一個方法A被調用時就產生了一個棧幀F1,並被壓入到棧中,A方法又調用了B方法,因而產生棧幀F2也被壓入棧,執行完畢後,先彈出F2棧幀,再彈出F1棧幀,遵循「先進後出」原則。
那棧幀中到底存在着什麼數據呢?棧幀中主要保存3類數據:本地變量(Local Variables),包括輸入參數和輸出參數以及方法內的變量;棧操做(Operand Stack),記錄出棧、入棧的操做;棧幀數據(Frame Data),包括類文件、方法等等。光說比較枯燥,咱們畫個圖來理解一下Java棧,以下圖所示:
示在一個棧中有兩個棧幀,棧幀2是最早被調用的方法,先入棧,而後方法2又調用了方法1,棧幀1處於棧頂的位置,棧幀2處於棧底,執行完畢後,依次彈出棧幀1和棧幀2,線程結束,棧釋放。
二、Heap 堆內存
jvm中分爲堆和方法區,**堆**又進一步分爲**新生代和老年代,方法區爲永久代。**
堆中區分的新生代和老年代是爲了垃圾回收,新生代中的對象存活期通常不長,而老年代中的對象存活期較長,因此當垃圾回收器回收內存時,新生代中垃圾回收效果較好,會回收大量的內存,而老年代中回收效果較差,內存回收不會太多。
基於以上特性,新生代中通常採用複製算法,由於存活下來的對象是少數,所須要複製的對象少,而老年代對象存活多,不適合採用複製算法,通常是標記整理和標記清除算法。
由於複製算法須要留出一塊單獨的內存空間來以備垃圾回收時複製對象使用,因此將新生代分爲eden區和兩個survivor區,每次使用eden和一個survivor區,另外一個survivor做爲備用的對象複製內存區。
一個JVM實例只存在一個堆類存,堆內存的大小是能夠調節的。類加載器讀取了類文件後,須要把類、方法、常變量放到堆內存中,以方便執行器執行,堆內存分爲三部分:
Permanent Space 永久存儲區
永久存儲區是一個常駐內存區域,用於存放JDK自身所攜帶的Class,Interface的元數據,也就是說它存儲的是運行環境必須的類信息,被裝載進此區域的數據是不會被垃圾回收器回收掉的,關閉JVM纔會釋放此區域所佔用的內存。
Young Generation Space 新生區
新生區是類的誕生、成長、消亡的區域,一個類在這裏產生,應用,最後被垃圾回收器收集,結束生命。新生區又分爲兩部分:伊甸區(Eden space)和倖存者區(Survivor pace),全部的類都是在伊甸區被new出來的。倖存區有兩個: 0區(Survivor 0 space)和1區(Survivor 1 space)。當伊甸園的空間用完時,程序又須要建立對象,JVM的垃圾回收器將對伊甸園區進行垃圾回收,將伊甸園區中的再也不被其餘對象所引用的對象進行銷燬。而後將伊甸園中的剩餘對象移動到倖存0區。若倖存0區也滿了,再對該區進行垃圾回收,而後移動到1區。那若是1區也滿了呢?再移動到養老區。
Tenure generation space養老區
養老區用於保存重新生區篩選出來的JAVA對象,通常池對象都在這個區域活躍。 三個區的示意圖以下:
三、 Method Area 方法區
方法區是被全部線程共享,該區域保存全部字段和方法字節碼,以及一些特殊方法如構造函數,接口代碼也在此定義。
四、PC Register 程序計數器
每一個線程都有一個程序計數器,就是一個指針,指向方法區中的方法字節碼,由執行引擎讀取下一條指令。
GC (Garbage Collection)的基本原理:將內存中再也不被使用的對象進行回收,GC中用於回收的方法稱爲收集器,因爲GC須要消耗一些資源和時間,Java在對對象的生命週期特徵進行分析後,按照新生代、舊生代的方式來對對象進行收集,以儘量的縮短GC對應用形成的暫停
(1)對新生代的對象的收集稱爲minor GC;
(2)對舊生代的對象的收集稱爲Full GC;
(3)程序中主動調用System.gc()強制執行的GC爲Full GC。
不一樣的對象引用類型, GC會採用不一樣的方法進行回收,JVM對象的引用分爲了四種類型:
(1)強引用:默認狀況下,對象採用的均爲強引用(這個對象的實例沒有其餘對象引用,GC時纔會被回收)
(2)軟引用:軟引用是Java中提供的一種比較適合於緩存場景的應用(只有在內存不夠用的狀況下才會被GC)
(3)弱引用:在GC時必定會被GC回收
(4)虛引用:因爲虛引用只是用來得知對象是否被GC
4、JVM的發展
1.Sun Classic / Exact VM
以今天的視角來看,Sun Classic VM的技術可能很原始,這款虛擬機的使命也早已終結。但僅憑它「世界上第一款商用Java虛擬機」的頭銜,就足夠有讓歷史記住它的理由。
1996年1月23日,Sun公司發佈JDK 1.0,Java語言首次擁有了商用的正式運行環境,這個JDK中所帶的虛擬機就是Classic VM。這款虛擬機只能使用純解釋器方式來執行Java代碼,若是要使用JIT編譯器,就必須進行外掛。可是假如外掛了JIT編譯器,JIT編譯器就徹底接管了虛擬機的執行系統,解釋器便再也不工做了。用戶在這款虛擬機上執行java -version命令,將會看到相似下面這行輸出:
1. java version "1.2.2"
2. Classic VM (build JDK-1.2.2-001, green threads, sunwjit)
Sun的虛擬機團隊努力去解決Classic VM所面臨的各類問題,提高運行效率。在JDK 1.2時,曾在Solaris平臺上發佈過一款名爲Exact VM的虛擬機,它的執行系統已經具有現代高性能虛擬機的雛形:如兩級即時編譯器、編譯器與解釋器混合工做模式等。Exact VM因它使用準確式內存管理(Exact Memory Management,也能夠叫Non-Conservative/Accurate Memory Management)而得名,即虛擬機能夠知道內存中某個位置的數據具體是什麼類型。雖然Exact VM的技術相對Classic VM來講先進了許多,可是在商業應用上只存在了很短暫的時間就被更爲優秀的HotSpot VM所取代,甚至尚未來得及發佈Windows和Linux平臺下的商用版本。而Classic VM的生命週期則相對長了許多,它在JDK 1.2以前是Sun JDK中惟一的虛擬機,在JDK 1.2時,它與HotSpot VM並存,但默認使用的是Classic VM(用戶可用java-hotspot參數切換至HotSpot VM),而在JDK 1.3時,HotSpot VM成爲默認虛擬機,但Classic VM仍做爲虛擬機的「備用選擇」發佈(使用java-classic參數切換),直到JDK 1.4的時候,Classic VM才徹底退出商用虛擬機的歷史舞臺,與Exact VM一塊兒進入了Sun Labs Research VM之中。
2.Sun HotSpot VM**
提起HotSpot VM,相信全部Java程序員都知道,它是Sun JDK和OpenJDK中所帶的虛擬機,也是目前使用範圍最廣的Java虛擬機。但不必定全部人都知道的是,這個目前看起來「血統純正」的虛擬機在最初並不是由Sun公司開發,而是由一家名爲「Longview Technologies」的小公司設計的;甚至這個虛擬機最初並不是是爲Java語言而開發的,它來源於Strongtalk VM,而這款虛擬機中至關多的技術又是來源於一款支持Self語言實現「達到C語言50%以上的執行效率」的目標而設計的虛擬機,Sun公司注意到了這款虛擬機在JIT編譯上有許多優秀的理念和實際效果,在1997年收購了Longview Technologies公司,從而得到了HotSpot VM。
HotSpot VM既繼承了Sun以前兩款商用虛擬機的優勢,也有許多本身新的技術優點,如它名稱中的HotSpot指的就是它的熱點代碼探測技術,HotSpot VM的熱點代碼探測能力能夠經過執行計數器找出最具備編譯價值的代碼,而後通知JIT編譯器以方法爲單位進行編譯。若是一個方法被頻繁調用,或方法中有效循環次數不少,將會分別觸發標準編譯和OSR(棧上替換)編譯動做。經過編譯器與解釋器恰當地協同工做,能夠在最優化的程序響應時間與最佳執行性能中取得平衡,並且無須等待本地代碼輸出才能執行程序,即時編譯的時間壓力也相對減少,這樣有助於引入更多的代碼優化技術,輸出質量更高的本地代碼。
在2006年的JavaOne大會上,Sun公司宣佈最終會把Java開源,並在隨後的一年,陸續將JDK的各個部分(其中固然也包括了HotSpot VM)在GPL協議下公開了源碼,並在此基礎上創建了OpenJDK。這樣,HotSpot VM便成爲了Sun JDK和OpenJDK兩個實現極度接近的JDK項目的共同虛擬機。
在2008年和2009年,Oracle公司分別收購了BEA公司和Sun公司,這樣Oracle就同時擁有了兩款優秀的Java虛擬機:JRockit VM和HotSpot VM。Oracle公司宣佈在不久的未來(大約應在發佈JDK 8的時候)會完成這兩款虛擬機的整合工做,使之優點互補。整合的方式大體上是在HotSpot的基礎上,移植JRockit的優秀特性,譬如使用JRockit的垃圾回收器與MissionControl服務,使用HotSpot的JIT編譯器與混合的運行時系統。
3. Sun Mobile-Embedded VM / Meta-Circular VM
Sun公司所研發的虛擬機可不只有前面介紹的服務器、桌面領域的商用虛擬機,除此以外,Sun公司面對移動和嵌入式市場,也發佈過虛擬機產品,另外還有一類虛擬機,在設計之初就沒抱有商用的目的,僅僅是用於研究、驗證某種技術和觀點,又或者是做爲一些規範的標準實現。這些虛擬機對於大部分不從事相關領域開發的Java程序員來講可能比較陌生。Sun公司發佈的其餘Java虛擬機有:
(1)KVM
KVM中的K是「Kilobyte」的意思,它強調簡單、輕量、高度可移植,可是運行速度比較慢。在Android、iOS等智能手機操做系統出現前曾經在手機平臺上獲得很是普遍的應用。
(2)CDC/CLDC HotSpot Implementation
CDC/CLDC全稱是Connected(Limited)Device Configuration,在JSR-139/JSR-218規範中進行定義,它但願在手機、電子書、PDA等設備上創建統一的Java編程接口,而CDC-HI VM和CLDC-HI VM則是它們的一組參考實現。CDC/CLDC是整個Java ME的重要支柱,但從目前Android和iOS二分天下的移動數字設備市場看來,在這個領域中,Sun的虛擬機所面臨的局面遠不如服務器和桌面領域樂觀。
(3)Squawk VM
Squawk VM由Sun公司開發,運行於Sun SPOT(Sun Small Programmable Object Technology,一種手持的WiFi設備),也曾經運用於Java Card。這是一個Java代碼比重很高的嵌入式虛擬機實現,其中諸如類加載器、字節碼驗證器、垃圾收集器、解釋器、編譯器和線程調度都是Java語言自己完成的,僅僅靠C語言來編寫設備I/O和必要的本地代碼。
(4)JavaInJava
JavaInJava是Sun公司於1997年~1998年間研發的一個實驗室性質的虛擬機,從名字就能夠看出,它試圖以Java語言來實現Java語言自己的運行環境,既所謂的「元循環」(Meta-Circular,是指使用語言自身來實現其運行環境)。它必須運行在另一個宿主虛擬機之上,內部沒有JIT編譯器,代碼只能以解釋模式執行。在20世紀末主流Java虛擬機都未能很好解決性能問題的時代,開發這種項目,其執行速度可想而知。
(5)Maxine VM
Maxine VM和上面的JavaInJava很是類似,它也是一個幾乎所有以Java代碼實現(只有用於啓動JVM的加載器使用C語言編寫)的元循環Java虛擬機。這個項目於2005年開始,到如今仍然在發展之中,比起JavaInJava,Maxine VM就顯得「靠譜」不少,它有先進的JIT編譯器和垃圾收集器(但沒有解釋器),可在宿主模式或獨立模式下執行,其執行效率已經接近了HotSpot Client VM的水平。
4. BEA JRockit / IBM J9 VM
Oracle JRockit (原來的 Bea JRockit)系列產品是一個全面的[Java](https://baike.baidu.com/item/Java/85979)運行時解決方案組合,包括了行業最快的標準Java解決方案。 大量的行業[基準測試](https://baike.baidu.com/item/%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95/5876292)顯示,基本JRockit JVM是世界上最快的[JVM](https://baike.baidu.com/item/JVM/2902369)。JRockit面向延遲敏感型應用的解決方案JRockit Real Time提供以毫秒或微秒級的JVM響應時間,適合財務前端辦公、軍事指揮與控制和電信網絡的須要。使用JRockit產品,客戶已經體驗到了顯著的性能提升(一些超過了70% )和硬件成本的減小(達50%)。
JRockit VM曾經號稱「世界上速度最快的Java虛擬機」它是BEA公司在2002年從Appeal Virtual Machines公司收購的虛擬機。BEA公司將其發展爲一款專門爲服務器硬件和服務器端應用場景高度優化的虛擬機,因爲專一於服務器端應用,它能夠不太關注程序啓動速度,所以JRockit內部不包含解析器實現,所有代碼都靠即時編譯器編譯後執行。除此以外,JRockit的垃圾收集器和MissionControl服務套件等部分的實現,在衆多Java虛擬機中也一直處於領先水平。
IBM J9 VM並非IBM公司惟一的Java虛擬機,不過是目前其主力發展的Java虛擬機。IBM J9 VM本來是內部開發代號,正式名稱是「IBM Technology for Java Virtual Machine」,簡稱IT4J,只是這個名字太拗口了一點,普及程度不如J9。J9 VM最初是由IBM Ottawa實驗室一個名爲SmallTalk的虛擬機擴展而來的,當時這個虛擬機有一個bug是由8k值定義錯誤引發的,工程師花了很長時間終於發現並解決了這個錯誤,此後這個版本的虛擬機就稱爲K8了,後來擴展出支持Java的虛擬機就被稱爲J9了。與BEA JRockit專一於服務器端應用不一樣,IBM J9的市場定位與Sun HotSpot比較接近,它是一款設計上從服務器端到桌面應用再到嵌入式都全面考慮的多用途虛擬機,J9的開發目的是做爲IBM公司各類Java產品的執行平臺,它的主要市場是和IBM產品(如IBM WebSphere等)搭配以及在IBM AIX和z/OS這些平臺上部署Java應用。
5. Azul VM / BEA Liquid VM
咱們平時所說起的「高性能Java虛擬機」通常是指HotSpot、JRockit、J9這類在通用平臺上運行的商用虛擬機,但其實Azul VM和BEA Liquid VM這類特定硬件平臺專有的虛擬機纔是「高性能」的武器。
Azul VM是Azul Systems 公司在HotSpot基礎上進行大量改進,運行於Azul Systems公司的專有硬件Vega系統上的Java虛擬機,每一個Azul VM實例均可以管理至少數十個CPU和數百GB內存的硬件資源,並提供在巨大內存範圍內實現可控的GC時間的垃圾收集器、爲專有硬件優化的線程調度等優秀特性。在2010年,Azul Systems公司開始從硬件轉向軟件,發佈了本身的Zing JVM,能夠在通用x86平臺上提供接近於Vega系統的特性。
Liquid VM便是如今的JRockit VE(Virtual Edition),它是BEA公司開發的,能夠直接運行在自家Hypervisor系統上的JRockit VM的虛擬化版本,Liquid VM不須要操做系統的支持,或者說它本身自己實現了一個專用操做系統的必要功能,如文件系統、網絡支持等。由虛擬機越過通用操做系統直接控制硬件能夠得到不少好處,如在線程調度時,不須要再進行內核態/用戶態的切換等,這樣能夠最大限度地發揮硬件的能力,提高Java程序的執行性能。
6. Apache Harmony / Google Android Dalvik VM
Harmony VM和Dalvik VM只能稱作「虛擬機」,而不能稱作「Java虛擬機」,可是這兩款虛擬機(以及所表明的技術體系)對最近幾年的Java世界產生了很是大的影響和挑戰,甚至有些悲觀的評論家認爲成熟的Java生態系統有崩潰的可能。
Apache Harmony是一個Apache軟件基金會旗下以Apache License協議開源的實際兼容於JDK 1.5和JDK 1.6的Java程序運行平臺,這個介紹至關拗口。它包含本身的虛擬機和Java庫,用戶能夠在上面運行Eclipse、Tomcat、Maven等常見的Java程序,可是它沒有經過TCK認證,因此咱們不得不用那麼一長串拗口的語言來介紹它,而不能用一句「Apache的JDK」來講明。若是一個公司要宣佈本身的運行平臺「兼容於Java語言」,那就必需要經過TCK(Technology Compatibility Kit)的兼容性測試。Apache基金會曾要求Sun公司提供TCK的使用受權,可是一直遭到拒絕,直到Oracle公司收購了Sun公司以後,雙方關係越鬧越僵,最終致使Apache憤然退出JCP(Java Community Process)組織,這是目前爲止Java社區最嚴重的一次「分裂」。
在Sun將JDK開源造成OpenJDK以後,Apache Harmony開源的優點被極大地削弱,甚至連Harmony項目的最大參與者IBM公司也宣佈辭去Harmony項目管理主席的職位,並參與OpenJDK項目的開發。雖然Harmony沒有通過真正大規模的商業運用,可是它的許多代碼(基本上是Java庫部分的代碼)被吸納進IBM的JDK 7實現及Google Android SDK之中,尤爲是對Android的發展起到了很大的推進做用。
說到Android,這個時下最熱門的移動數碼設備平臺在最近幾年間的發展過程當中所取得的成果已經遠遠超越了Java ME在過去十多年所得到的成果,Android讓Java語言真正走進了移動數碼設備領域,只是走的並不是Sun公司本來想象的那一條路。
Dalvik VM是Android平臺的核心組成部分之一,它的名字來源於冰島一個名爲Dalvik的小漁村。Dalvik VM並非一個Java虛擬機,它沒有遵循Java虛擬機規範,不能直接執行Java的Class文件,使用的是寄存器架構而不是JVM中常見的棧架構。可是它與Java又有着千絲萬縷的聯繫,它執行的dex(Dalvik Executable)文件能夠經過Class文件轉化而來,使用Java語法編寫應用程序,能夠直接使用大部分的Java API等。目前Dalvik VM隨着Android一塊兒處於迅猛發展階段,在Android 2.2中已提供即時編譯器實現,在執行性能上有了很大的提升。
7. Microsoft JVM及其餘
在十幾年的Java虛擬機發展過程當中,除去上面介紹的那些被大規模商業應用過的Java虛擬機外,還有許多虛擬機是鮮爲人知的或者曾經「絢麗」過但最終湮滅的。咱們以其中微軟公司的JVM爲例來介紹一下。
也許Java程序員聽起來可能會以爲驚訝,微軟公司曾經是Java技術的鐵桿支持者(也必須認可,與Sun公司爭奪Java的控制權,令Java從跨平臺技術變爲綁定在Windows上的技術是微軟公司的主要目的)。在Java語言誕生的初期(1996年~1998年,以JDK 1.2發佈爲分界),它的主要應用之一是在瀏覽器中運行Java Applets程序,微軟公司爲了在IE3中支持Java Applets應用而開發了本身的Java虛擬機,雖然這款虛擬機只有Windows平臺的版本,倒是當時Windows下性能最好的Java虛擬機,它在1997年和1998年連續兩年得到了《PC Magazine》雜誌的「編輯選擇獎」。但好景不長,在1997年10月,Sun公司正式以侵犯商標、不正當競爭等罪名控告微軟公司,在隨後對微軟公司的壟斷調查之中,這款虛擬機也曾做爲證據之一被呈送法庭。這場官司的結果是微軟公司賠償2000萬美金給Sun公司(最終微軟公司因壟斷賠償給Sun公司的總金額高達10億美圓),承諾終止其Java虛擬機的發展,並逐步在產品中移除Java虛擬機相關功能。具備諷刺意味的是,到最後在Windows XP SP3中Java虛擬機被徹底抹去的時候,Sun公司卻又處處登報但願微軟公司不要這樣作。Windows XP高級產品經理Jim Cullinan稱:「咱們花費了3年的時間和Sun打官司,當時他們試圖阻止咱們在Windows中支持Java,如今咱們這樣作了,可他們又在抱怨,這太具備諷刺意味了。」
咱們試想一下,若是當年Sun公司沒有起訴微軟公司,微軟公司繼續保持着對Java技術的熱情,那Java的世界會變得怎麼樣呢?.NET技術是否會發展起來?但歷史是沒有假設的。
問:堆和棧有什麼區別
答:堆是存放對象的,可是對象內的臨時變量是存在棧內存中,如例子中的methodVar是在運行期存放到棧中的。
棧是跟隨線程的,有線程就有棧,堆是跟隨JVM的,有JVM就有堆內存。
問:堆內存中到底存在着什麼東西?
答:對象,包括對象變量以及對象方法。
問:類變量和實例變量有什麼區別?
答:靜態變量是類變量,非靜態變量是實例變量,直白的說,有static修飾的變量是靜態變量,沒有static修飾的變量是實例變量。靜態變量存在方法區中,實例變量存在堆內存中。
問:我據說類變量是在JVM啓動時就初始化好的,和你這說的不一樣呀!
答:那你是道聽途說,信個人,沒錯。
問:Java的方法(函數)究竟是傳值仍是傳址?
答:都不是,是以傳值的方式傳遞地址,具體的說原生數據類型傳遞的值,引用類型傳遞的地址。對於原始數據類型,JVM的處理方法是從Method Area或Heap中拷貝到Stack,而後運行frame中的方法,運行完畢後再把變量指拷貝回去。
問:爲何會產生OutOfMemory產生?
答:一句話:Heap內存中沒有足夠的可用內存了。這句話要好好理解,不是說Heap沒有內存了,是說新申請內存的對象大於Heap空閒內存,好比如今Heap還空閒1M,可是新申請的內存須要1.1M,因而就會報OutOfMemory了,可能之後的對象申請的內存都只要0.9M,因而就只出現一次OutOfMemory,GC也正常了,看起來像偶發事件,就是這麼回事。 但若是此時GC沒有回收就會產生掛起狀況,系統不響應了。
問:我產生的對象很少呀,爲何還會產生OutOfMemory?
答:你繼承層次忒多了,Heap中 產生的對象是先產生 父類,而後才產生子類,明白不?
問:OutOfMemory錯誤分幾種?
答:分兩種,分別是「OutOfMemoryError:java heap size」和」OutOfMemoryError: PermGen space」,兩種都是內存溢出,heap size是說申請不到新的內存了,這個很常見,檢查應用或調整堆內存大小。
「PermGen space」是由於永久存儲區滿了,這個也很常見,通常在熱發佈的環境中出現,是由於每次發佈應用系統都不重啓,長此以往永久存儲區中的死對象太多致使新對象沒法申請內存,通常從新啓動一下便可。
問:爲何會產生StackOverflowError?
答:由於一個線程把Stack內存所有耗盡了,通常是遞歸函數形成的。
問:一個機器上能夠看多個JVM嗎?JVM之間能夠互訪嗎?
答:能夠多個JVM,只要機器承受得了。JVM之間是不能夠互訪,你不能在A-JVM中訪問B-JVM的Heap內存,這是不可能的。在之前老版本的JVM中,會出現A-JVM Crack後影響到B-JVM,如今版本很是少見。
問:爲何Java要採用垃圾回收機制,而不採用C/C++的顯式內存管理?
答:爲了簡單,內存管理不是每一個程序員都能折騰好的。
問:爲何你沒有詳細介紹垃圾回收機制?
答:垃圾回收機制每一個JVM都不一樣,JVM Specification只是定義了要自動釋放內存,也就是說它只定義了垃圾回收的抽象方法,具體怎麼實現各個廠商都不一樣,算法各異,這東西實在不必深刻。
問:JVM中到底哪些區域是共享的?哪些是私有的?
答:Heap和Method Area是共享的,其餘都是私有的
問:什麼是JIT,你怎麼沒說?
答:JIT是指Just In Time,有的文檔把JIT做爲JVM的一個部件來介紹,有的是做爲執行引擎的一部分來介紹,這都能理解。Java剛誕生的時候是一個解釋性語言,別噓,即便編譯成了字節碼(byte code)也是針對JVM的,它須要再次翻譯成原生代碼(native code)才能被機器執行,因而效率的擔心就提出來了。Sun爲了解決該問題提出了一套新的機制,好,你想編譯成原生代碼,沒問題,我在JVM上提供一個工具,把字節碼編譯成原生碼,下次你來訪問的時候直接訪問原生碼就成了,因而JIT就誕生了,就這麼回事。
問:JVM還有哪些部分是你沒有提到的?
答:JVM是一個異常複雜的東西,寫一本磚頭書都不爲過,還有幾個要說明的:
問:爲何不建議在程序中顯式的生命System.gc()?
答:由於顯式聲明是作堆內存全掃描,也就是Full GC,是須要中止全部的活動的(Stop The World Collection),你的應用能承受這個嗎?
問:JVM有哪些調整參數?
答:很是多,堆內存、棧內存的大小均可以定義,甚至是堆內存的三個部分、新生代的各個比例都能調整。
在互聯網公司面試中,架構的底層必定是面試官會問到的問題,針對面試官通常會提到的問題,我錄製了一些底層原理的錄像視頻,加羣:650385180能夠免費獲取這些錄像,裏面有些分佈式,微服務,性能優化,Spring,MyBatis的等源碼知識點的錄像視頻。上圖的性能優化只是其中的一小部分,這些視頻都是我找一些資深架構師朋友一塊兒錄製出來的,視頻但願可以幫助到如下幾類程序員:
1.對如今的薪資不滿,想要跳槽,卻對本身的技術沒有信心,不知道如何面對面試官。
2.想從傳統行業轉行到互聯網行業,但沒有接觸過互聯網技術。
3.工做1 - 5年須要提高本身的核心競爭力,但學習沒有系統化,不知道本身接下來要學什麼纔是正確的,踩坑後又不知道找誰,百度後依然不知因此然。
4.工做5 - 10年沒法突破技術瓶頸(運用過不少技術,在公司一直寫着業務代碼,卻依然不懂底層實現原理)
若是你如今正處於我上述所說的幾個階段能夠加下個人羣來學習。並且我也可以提供一些面試指導,職業規劃等建議。