日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > 綜合技術 > 單例模式討論篇:單例模式與垃圾回收

單例模式討論篇:單例模式與垃圾回收

來源:程序員人生   發布時間:2017-02-04 09:30:54 閱讀次數:3004次

  Jvm的垃圾回收機制到底會不會回收掉長時間不用的單例模式對象,這的確是1個比較有爭議性的問題。將這1部份內容單獨成篇的目的也是為了與廣大博友廣泛的討論1下這個問題。為了能讓更多的人看到這篇文章,請各位博友看完文章以后,點1下“頂”,讓本篇文章排名盡可能的靠前。筆者在此謝過。

討論命題:當1個單例的對象久長不用時,會不會被jvm的垃圾搜集機制回收。

        首先說1下為何會產生這1疑問,筆者本人再此之前歷來沒有斟酌過垃圾回收對單例模式的影響,直到去年讀了1本書,《設計模式之禪》秦小波著。在書中提到在j2ee利用中,jvm垃圾回收機制會把久長不用的單例類對象當作垃圾,并在cpu空閑的時候對其進行回收。之前讀過的幾本設計模式的書,包括《Java與模式》,書中都沒有提到jvm垃圾回收機制對單例的影響。并且在工作進程中,也沒有過單例對象被回收的經歷,加上工作中很多先輩曾告誡過筆者:盡可能不要聲明太多的靜態屬性,由于這些靜態屬性被加載后不會被釋放。因此對jvm垃圾搜集會回收單例對象這1說法持懷疑態度。漸漸地,發現在同事中和網上的技術人員中,對這1問題也基本上是鮮明的對峙兩派。那末到底jvm會不會回收久長不用的單例對象呢。

        對這1問題,筆者本人的觀點是:不會回收。

下面給出本人的測試代碼

[java] view plain copy
  1. class Singleton {  
  2.     private byte[] a = new byte[6*1024*1024];  
  3.     private static Singleton singleton = new Singleton();  
  4.     private Singleton(){}  
  5.       
  6.     public static Singleton getInstance(){  
  7.         return singleton;  
  8.     }  
  9. }  
  10.   
  11. class Obj {  
  12.     private byte[] a = new byte[3*1024*1024];  
  13. }  
  14.   
  15. public class Client{  
  16.     public static void main(String[] args) throws Exception{  
  17.         Singleton.getInstance();  
  18.         while(true){  
  19.             new Obj();  
  20.         }  
  21.     }  
  22. }  

        本段程序的目的是摹擬j2ee容器,首先實例化單例類,這個單例類占6M內存,然后程序進入死循環,不斷的創建對象,逼迫jvm進行垃圾回收,然后視察垃圾搜集信息,如果進行垃圾搜集后,內存依然大于6M,則說明垃圾回收不會回收單例對象。

        運行本程序使用的虛擬機是hotspot虛擬機,也就是我們使用的最多的java官方提供的虛擬機,俗稱jdk,版本是jdk1.6.0_12

        運行時vm arguments參數為:-verbose:gc -Xms20M -Xmx20M,意思是每次jvm進行垃圾回收時顯示內存信息,jvm的內存設為固定20M。

運行結果:

……

[Full GC 18566K->6278K(20352K), 0.0101066 secs]

[GC 18567K->18566K(20352K), 0.0001978 secs]

[Full GC 18566K->6278K(20352K), 0.0088229 secs]

……

        從運行結果中可以看到總有6M空間沒有被搜集。因此,筆者認為,最少在hotspot虛擬機中,垃圾回收是不會回收單例對象的。

        后來查閱了1些相干的資料,hotspot虛擬機的垃圾搜集算法使用根搜索算法。這個算法的基本思路是:對任何“活”的對象,1定能終究追溯到其存活在堆棧或靜態存儲區當中的援用。通過1系列名為根(GC Roots)的援用作為出發點,從這些根開始搜索,經過1系列的路徑,如果可以到達java堆中的對象,那末這個對象就是“活”的,是不可回收的。可以作為根的對象有:

  • 虛擬機棧(棧楨中的本地變量表)中的援用的對象。
  • 方法區中的類靜態屬性援用的對象。
  • 方法區中的常量援用的對象。
  • 本地方法棧中JNI的援用的對象。

        方法區是jvm的1塊內存區域,用來寄存類相干的信息。很明顯,java中單例模式創建的對象被自己類中的靜態屬性所援用,符合第2條,因此,單例對象不會被jvm垃圾搜集。

        雖然jvm堆中的單例對象不會被垃圾搜集,但是單例類本身如果長時間不用會不會被搜集呢?由于jvm對方法區也是有垃圾搜集機制的。如果單例類被搜集,那末堆中的對象就會失去到根的路徑,必定會被垃圾搜集掉。對此,筆者查閱了hotspot虛擬機對方法區的垃圾搜集方法,jvm卸載類的判定條件以下:

  • 該類所有的實例都已被回收,也就是java堆中不存在該類的任何實例。
  • 加載該類的ClassLoader已被回收。
  • 該類對應的java.lang.Class對象沒有任何地方被援用,沒法在任何地方通過反射訪問該類的方法。

        只有3個條件都滿足,jvm才會在垃圾搜集的時候卸載類。明顯,單例的類不滿足條件1,因此單例類也不會被卸載。也就是說,只要單例類中的靜態援用指向jvm堆中的單例對象,那末單例類和單例對象都不會被垃圾搜集,根據根搜索算法,對象是不是會被垃圾搜集與未被使用時間長短無關,僅僅在于這個對象是否是“活”的。假設1個對象久長未使用而被回收,那末搜集算法應當是最近最長未使用算法,最近最長未使用算法1般用在操作系統的內外存交換中,如果用在虛擬機垃圾回收中,豈不是太不安全了?以上是筆者的觀點。

        因此筆者的觀點是:在hotspot虛擬機1.6版本中,除非人為地斷開單例中靜態援用到單例對象的聯接,否則jvm垃圾搜集器是不會回收單例對象的。

        期待各位博友的發言。

 

參考文獻

Java虛擬機規范

Java hotspot虛擬機內存管理

Java編程思想

Java與模式

設計模式

設計模式之禪

深入理解java虛擬機

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 久久精品小视频 | 伊人天天| av在线免费网址 | 久久久久97 | 国产成人精品久久二区二区 | 91精品国产91久久久久久 | 成人免费视频网站在线看 | 亚洲国产精品久久久久秋霞不卡 | 男人天堂视频网 | 黄色在线观看视频网站 | 国产专区一区 | 99激情网| 99久久精品免费一区 | 欧美视频一 | 在线看片日韩 | 国产精品久久一区二区三区 | 亚洲精品在线免费看 | 成人免费视频视频 | 在线看av的网址 | 日韩免费福利视频 | 国产精品国产三级国产在线观看 | 日韩视频不卡 | 福利一区福利二区 | 激情五月视频 | 日韩精品中文字幕一区二区三区 | 久久久久久久久国产精品 | 免费在线观看av网站 | 青草久久网 | 日韩精品一区二区在线观看 | 精品一级 | 最新国产精品 | 草久在线 | 欧美一级毛片视频 | 亚洲福利视频一区 | 精品中文字幕一区二区三区 | 午夜激情视频 | 欧美精品免费在线观看 | 伊人天天操 | 国产精品观看 | 日日摸夜夜添夜夜添国产精品 | 精品久久久久久久 |