筆者能力有限,總結(jié)有誤的地方,請讀者協(xié)作更正。
1.類的加載機制
關(guān)注點: ?什么是類的加載 ?類的生命周期 ?類加載器 ?雙親委派模型
1)談一談類的實例化順序,比如:父類靜態(tài)數(shù)據(jù),構(gòu)造函數(shù),字段等的執(zhí)行順序? 先靜態(tài)-->先父后子-->非靜態(tài)代碼塊-->構(gòu)造函數(shù)
2)java代碼的執(zhí)行編譯過程 ? 主要就是兩部:java源文件由編譯器編譯成字節(jié)碼文件,字節(jié)碼文件由虛擬機解釋執(zhí)行。
具體來說,源碼需要經(jīng)過詞法分析器組件,語法分析器組件,語義分析器組件,最后經(jīng)過代碼生成器組件編譯成字節(jié)碼文件。
3)java類的生命周期?
一個java類的完整的生命周期會經(jīng)歷加載、連接、初始化、使用、和卸載五個階段,當然也有在加載或者連接之后沒有被初始化就直接被使用的情況。
4)類加載器?
類加載器是java語言強大的特征之一, 默認情況下有三種類加載器(引導類加載器,擴展類加載器,應用類加載器),我們也可以自定義類加載器。 應用程序的每一個類都由ClassLoader加載,java類是被動態(tài)的加載到內(nèi)存,java的一大特點,也稱為運行時綁定。
5)什么是類加載器的雙親委派模型?
就是類加載器之間的的層次關(guān)系,該模型要求除了頂層的啟動類加載器之外,其余的類加載器都要有父類加載器,而且這種關(guān)系一般通過組合關(guān)系來實現(xiàn),而不是通過繼承。
某一個類加載器在接到加載類的請求時候,首先會將任務委托給父類加載,依次遞歸,如果父類加載器可以完成類加載任務,則成功返回;如果父類加載器無法完成加載任務,將拋出ClassNotFoundException異常后,再調(diào)用自己的findClass()方法進行加載,依次類推。
好處:
防止內(nèi)存中出現(xiàn)多份同樣的字節(jié)碼。 如果沒有雙親委派模型而是由各個類加載器自行加載的話,如果用戶編寫了一個java.lang.Object的同名類并放在ClassPath中,多個類加載器都去加載這個類到內(nèi)存中,系統(tǒng)中將會出現(xiàn)多個不同的Object類,那么類之間的比較結(jié)果及類的唯一性將無法保證,將會給虛擬機的安全帶來隱患。
2.JVM內(nèi)存結(jié)構(gòu)
關(guān)注點: ?內(nèi)存結(jié)構(gòu) ?對象分配規(guī)則
1)JVM的內(nèi)存分配?
Java虛擬機的運行時數(shù)據(jù)區(qū)包括:Java堆、Java虛擬機棧、方法區(qū)、PC寄存器、本地方法棧,還有常量池。它們被分為兩大類-------線程共享、私有數(shù)據(jù)區(qū)。
2)虛擬機內(nèi)存分配的各個區(qū)域作用?
堆:
new處理的對象都存放在堆中,堆的大小可以通過-Xmx和-Xms來控制; 堆被分為新生代、舊生代、持久代新創(chuàng)建的對象都用新生代內(nèi)存分配,舊生代用于存放新生代中多次經(jīng)過垃圾回收仍然存活的對象;
棧:
每個線程執(zhí)行每個方法時候都會在棧中申請一個棧幀,用于存放此次方法調(diào)用過程中臨時的變量、參數(shù)、中間結(jié)果等;
本地方法棧:
用于支持native方法執(zhí)行,存儲每個native方法調(diào)用的狀態(tài)
方法區(qū):
持久代實現(xiàn)方法區(qū),主要用來存放已經(jīng)加載的類的信息,方法,常量等;可以通過XX:PermSize和-XX:MaxPermSize來指定持久帶初始化值和最大值。
3.GC算法 垃圾回收
關(guān)注點: ?對象存活判斷 ?GC算法 ?垃圾回收器
1)垃圾回收采用什么算法實現(xiàn)?按照基本策略分為:
引用計數(shù)器(Reference Counting): 比較舊的一個算法,原理是此對象有一個引用;增加一個計數(shù),增加一個引用;刪除一個引用,減少一個計數(shù)。 垃圾回收時,只收集計數(shù)為0的對象。 存在最致命的問題是,無法處理循環(huán)引用的問題。
標記-清除(Mark-Sweep): 此算法分為兩個階段,第一個階段從引用根節(jié)點開始標記被引用的對象; 第二個階段遍歷整個堆,把未標記的對象清除。此算法需要暫停整個應用,同時,會產(chǎn)生內(nèi)存碎片。
復制(Copying): 此算法把內(nèi)存空間劃分為相等的區(qū)域,每次只使用其中一個區(qū)域,垃圾回收時候,遍歷當前的區(qū)域,把正在使用中的對象復制到另一個區(qū)域。 算法每次只處理正在使用的對象,因為復制成本小,同時復制過去之后還能進行相應的內(nèi)存調(diào)整,不會出現(xiàn)碎片問題。 缺點就是,需要兩倍的內(nèi)存空間。
標記-整理(Mark-Compact): 此算法集合了“標記-清除”和“復制”兩個算法的優(yōu)點分為兩個階段,第一階段從根節(jié)點開始標記所有被引用的對象,第二階段遍歷整個堆,把清除未標記的對象并且存活的對象“壓縮”到堆的其中一塊,按照順序排放。 此算法避免了“標記-清除”的碎片問題,同時也避免了“復制”算法的空間問題。
2)Java對新生代和舊生代采取了不同的垃圾回收機制
新生代的GC: 新生代通常存活時間較短,居于Coping算法來進行回收; 采用空指針的方式來控制GC觸發(fā),指針保持最后一個分配的對象在新生代區(qū)間位置,當有新的對象要分配內(nèi)存時候,用于檢查空間是否足夠,不夠就觸發(fā)GC; 在執(zhí)行機制上提供了串行GC,并行回收GC,和并行GC;
舊生代GC: 舊生代GC對象存活的時間比較長,比較穩(wěn)定;
采用標記(Mark)算法來進行回收,就是掃描出存活的對象,回收位被標記的對象,回收后對對騰出的空間進行合并。 在執(zhí)行機制上JVM提供了串行GC,并行GC和并發(fā)GC;
4.GC分析 命令調(diào)優(yōu)
關(guān)注點: ?GC日志分析 ?調(diào)優(yōu)命令 ?調(diào)優(yōu)工具
調(diào)優(yōu)主要的目的是減少GC的頻率和Full GC的次數(shù),過多的GC和Full GC是會占用很多的系統(tǒng)資源(主要是CPU),影響系統(tǒng)的吞吐量。
調(diào)優(yōu)手段:主要是通過控制堆內(nèi)存的各個部分的比例和GC策略來實現(xiàn),JVM提供兩種較為簡單的GC策略的設(shè)置方式;
1)吞吐量優(yōu)先 ? ? JVM以吞吐量為指標,自行選擇相應的GC策略及控制新生代與舊生代的大小比例,來達到吞吐量指標。這個值可由-XX:GCTimeRatio=n來設(shè)置
2)暫停時間優(yōu)先 ? ? JVM以暫停時間為指標,自行選擇相應的GC策略及控制新生代與舊生代的大小比例,盡量保證每次GC造成的應用停止時間都在指定的數(shù)值范圍內(nèi)完成。這個值可由-XX:MaxGCPauseRatio=n來設(shè)置
更多建議: