<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      深入理解JVM(③)判斷對象是否還健在?

      前言

      因為Java對象主要存放在Java堆里,所以垃圾收集器(Garbage Collection)在對Java堆進行回收前,第一件事情就是要確定這些對象之中哪些還“存活”著,哪些已經“死去”(不被引用了)。

      判斷對象是否健在的算法

      1.引用計數算法

      引用計數算法,很容易理解,在對象中添加一個引用計數器,每有一個地方引用它時,計數器值就加一;當引用失效是,計數器值就減一;任何時刻計數器為零的對象就是不可以能再被使用的對象
      引用計數算法的原理簡單,判定效率也很高。市面上也確實有一些技術使用的此類算法來判定對象是否存活,像ActionScript 3 的FlashPlayer、Python語言等。但是在主流的Java虛擬機里面都沒有選用引用計算法來管理內存,主要是使用此算法時,必須要配合大量的額外處理才能保證正確的工作,例如要解決對象之間的相互循環引用的問題。

      public class OneTest {
      
          public Object oneTest = null;
      
          private static final int _1MB = 1024 * 1024;
      
          private byte[] bigSize = new byte[256 * _1MB];
      
      
          /**
           * 這個成員屬性的唯一意義就是占點內存,以便能在GC日志中看清楚是否有回收過。
           */
          @Test
          public void testGC(){
      
              OneTest test1 = new OneTest();
              OneTest test2 = new OneTest();
      
              test1.oneTest = test2;
              test2.oneTest = test1;
      
              test1 = null;
              test2 = null;
      
              // 假設在這行發生GC,test1和test2是否能被回收?
              System.gc();
      
          }
      
      }
      

      分析代碼,test1和test2對象都被設置成了null,在后面發生GC的時候,如果按照引用計數算法,這兩個對象雖然都被設置成了null,但是test1引用了test2,test2又引用了test1,所以這兩個對象的引用計數值都不為0,所以都不會被回收,但是真正的實際運行結果是,這兩個對象都被回收了,這也說明HotSpot虛擬機并不是用引用計數法來進行的內存管理。

      2. 可達性分析算法

      當前主流的商用程序語言(Java、C#等),都是通過可達性分析(Reachability Analysis)算法來判斷對象是否存活的。這個算法的基本思路就是通過一一系列稱為“GC Roots” 的根對象作為起始節點集,從這些節點開始根據引用關系向下搜索,搜索走過的的路徑稱為“引用鏈”(Reference Chain),如果某個對象到GC Roots 間沒有任何引用鏈相連,或者從GC Roots 到這個對象不可達時,則證明此對象是不可能再被使用的。
      如下圖,object10、object11、object12這三個對象,雖然互相有關聯,但是它們到GC Roots是不可達的,因此它們會被判定為可回收的對象。
      可達性分析算法
      在Java程序中,固定可作為GC Roots 的對象包括以下幾種:

      • 在虛擬機棧(棧幀中的本地變量表)中引用的對象,譬如各個現場被調用的方法堆棧中使用到的參數、局部變量、臨時變量等。
      • 在方法區中類靜態屬性引用的對象,譬如Java類的引用類型靜態變量。
      • 在方法區中常量引用的對象,譬如字符串常量池(String Table)里的引用。
      • 在本地方法棧中JNI(即通常所說的Native方法)引用的對象。
      • Java虛擬機內部的引用,如基本數據類型對應的Class對象,一些常駐的異常對象(NullPointException、OutOfMemoryError)等,還有系統類加載器。
      • 所有被同步鎖(synchronized關鍵字)持有的對象。
      • 反映Java虛擬機內部情況的JMXBean、JVMTI中注冊的回調、本地代碼緩存等。
        除了這些固定的GC Roots集合以外,根據垃圾收集器以及當前回收的呢村區域不同,還會有其他對象“臨時性”的加入,如果只針對Java堆中某一塊兒區域發起垃圾收集時(例如只針對年輕代的垃圾收集),必須考慮到當前區域內的對象是否有被其他區域的對象所引用,這個時候就需要把這些關聯區域的對象一并加入GC Roots集合中,來保證可達性分析的正確性。

      重申引用

      無論是通過引用計數算法判斷對象的引用數量,還是通過可達性分析算法判斷對象是否引用鏈可達,判斷對象是否存活都和“引用”離不開關系。在JDK1.2之前,Java里對引用的概念是:如果reference類型的數據中存儲的數值代表的是另外一塊兒內存的地址,就稱該reference數據是代表某塊內存、某個對象的引用。
      在JDK1.2版之后,Java對引用的概念進行了擴充,將引用分為強引用(Strongly Reference)、軟引用(Soft Reference)、弱引用(Weak Reference)、虛引用(Phantom Reference)4種,這4種引用強度依次逐漸減弱。

      • 強引用是最傳統的“引用”的定義,指引用復制,即類似
      Object obj = new Object()
      

      這種引用關系。無論在任何情況下,只要強引用關系還存在,垃圾收集器就不會回收掉被引用的對象。

      • 軟引用是用來描述一些還有用,但非必須的對象。在系統發生內存溢出前,會先對軟引用對象進行第二次回收,如果回收后還沒有足夠的內存,才會拋出內存溢出的異常。
      • 弱引用也是用來描述那些非必須的對象,但是它的強度比軟引用更弱一些,弱引用的對象,只能生存到下一次垃圾收集發生為止。當垃圾收集器開始工作,無論當前內存是否足夠,都會回收掉只被弱引用關聯的對象。
      • 虛引用也稱為“幽靈引用”或“幻影引用”,它是最弱的一種引用關系。為一個對象設置虛引用關聯的唯一目的只是為了能在這個對象被收集器回收時收到一個系統通知。

      判斷對象是生是死的過程

      即使在可達性分析算法中,判斷為不可達的對象,也不是“非死不可”的,要真正宣告一個對象死亡,至少要經歷兩次標記過程:

      • 如果第一次對象在進行可達性分析后發現與GC Roots 不可達,將進行第一次標記。
      • 隨后對此對象進行一次是否有必要執行finalize()方法進行篩選,假如對象沒有覆蓋finalize()方法,或者finalize()方法已經被虛擬機調用過,都視為“沒有必要執行”。
        如果對象被判定有必要執行finalize()方法,會將對象放置在一個名為F-Queue的隊列中,并在由一條由虛擬機自動建立的、低調度的線程區執行它們的finalize()方法。但并不承諾一定會等待它們運行結束。

      需要注意的是:任何一個對象的finalize()方法都只會被系統自動調用一次,如果對象面臨第二次回收,它的finalize()方法不會被再次執行。
      還有一點就是Java官方已經明確聲明不推薦手動調用finalize()方法了,因為它的運行代價高昂,不確定性大,無法保證各個對象的調用順序,并且finanlize()能做的所有工作,使用try-finally或其他方式都可以做的更好、更及時。

      回收方法區

      方法區垃圾收集的“性價比”通常比較低,并且方法區回收也有過于苛刻的判定條件。
      方法區的垃圾收集主要回收兩部分內容:廢棄的常量不再使用的類型,回收廢棄常量時,如果當前系統沒有一個常量的值是當前常量值,且虛擬機中也沒有其他地方引用這個常量。如果這個時候發生垃圾回收,常量就會被系統清理出常量池。
      判定一個類型是否屬于“不再使用的類”的條件就比較苛刻了,要同時滿足如下三個條件:

      • 該類所有的實例都已經被回收,也就是Java堆中不存在該類及其任何派生子類的實例。
      • 加載該類的類加載器已經被回收,這個條件除非是經過精心設計的可替換類加載器的場景,如OSGi、JSP的沖加載等,否則通常很難達成的。
      • 該類對應的java.lang.Class對象沒有在任何地方被引用,無法在任何地方通過反射訪問該類的方法。

      同時滿足了上述的三個條件后,也只是被允許進行回收了,關于是否要對類型進行回收還要對虛擬機進行一系列的參數設置,這里就不贅述了,感興趣的可以自己去查詢。

      posted @ 2020-06-06 18:00  紀莫  閱讀(752)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产精品亚洲二区在线看| 97久久久亚洲综合久久| 精品国产中文字幕在线| 国产极品粉嫩馒头一线天| 久久中文字幕无码一区二区| 亚洲午夜福利精品无码不卡| 好吊视频专区一区二区三区| 久久精品熟女亚洲av艳妇| 国产一区二区不卡91| 中文字幕久久六月色综合| 亚洲国产成人av毛片大全| 亚洲av中文一区二区| 精品人妻中文字幕在线| 绍兴市| 成人精品一区日本无码网| 精品国产一区AV天美传媒| 午夜免费无码福利视频麻豆| 免费无码又爽又刺激网站| 狠狠躁夜夜人人爽天96| 中文字幕在线日韩| 日本福利一区二区精品| 国产极品美女高潮无套| 国模雨珍浓密毛大尺度150p| 国产白丝无码免费视频| 亚洲精品欧美综合二区| 国产成人综合在线观看不卡| 国产不卡av一区二区| 两个人日本www免费版| 国产精品久久久久久久久久久久| 噜噜噜噜私人影院| 国内偷自第一区二区三区| 国产超碰无码最新上传| 中文字幕日韩人妻一区| 午夜免费啪视频| 午夜福利影院不卡影院| 亚洲精品一品二品av| 久久久久无码中| 国产精品十八禁一区二区| 狠狠做五月深爱婷婷天天综合| 视频一本大道香蕉久在线播放| 国产精品自在线拍国产手青青机版|