一):運行數據區java
1:程序計數器(Program Counter Register),也稱"PC寄存器"算法
A:用來指示須要執行哪條指令的。(在彙編語言中,CPU在獲得指令以後,程序計數器便自動加1或者根據 轉移指針獲得下一條指令的地址,如此循環,直至執行完全部的指令。)數組
B:因爲在JVM中,多線程是經過線程輪流切換來得到CPU執行時間的。每個線程都有獨立的程序計數器,屬 於私有的。多線程
C:若是線程執行的是java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令地址;若是正在執行的是 Native方法,則程序計數器中的值是undefined。併發
D: 因爲程序計數器中存儲的數據所佔空間的大小不會隨程序的執行而發生改變,所以,對於程序計數器是不會 發生內存溢出現象(OutOfMemory)的。spa
2:虛擬機棧(VM Stack),也稱 Java棧線程
A:每一個方法執行都會建立一個棧幀(Stack Frame),用於存儲局部變量表,操做數棧,常量引用,動態連接, 方法出口等其餘附加信息;-Xss參數設定。指針
B:對於基本數據類型的變量,則直接存儲它的值,對於引用類型的變量,則存的是指向對象的引用。局部變量 表的大小在編譯器就能夠肯定其大小了,所以在程序執行期間局部變量表的大小是不會改變的。對象
C:若是線程請求大於虛擬機容許的深度,將拋出StackOverflowError;若是虛擬機棧能夠動態擴展(也容許 固定長度),擴展時內存不夠,就拋出OutOfMemoryError。接口
3:本地方法棧(Native Method Stack)
A:與虛擬機棧做用類似,區別就是它爲Native方法服務的;
B:有的虛擬機(如Sun HotSpot)把本地方法棧和虛擬機棧合二爲一;
4:堆(Heap),即java堆
A:Java中的堆是用來存儲對象自己的以及數組(固然,數組引用是存放在Java棧中的);
B:Java堆是垃圾收集器管理的主要區域,Java堆在虛擬機啓動時建立,被全部線程共享;
C:Java堆裏面分爲:新生代和老生代;
D:在實現時,既能夠是固定大小又能夠是可擴展的(經過-Xmx和-Xms控制,設置同樣就不能自動擴展), 若是堆內存不夠將會拋出OutOfMemoryError;
5:方法區(Method Area)
A:在方法區中,存儲了每一個類的信息(包括類的名稱、方法信息、字段信息)、靜態變量、常量以及編譯 器編譯後的代碼等。
B:別名 Non-Heap ,非堆;目的應該是區別java堆;設置-XX:PermSize和-XX:MaxPermSize限制方法 區大小;
C:HotSpot上不少人習慣把方法區看作「永久代」,可是本質上二者並不等價!
HotSpot是使用永久代來實現方法區的,這樣GC就能夠像管理Java堆同樣地管理方法區了,省去了爲 方法區編寫內存管理的代碼。但其餘虛擬機(JRockit,J9等)來講是不存在永久代的;原則上如何實現方 法區,不受虛擬機規範約束;對於HotSpot如今也有放棄永久代並逐步改成Native Memory來實現方 法區的規劃了;jdk1.7的HotSpot中已經把本來放在永久代的字符串常量池移除;
D:方法區沒法知足內存分配時,將拋出OutOfMemoryError;
E:運行時常量池時方法區的一部分;
6:直接內存,受物理內存大小限制;
1:程序計數器、虛擬機棧、本地方法棧都是隨着線程而生,隨線程而消亡;須要回收的是堆和方法區;
2:對象已死嗎?對象已經被回收了嗎?
1) 引用計數法:給對象添加一個引用計數器,每當對象有個引用,計數器就加1,引用失效就減1,當引用計 數器爲0時,該對象就不可能再被使用了(回收)(不少人的答an)。
可是,至少主流的java虛擬機沒有使用這種算法來管理內存,主要緣由是它很難解決對象之間的循環引用。
2)可達性分析算法:主流都是通這個算法來判斷對象是否存活。
這個算法基本思想就是經過一些列的'GC Roots'的對象做爲起始點,從這些節點開始往下搜索,搜索所走過 的路徑成爲'引用鏈',當一個對象到GC Roots沒有任何引用鏈死,就是從GC Roots到這個對象不可達。則證 明這個對象不可用,這些對象將被斷定可回收。
但這些對象不是'非死不可'(緩刑階段),要宣告一個對象死亡,至少要經歷兩次標記。GC Roots不可達將會 進行第一次標記且進行一次篩選,篩選的條件就是此對象有沒有必要執行finalize()方法,當對象沒有覆蓋 finalize()或finalize()被虛擬機調用過,這兩種狀況虛擬機視爲"沒有必要執行"。此外就是有必要執行,那 麼這個對象就是會被放入F-Queue的隊列中,finalize()方法是對象逃脫死亡的最後一次機會(把對象賦值給 某個變量);稍後GC對F-Queue中的對象進行小規模的第二次標記,被兩次標記對象真的要被回收了。
3)回收方法區:
A:java虛擬機規範能夠不要求虛擬機在方法區實現垃圾收集,方法區(永久代)垃圾收集效率比較低。
B:永久代垃圾收集分爲兩部分:廢棄常量和無用的類。
回收廢棄常量和回收java堆中對象很是相似,但常量沒有其餘地方引用就會被移除常量池(回收),方法區 中的類(接口)字段等符號引用也是如此。
知足如下3個條件纔算是'無用的類':(是否被回收,虛擬機提供了一些設置參數)
1:該類的所用實例都已經被回收
2:加載該類的ClassLoader已經被回收
3:該類對應的java.lang.Class對象沒有任何地方被引用,沒法經過發射訪問該類的方法
4)垃圾收集算法:
A:標記-清除算法:分爲標記和清除兩個階段。有兩個問題1:效率不高 2:會產生大量不連續的內存碎片。
B:複製算法:運行高效。
C:標記-整理算法:老年代通常使用這種算法 。
D:分代收集算法:
當前商業虛擬機的垃圾收集都採用分代收集;
根據對象存活週期的不一樣把內存劃分爲幾塊;
通常是把java堆分爲新生代和老年代,根據各個年代特色採用不一樣算法,
在新生代,每次垃圾收集就有大量對象死去,因此採用複製算法;
在老年代,對象存活率較高,就採用標記-清除或標記-整理算法;
5)垃圾收集器:若是說垃圾收集算法是內存回收的方法論,那麼垃圾收集器就是具體實現;有好7種。
A:Serial收集器:單線程的。發展歷史最悠久的收集器。簡單高效,jdk1.3以前 新生代的惟一選擇。
B:ParNew收集器:Serial的多線程版;是運行在Service模式下的虛擬機中首先的新生代收集器。jdk1.3
C:Parallel Scavenge收集器:使用複製算法的新生代收集器,又是並行的多線程收集器;jdk1.4。
D:Serial Old收集器:是Serial送機器的老年代版本,單線程,使用標記-整理算法,主要意義在於給 Client模式下的虛擬機使用;jdk1.5
E:Parallel Old收集器:Parallel Scavenge收集器老年代版本,多線程,採用標記-整理的算法;jdk1.6
F:CMS收集器:是以獲取最短回收停頓時間爲目標的收集器,基於標記-清除算法。併發收集低停頓.jdk1.5
J:G1收集器:jdk1.7中,面向服務端應用的垃圾收集器,將來可能替換掉CMS收集器;
特色:1並行與併發;2分代收集;3空間整合;4可預測的停頓;
運做步驟:1:初始標記;2:併發標記;3:最終標記;4:篩選回收;
6)內存分配與回收策略:
A .對象優先在Eden上分配:
大多數狀況下,對象在新生代Eden上分配,但Eden上沒有空間了,虛擬機會發起一次Minor GC(發生在新 生代垃圾收集動做,比較頻繁,通常回收速度快);老年代GC(Major GC 或Full GC),發生在老年代的 GC,出現了Major GC ,常常會伴隨至少一的 Minor GC(但非絕對);
B.大對象直接進入老年代:大對象就是須要大量連續內存空間的java對象,最典型的就是較長的字符串以及數組
C.長期存活的對象將進入老年代:
有個對象年齡計算器,每熬過1次Minor GC 年齡就加1歲,當年齡到達默認值(15歲)就會晉升到老年代中, 這個年齡閥值能夠經過設置-XX:MaxTenuringThreshold;
寫博客有點累,未完待續》。。