參考鏈接:
http://www.importnew.com/21470.html
雖然平時我們用的大多是Sun(現(xiàn)已被Oracle收購)JDK提供的JVM张惹,但是JVM本身是一個規(guī)范桃犬,所以可以有多種實現(xiàn)假消,除了Hotspot外犯助,還有諸如Oracle的JRockit耿导、IBM的J9也都是非常有名的JVM赎离。
主要組成:
類加載器子系統(tǒng)晦攒、運行時數據區(qū)(內存空間)闽撤、執(zhí)行引擎以及與本地方法接口等組成。
其中運行時數據區(qū)又由堆脯颜、方法區(qū)哟旗、Java棧、本地方法棧栋操、PC寄存器組成闸餐。堆與方法區(qū)是所有JAVA線程共享的。JAVA棧矾芙,本地方法棧舍沙,PC寄存器則由每個線程私有。
堆:
堆是JVM所管理的內存中最大的一塊剔宪,是被所有Java線程鎖共享的场勤,不是線程安全的,在JVM啟動時創(chuàng)建歼跟。
Sun JDK從1.2版本開始引入了分代管理的方式和媳。主要分為新生代、舊生代哈街。分代方式大大改善了垃圾收集的效率留瞳。
-Xms -Xmx
-XX:MinHeapFreeRatio
-XX:MaxHeapFreeRatio
對于運行系統(tǒng)而言,為避免在運行時頻繁調整Heap 的大小骚秦,通常將-Xms和-Xmx的值設成一樣她倘。
方法區(qū):
類型信息和類的靜態(tài)變量及常量池都存儲在方法區(qū)中璧微。常量池中存儲了如字符串、final變量值硬梁、類名和方法名常量前硫。在Sun JDK中,方法區(qū)對應了持久代(Permanent Generation)荧止,默認最小值為16MB屹电,最大值為64MB。大小可以通過參數來設置,可以通過-XX:PermSize指定初始值跃巡,-XX:MaxPermSize指定最大值危号。
JAVA棧:
Java棧的主要任務是存儲方法參數、局部變量素邪、中間運算結果外莲,并且提供部分其它模塊工作需要的數據。
Java椡秒總是與線程關聯(lián)在一起的偷线,每當創(chuàng)建一個線程,JVM就會為該線程創(chuàng)建對應的Java棧沽甥,在這個Java棧中又會包含多個棧幀(Stack Frame)声邦,這些棧幀是與每個方法關聯(lián)起來的,每運行一個方法就創(chuàng)建一個棧幀安接,每個棧幀會含有一些局部變量翔忽、操作棧和方法返回值等信息。每當一個方法執(zhí)行完成時盏檐,該棧幀就會彈出棧幀的元素作為這個方法的返回值歇式,并且清除這個棧幀,Java棧的棧頂的棧幀就是當前正在執(zhí)行的活動棧胡野,也就是當前正在執(zhí)行的方法材失,PC寄存器也會指向該地址。它分為三部分:局部變量區(qū)硫豆、操作數棧龙巨、幀數據區(qū)。
本地方法棧:
本地方法棧類似于Java棧熊响,主要存儲了本地方法調用的狀態(tài)旨别。區(qū)別不過是Java棧為JVM執(zhí)行Java方法服務,而本地方法棧為JVM執(zhí)行Native方法服務汗茄。本地方法棧也會拋出StackOverflowError和OutOfMemoryError異常秸弛。在Sun JDK中,本地方法棧和Java棧是同一個。
PC寄存器:
嚴格來說是一個數據結構递览,用于保存當前正在執(zhí)行的程序的內存地址叼屠,由于Java是支持多線程執(zhí)行的,所以程序執(zhí)行的軌跡不可能一直都是線性執(zhí)行绞铃。當有多個線程交叉執(zhí)行時镜雨,被中斷的線程的程序當前執(zhí)行到哪條內存地址必然要保存下來,以便用于被中斷的線程恢復執(zhí)行時再按照被中斷時的指令地址繼續(xù)執(zhí)行下去儿捧。為了線程切換后能恢復到正確的執(zhí)行位置荚坞,每個線程都需要有一個獨立的程序計數器,各個線程之間計數器互不影響纯命,獨立存儲西剥,我們稱這類內存區(qū)域為“線程私有”的內存,這在某種程度上有點類似于“ThreadLocal”痹栖,是線程安全的亿汞。
ClassLoader的分類#####
Bootstrap, Extension, System, User-Defined
類加載分為裝載、鏈接揪阿、初始化三步
JAVA 初始化 順序:
靜態(tài)變量疗我,static代碼塊,構造器
Java內存模型#####
所有的變量都存儲在主內存中南捂,每條線程還有自己的工作內存吴裤,線程的工作內存中保存了該線程使用到的變量到主內存副本拷貝,線程對變量的所有操作(讀取溺健、賦值)都必須在工作內存中進行麦牺,而不能直接讀寫主內存中的變量。不同線程之間無法直接訪問對方工作內存中的變量鞭缭,線程間變量值的傳遞均需要在主內存來完成剖膳,線程、主內存和工作內存的交互關系如下圖所示岭辣,和上圖很類似吱晒。