可以做代發(fā)貨源的網(wǎng)站seo外包公司怎么樣
如何判斷堆上的對(duì)象沒(méi)有被引用?
常見(jiàn)的有兩種判斷方法:引用計(jì)數(shù)法和可達(dá)性分析法。
引用計(jì)數(shù)法會(huì)為每個(gè)對(duì)象維護(hù)一個(gè)引用計(jì)數(shù)器,當(dāng)對(duì)象被引用時(shí)加1,取消引用時(shí)減1。
引用計(jì)數(shù)法的優(yōu)點(diǎn)是實(shí)現(xiàn)簡(jiǎn)單,缺點(diǎn)有兩點(diǎn):
1.每次引用和取消引用都需要維護(hù)計(jì)數(shù)器,對(duì)系統(tǒng)性能會(huì)有一定的影響
2.存在循環(huán)引用問(wèn)題,所謂循環(huán)引用就是當(dāng)A引用B,B同時(shí)引用A時(shí)會(huì)出現(xiàn)對(duì)象無(wú)法回收的問(wèn)題。
可達(dá)性分析算法
Java使用的是可達(dá)性分析算法來(lái)判斷對(duì)象是否可以被回收??蛇_(dá)性分析將對(duì)象分為兩類:垃圾回收的根對(duì)象(GC
Root)和普通對(duì)象,對(duì)象與對(duì)象之間存在引用關(guān)系。
下圖中A到B再到C和D,形成了一個(gè)引用鏈,可達(dá)性分析算法指的是如果從某個(gè)到GC Root對(duì)象是可達(dá)的,對(duì)象就
不可被回收。
可達(dá)性分析算法
哪些對(duì)象被稱之為GC Root對(duì)象呢?
? 線程Thread對(duì)象,引用線程棧幀中的方法參數(shù)、局部變量等。
? 系統(tǒng)類加載器加載的java.lang.Class對(duì)象,引用類中的靜態(tài)變量。
? 監(jiān)視器對(duì)象,用來(lái)保存同步鎖synchronized關(guān)鍵字持有的對(duì)象。
? 本地方法調(diào)用時(shí)使用的全局對(duì)象。
如何判斷堆上的對(duì)象有沒(méi)有被引用?
引用計(jì)數(shù)法會(huì)為每個(gè)對(duì)象維護(hù)一個(gè)引用計(jì)數(shù)器,當(dāng)對(duì)象被引用時(shí)加1,取消引用時(shí)減
1,存在循環(huán)引用問(wèn)題所以Java沒(méi)有使用這種方法。
Java使用的是可達(dá)性分析算法來(lái)判斷對(duì)象是否可以被回收。可達(dá)性分析將對(duì)象分為兩
類:垃圾回收的根對(duì)象(GC Root)和普通對(duì)象。
可達(dá)性分析算法指的是如果從某個(gè)到GC Root對(duì)象是可達(dá)的,對(duì)象就不可被回收。最
常見(jiàn)的是GC Root對(duì)象會(huì)引用棧上的局部變量和靜態(tài)變量導(dǎo)致對(duì)象不可回收
JVM 中都有哪些引用類型
? 強(qiáng)引用,JVM中默認(rèn)引用關(guān)系就是強(qiáng)引用,即是對(duì)象被局部變量、靜態(tài)變量等GC Root關(guān)聯(lián)的對(duì)象引用,只要
這層關(guān)系存在,普通對(duì)象就不會(huì)被回收。
? 軟引用,軟引用相對(duì)于強(qiáng)引用是一種比較弱的引用關(guān)系,如果一個(gè)對(duì)象只有軟引用關(guān)聯(lián)到它,當(dāng)程序內(nèi)存不足
時(shí),就會(huì)將軟引用中的數(shù)據(jù)進(jìn)行回收。軟引用主要在緩存框架中使用。
? 弱引用,弱引用的整體機(jī)制和軟引用基本一致,區(qū)別在于弱引用包含的對(duì)象在垃圾回收時(shí),不管內(nèi)存夠不夠都
會(huì)直接被回收,弱引用主要在ThreadLocal中使用。
? 虛引用(幽靈引用/幻影引用),不能通過(guò)虛引用對(duì)象獲取到包含的對(duì)象。虛引用唯一的用途是當(dāng)對(duì)象被垃圾回
收器回收時(shí)可以接收到對(duì)應(yīng)的通知。直接內(nèi)存中為了及時(shí)知道直接內(nèi)存對(duì)象不再使用,從而回收內(nèi)存,使用了
虛引用來(lái)實(shí)現(xiàn)。
? 終結(jié)器引用,終結(jié)器引用指的是在對(duì)象需要被回收時(shí),終結(jié)器引用會(huì)關(guān)聯(lián)對(duì)象并放置在Finalizer類中的引用隊(duì)
列中,在稍后由一條由FinalizerThread線程從隊(duì)列中獲取對(duì)象,然后執(zhí)行對(duì)象的finalize方法,在對(duì)象第二次
被回收時(shí),該對(duì)象才真正的被回收
ThreadLocal中為什么要使用弱引用?
ThreadLocal可以在線程中存放線程的本地變量,保證數(shù)據(jù)的線程安全。
ThreadLocal中是這樣去保存對(duì)象的:
1、在每個(gè)線程中,存放了一個(gè)ThreadLocalMap對(duì)象,本質(zhì)上就是一個(gè)數(shù)組實(shí)現(xiàn)的哈希表,里邊存放多個(gè)Entry對(duì)象。
2、每個(gè)Entry對(duì)象繼承自弱引用,內(nèi)部存放ThreadLocal對(duì)象。同時(shí)用強(qiáng)引用,引用保存的ThreadLocal對(duì)應(yīng)的value值。
以代碼為例:
threadLocal.set(new User(1,“main線程對(duì)象”));
User user = threadLocal.get();
不再使用Threadlocal對(duì)象時(shí), threadlocal = null;由于是弱引用,那么在垃圾回收之后,ThreadLocal對(duì)象就可以被
回收。
此時(shí)還有Entry對(duì)象和value對(duì)象沒(méi)有能被回收,所以在ThreadLocal類的set、get、remove方法中,在某些特定條件滿
足的情況下,會(huì)主動(dòng)刪除這兩個(gè)對(duì)象。
如果一直不調(diào)用set、get、remove方法或者調(diào)用了沒(méi)有滿足條件,這部分對(duì)象就會(huì)出現(xiàn)內(nèi)存泄漏。強(qiáng)烈建議在
ThreadLocal不再使用時(shí),調(diào)用remove方法回收將Entry對(duì)象的引用關(guān)系去掉,這樣就可以回收這兩個(gè)對(duì)象了
ThreadLocal中為什么要使用弱引用?
當(dāng)threadlocal對(duì)象不再使用時(shí),使用弱引用可以讓對(duì)象被回收;因?yàn)閮H有弱引用沒(méi)
有強(qiáng)引用的情況下,對(duì)象是可以被回收的。
弱引用并沒(méi)有完全解決掉對(duì)象回收的問(wèn)題,Entry對(duì)象和value值無(wú)法被回收,所以合
理的做法是手動(dòng)調(diào)用remove方法進(jìn)行回收,然后再將threadlocal對(duì)象的強(qiáng)引用解除