須要反覆記憶的東西--暫時無用

一  JVMhtml

     1.  棧幀包括:局部變量表、操做數棧、常量池、動態連接、方法出口信息等算法

     2.  方法區:堆的一個邏輯部分,線程共享,存放已經被虛擬機加載的類信息、常量、編程

                        靜態變量、即時編譯器編譯後的代碼等。數組

     3.  如何判斷對象已死多線程

          對象不可達並經歷兩次標記的對象。併發

        (1)可達性分析算法函數

                 該算法的思路是經過一系列稱爲「GC Root」的對象做爲始點,從這些節點開始向下搜索,性能

                 搜索所走過的路稱爲引用鏈(Reference Chain),當一個對象到GC Roots沒有任何引this

                 用鏈相接(不可達)時,則證實此對象時不可用的。以下圖所示,object五、object六、spa

                 object7雖然相會關聯,可是它們到GC Root是不可達的,因此將會被斷定爲是可回收

                 的對象。

                 

                在Java中,可做爲GC Root的對象包括下面幾種:

                --  虛擬機棧(棧幀中的本地變量表)中引用的對象。

                --  本地方法棧中JNI(即通常說的Native方法)引用的對象

                --  方法區內類靜態屬性引用的對象和常量引用的對象。

          (2)可達性分析算法            

                   若是進行垃圾回收的時候發現一個對象沒有在GC Root鏈上,那麼就須要進行兩次的

                   標記過程,若是當前發現沒有關聯在GC Root鏈上,那麼就會進行第一次標記,若是

                   此時對象的finalize()方法沒有被覆蓋或該方法已經被虛擬機調用過,那麼此時將被標

                   記爲沒有必要執行,此時該對象會被放入「即將回收」集合,不然就會放入F-Queue的

                   對象中等待執行finalize()方法,若是在此方法中對象將本身與GC Root鏈上的任何一

                   個對象關聯(譬如把本身(this)賦值給某個類變量或者對象的成員變量),那麼就

                   會被移出」即將回收「集合。

     4.  常見的垃圾回收算法

        (1)標記清除算法

                         分爲兩個階段,標註和清除。標記階段標記出全部須要回收的對象,清除階段回

                         收被標記的對象所佔用的空間,該算法最大的問題是內存碎片產生嚴重。

        (2)複製算法

                        爲了解決Mark-Sweep算法內存碎片化的缺陷而被提出的算法。按內存容量將內存

                        劃分爲等大小的兩塊。每次只使用其中一塊,當這一塊內存滿後將尚存活的對象復

                        制到另外一塊上去,把已使用的內存清掉。這種算法雖然實現簡單,內存效率高,不

                        易產生碎片,可是最大的問題是可用內存被壓縮到了本來的一半。且存活對象增多

                        的話,Copying算法的效率會大大下降

        (3)標記壓縮算法

                         標記階段和標記算法相同,標記後不是清理對象而是將存活的對象移動到內存的

                         一端,而後清除邊界外的對象。

        (4)分代算法

                        分代收集法是目前大部分JVM所採用的方法,其核心思想是根據對象存活的不一樣

                        生命週期將內存劃分爲不一樣的域,通常狀況下將GC堆劃分爲老生代

                        (Tenured/Old Generation)和新生代(Young Generation)。老生代的特色是每次垃

                        圾回收時只有少許對象須要被回收,新生代的特色是每次垃圾回收時都有大量垃

                        圾須要被回收,所以能夠根據不一樣區域選擇不一樣的算法。新生代採用複製算法,

                        老年代採用標記壓縮算法。

        (5)分區算法

                         將整個內存分爲N個小的獨立空間,每一個小空間均可以獨立使用,這樣細粒度控

                         制一次回收多少個小空間和哪些個小空間,而不是對整個空間進行GC,從而提

                         升性能。

     5.  垃圾回收器

         (1)Serial收集器

                           新生代收集器,是一個單線程的收集器,採用的是「複製算法」。它的 「單線程」

                           的意義並不只僅說明它只會使用一個CPU或一條收集線程去完成垃圾收集工

                           做,更重要的是在它進行垃圾收集時,必須暫停其它全部工做線程,直到它收

                           集結束。

         (2)ParNew收集器

                           是Serial收集器的多線程版本,採用的是「複製算法」。除了使用多線程進行垃圾

                           收集以外,其他行爲包括Serial收集器可用的全部控制參 數、收集算法、

                           Stop The World、對象分配規則、回收策略等都與Serial收集器徹底同樣,在

                           實現上,這兩種收集器也共用了至關多的代碼。ParNew收集器除了多線程收集

                           以外,其它與Serial收集器相比並無太多創新之處,但它倒是運行在Server模

                           式下的虛擬機中首選的新生代收集器,其中一個與性能無關但很重要的緣由是,

                           除了Serial收集器外,目前只有它能與CMS收集器配合工做。

         (3)Parallel Scavenge收集器:

                          是工做在新生代的垃圾回收器,使用了複製算法,也是多線程獨佔(獨佔回收器:

                          GC來的時候應用停頓只執行GC)形式的收集器,它的特色是關注系統的吞吐量。

         (4)Serial Old收集器:

                          是Serial收集器的老年代版本,它一樣是一個單線程的收集器,使用「標記-整理」

                          算法。這個收集器的主要意義也是在於給Client模式下的虛擬機使用。若是在

                          Server模式下,那麼它主要還有兩大用途:

                          一種用途在JDK1.5以及以前的版本中與Parallel Scavenge收集器搭配使用。

                          另外一種用途就是做爲CMS收集器的後備方案,在併發收集器發生

                          Concurrent Mode Failure時使用。

         (5)Parallel Old是Parallel Scavenge收集器的老年代版本,使用多線程和「標記-整理」算法。

                   這個收集器在JDK1.6中才開始提供的,在此以前,新生代的Parallel Scavenge收集器

                   一直處於比較尷尬大的狀態。緣由是若是新生代選擇了Parallel Scavenge收集器,老

                   年代除了Serial Old收集器外別無選擇。因爲老年代Serial Old收集器在服務端性能上

                   的拖累,使用Parallel Scavenge收集器也未必能在總體應用上得到吞吐量最大的效果。

                   直到。

        (6)CMS回收器:

                 工做在老年代的回收器,使用的是標記清除法,是一種以獲取最短回收停頓時間爲目標

                 的收集器主要關注的是系統的停頓時間。CMS並非獨佔的回收器,也就是說CMS回

                 收的過程當中,應用程序仍然在不停的工做,又會有新的垃圾不斷產生,因此在使用CMS

                 過程當中應該確保應用程序的內存足夠可用,CMS不會等到應用程序飽和的時候在去回收

                 圾,而是到達某個閾值的時候就去回收,回收的閾值能夠經過指定的參數來設置

                 -XX:CMSInitiatingOccupancyFraction來指定,默認值是68,也就是說當老年代的使用率

                 達到68%的時候會執行CMS垃圾回收,若是內存使用增加的很快,在CMS過程當中出現了

                 內存不足的狀況,CMS回收就會失敗,虛擬機將啓用老年代串行回收器進行垃圾回收,

                 這會致使應用程序中斷,直到垃圾回收完成後纔會正常工做,這個過程GC停頓時間可能

                 過長,因此設置-XX:CMSInitiatingOccupancyFraction要根據實際狀況。

                 運做過程:初始標記、併發標記、從新標記、併發清除。有的版本叫(另外CMS收集

                 器比較詳細的步驟查看:https://blog.csdn.net/zqz_zqz/article/details/70568819

                 初始標記、從新標記這兩個步驟仍需「Stop The World」。初始標記僅僅只是標記一下

                 GC Root能直接關聯到的對象不包括間接到達的哈,沒有直接關聯的對象在併發標記

                 階段標記哈),速度很快;併發標記階段就是進行GC Roots Tracing的過程從新標記

                 則是爲了修正併發標記期間因用戶程序繼續而致使標記產生變更的那一部分對象的標記

                 記錄,這個時間的停頓時間通常會比初始標記階段稍長些,但遠比並發標記短。在這個

                 階段暫停全部用戶線程,從新掃描堆中的對象,進行可達性分析,標記活着的對象,特

                 別須要注意一點,這個階段是以新生代中對象爲根來判斷對象是否存活的;併發清除,

                 這個階段主要是清除那些沒有標記的對象而且回收空間,因爲CMS併發清理階段用戶線

                 程還在運行着,伴隨程序運行天然就還會有新的垃圾不斷產生,這一部分垃圾出如今標

                 記過程以後,CMS沒法在當次收集中處理掉它們,只好留待下一次GC時再清理掉。這

                 一部分垃圾就稱爲「浮動垃圾」。

                 缺點:

                 (A)CMS收集器對CPU資源很是敏感(其實應該說它比較消耗cpu資源)。在並

                           發階段,它雖然不會致使用戶線程停頓,可是會由於佔用一部分CPU資源而

                           致使應用程序變慢。CMS默認啓動的回收器線程數量是 (CPU數量+3) / 4,

                           也就是當CPU在4個以上時,併發回收時垃圾收集線程很多於25%的CPU

                           資源,而且隨着CPU數量的增長而降低。可是當CPU的數量不足時(譬

                           如2個),CMS對用戶程序的影響就可能變得很大。爲了應付這種狀況,

                           虛擬機提供了一種稱爲「增量式併發收集器」(i-CMS)的CMS收集器變種,

                           就時在併發標記、清理的時候讓GC線程、用戶線程交替運行,儘可能減小線

                           程的獨佔資源的時間。在目前版本中i-CMS已經被聲明爲「deprecated」,即

                           不在提倡用戶使用。

                 (B)CMS處理器沒法處理浮動垃圾。

                 (C)基於「標記-清除」算法實現的收集器,會產生大量額空間碎片,會出現併發

                           模式失敗的狀況,併發模式失敗就要執行內存整理(內存壓縮),這種情

                           況下會致使CMS比Parallel Scavenge更慢(一般狀況下CMS比

                           Parallel Scavenge要快)。

        (7)G1回收器:

                 是JDK1.7中提出的基於「標記-整理」算法的垃圾回收器,它的使命是取代CMS

                 回收器,可創建可預測的停頓時間模型屬於分代垃圾回收器 區分新生代和老

                 年代,依然有eden和from、to區,它不要求新生代、老年代、eden、from、

                 to區空 間都 連續,使用了分區算法。聽說JDK1.7以後使用的是G1回收算法,

                 不過有待考證,目前不能肯定,可是在

                 JDK1.7裏它還不太成熟。

                        G1收集器將整個Java堆劃分爲大小相等的獨立區域(Region),雖然還

                 保留着新生代和老年代的概念,但新生代和老年代再也不是物理隔離的了,它

                 們都是一部分Region(不須要連續)的集合。

                        G1收集器之因此能創建可預測的停頓時間模型,是由於它能夠有計劃

                 地避免在整個Java堆中進行全區域的垃圾收集。G1跟蹤各個堆裏面的垃圾

                 堆積的價值大小(回收所得到的空間大小以及回收所須要時間的經驗值),

                 在後臺維護一個優先列表,每次根據容許的回收時間,優先回收價值最大

                 的Region。

                 特色:

                 並行和併發:G1充分利用多CPU、多核環境下的硬件優點,使用多個CPU

                                      來縮短Stop-The-World停頓的時間,部分其它收集器本來須要

                                       停頓Java線程執行的GC動做,G1收集器仍然能夠經過併發的

                                        方式讓Java程序繼續執行。

                 分代收集:存在Eden、from、to。不須要其它收集器的配合就能獨立管理

                                   整個GC堆,能夠本身處理堆中的對象。

                 空間整合:重總體來看是基於「標記-整理」算法實現的;局部(兩個Region

                                   之間)來看是基於「複製」算法的實現的,但這兩種算法都不會

                                   產生內存碎片。

                 可預測停頓:能創建可預測的停頓時間模型。能讓使用者明確指定一個長

                                      度爲M毫秒的時間片斷內,消耗在垃圾收集上的時間不得超

                                      過N毫秒。(這點是G1相對於CMS的另一大優點,低停

                                      頓是G1和CMS共同的關注點,但G1除了追求低停頓外,還

                                      能創建可預測的停頓時間模型)

                 執行過程:若是不計算維護Remembered Set的操做,G1收集器的運做

                                   大體可劃分爲如下幾個步驟:

                                   初始標記、併發標記、並行標記、最終標記、篩選回收。

                                   初始標記僅僅是標記一下GC Root能直接關聯到的對象,並

                                   且修改TAMS(Next Top at Mark Start)的值,讓下一階段

                                   用戶程序併發運行時,能在正確可用的Region中建立對象,

                                   這階段須要停頓但時耗時短;併發標記是從GC Root開始對

                                   堆中對象進行可達性分析,找出存活的對象,這階段耗時較長,

                                   但可與用戶程序併發執行;最終標記是爲了修正在併發標記期

                                    間因用戶程序繼續運做而致使標記產生變更的那一部分標記記

                                    錄;篩選回收階段首先要對各個Region的回收價值和成本進行

                                   排序,根據用戶所指望的GC停頓時間來制定回收計劃,根據

                                   Sun公司透露的信息來看,這個階段其實能夠作到與用戶程序

                                   一塊兒併發執行。

  

     6.  減小GC開銷的編程技巧

           http://www.importnew.com/10472.html

         (1)不要顯式調用System.gc()

                  此函數建議JVM進行主GC,雖然只是建議而非必定,但不少狀況下它

                  會觸發主GC,從而增長主GC的頻率,也即增長了間歇性停頓的次數。

         (2)儘可能減小臨時對象的使用

                  臨時對象在跳出函數調用後,會成爲垃圾,少用臨時變量就至關於

                  減小了垃圾的產生,從而延長了出現上述第二個觸發條件出現的時

                  間,減小了主GC的機會。

         (3)儘可能使用StringBuffer,而不用String來累加字符串

             因爲String是固定長的字符串對象,累加String對象時,並不是在一個

                  String對象中擴增,而是從新建立新的String對象,如

                  Str5=Str1+Str2+Str3+Str4,這條語句執行過

                  程中會產生多個垃圾對象,由於對次做「+」操做時都必須建立新的

                  String對象,但這

                  些過渡對象對系統來講是沒有實際意義的,只會增長更多的垃圾。

        (4)計劃好List的容量

                 像ArrayList這樣的動態集合用來存儲一些長度可變化數據的基本結

                 構。ArrayList和一些其餘的集合(如HashMap、TreeMap),底層

                 都是經過使用Object[]數組來實現的。而String(它們本身包裝在

                 char[]數組中),char數組的大小是不變的。那麼問題就出現了,

                 若是它們的大小是不變的,咱們怎麼能放item記錄到集合中去呢?

                 答案顯而易見:分配更多的數組。因此,不管何時,儘量

                 的給List或者Map分配一個初始容量,就像這樣。

        (5)能用基本類型如Int,long,就不用Integer,Long對象

                 基本類型變量佔用的內存資源比相應對象佔用的少得多,若是沒有

                 必要,最好使用基本變量。

        (6)儘可能少用靜態對象變量

                 靜態變量屬於全局變量,不會被GC回收,它們會一直佔用內存。

        (7)對象不用時最好顯式置爲Null

                 通常而言,爲Null的對象都會被做爲垃圾處理,因此將不用的對象顯

                 式地設爲Null,有利於GC收集器斷定垃圾,從而提升了GC的效

                 率。

        (8)分散對象建立或刪除的時間(我的以爲這個彷佛不太現實)

                 集中在短期內大量建立新對象,特別是大對象,會致使忽然須要大

                 量內存,JVM在面臨這種狀況時,只能進行主GC,以回收內存或

                 整合內存碎片,從而增長主GC的頻率。集中刪除對象,道理也是一

                 樣的。它使得忽然出現了大量的垃圾對象,空閒空間必然減小,從

                 而大大增長了下一次建立新對象時強制主GC的機會。

相關文章
相關標籤/搜索