国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

JVM源碼分析之FinalReference完全解讀

開發 開發工具
JAVA對象引用體系除了強引用之外,出于對性能、可擴展性等方面考慮還特地實現了四種其他引用:SoftReference、WeakReference、PhantomReference、FinalReference,本文主要想講的是FinalReference,因為我們在使用內存分析工具比如zprofiler、mat等在分析一些oom的heap的時候,經常能看到 java.lang.ref.Finalizer占用的內存大小遠遠排在前面,而這個類占用的內存大小又和我們這次的主角FinalReference有著密不可分的關系。

[[181424]]

概述

JAVA對象引用體系除了強引用之外,出于對性能、可擴展性等方面考慮還特地實現了四種其他引用:SoftReference、WeakReference、PhantomReference、FinalReference,本文主要想講的是FinalReference,因為我們在使用內存分析工具比如zprofiler、mat等在分析一些oom的heap的時候,經常能看到 java.lang.ref.Finalizer占用的內存大小遠遠排在前面,而這個類占用的內存大小又和我們這次的主角FinalReference有著密不可分的關系。

對于FinalReference及關聯的內容,我們可能有如下印象:

  • 自己代碼里從沒有使用過
  • 線程dump之后,我們能看到一個叫做Finalizer的java線程
  • 偶爾能注意到java.lang.ref.Finalizer的存在
  • 我們在類里可能會寫finalize方法

那FinalReference到底存在的意義是什么,以怎樣的形式和我們的代碼相關聯呢,這是本文要理清的問題。

JDK中的FinalReference

首先我們看看FinalReference在JDK里的實現:

大家應該注意到了類訪問權限是package的,這也就意味著我們不能直接去對其進行擴展,但是JDK里對此類進行了擴展實現java.lang.ref.Finalizer,這個類也是我們在概述里提到的,而此類的訪問權限也是package的,并且是final的,意味著真的不能被擴展了,接下來的重點我們圍繞java.lang.ref.Finalizer展開(PS:后續講Finalizer相關的其實也就是在說FinalReference)

Finalizer的構造函數

從構造函數上我們獲得下面的幾個關鍵信息 * private:意味著我們在外面無法自己構建這類對象 * finalizee參數:FinalReference指向的對象引用 * 調用add方法:將當前對象插入到Finalizer對象鏈里,鏈里的對象和Finalizer類靜態相關聯,言外之意是在這個鏈里的對象都無法被gc掉,除非將這種引用關系剝離掉(因為Finalizer類無法被unload)。

雖然外面無法創建Finalizer對象,但是注意到有一個register的靜態方法,在方法里會創建這種對象,同時將這個對象加入到Finalizer對象鏈里,這個方法是被vm調用的,那么問題來了,vm在什么情況下會調用這個方法呢?

Finalizer對象何時被注冊到Finalizer對象鏈里

類其實有挺多的修飾,比如final,abstract,public等等,如果一個類有final修飾,我們就說這個類是一個final類,上面列的都是語法層面我們可以顯示標記的,在jvm里其實還給類標記其他一些符號,比如finalizer,表示這個類是一個finalizer類(為了和java.lang.ref.Fianlizer類進行區分,下文要提到的finalizer類的地方都說成f類),gc在處理這種類的對象的時候要做一些特殊的處理,如在這個對象被回收之前會調用一下它的finalize方法。

如何判斷一個類是不是一個f類

在講這個問題之前,我們先來看下java.lang.Object里的一個方法

在Object類里定義了一個名為finalize的空方法,這意味著Java世界里的所有類都會繼承這個方法,甚至可以覆寫該方法,并且根據方法覆寫原則,如果子類覆蓋此方法,方法訪問權限都是至少是protected級別的,這樣其子類就算沒有覆寫此方法也會繼承此方法。

而判斷當前類是否是一個f類的標準并不僅僅是當前類是否含有一個參數為空,返回值為void的名為finalize的方法,而另外一個要求是finalize方法必須非空,因此我們的Object類雖然含有一個finalize方法,但是并不是一個f類,Object的對象在被gc回收的時候其實并不會去調用它的finalize方法。

需要注意的是我們的類在被加載過程中其實就已經被標記為是否為f類了(遍歷所有方法,包括父類的方法,只要有一個非空的參數為空返回void的finalize方法就認為是一個f類)。

f類的對象何時傳到Finalizer.register方法

對象的創建其實是被拆分成多個步驟的,比如A a=new A(2)這樣一條語句對應的字節碼如下:

先執行new分配好對象空間,然后再執行invokespecial調用構造函數,jvm里其實可以讓用戶選擇在這兩個時機中的任意一個將當前對象傳遞給Finalizer.register方法來注冊到Finalizer對象鏈里,這個選擇依賴于RegisterFinalizersAtInit這個vm參數是否被設置,默認值為true,也就是在調用構造函數返回之前調用Finalizer.register方法,如果通過-XX:-RegisterFinalizersAtInit關閉了該參數,那將在對象空間分配好之后就將這個對象注冊進去。

另外需要提一點的是當我們通過clone的方式復制一個對象的時候,如果當前類是一個f類,那么在clone完成的時候將調用Finalizer.register方法進行注冊。

hotspot如何實現f類對象在構造函數執行完畢后調用Finalizer.register

這個實現比較有意思,在這里簡單提一下,我們知道一個構造函數執行的時候,會去調用父類的構造函數,主要是為了能對繼承自父類的屬性也能做初始化,那么任何一個對象的初始化最終都會調用到Object的空構造函數里(任何空的構造函數其實并不空,會含有三條字節碼指令,如下代碼所示),為了不對所有的類的構造函數都做埋點調用Finalizer.register方法,hotspot的實現是在Object這個類在做初始化的時候將構造函數里的return指令替換為_return_register_finalizer指令,該指令并不是標準的字節碼指令,是hotspot擴展的指令,這樣在處理該指令的時候調用Finalizer.register方法,這樣就在侵入性很小的情況下***地解決了這個問題。

f類對象的GC回收

FinalizerThread線程

在Finalizer類的clinit方法(靜態塊)里我們看到它會創建了一個FinalizerThread的守護線程,這個線程的優先級并不是***的,意味著在cpu很緊張的情況下其被調度的優先級可能會受到影響

這個線程主要就是從queue里取Finalizer對象,然后執行該對象的runFinalizer方法,這個方法主要是將Finalizer對象從Finalizer對象鏈里剝離出來,這樣意味著下次gc發生的時候就可能將其關聯的f對象gc掉了,***將這個Finalizer對象關聯的f對象傳給了一個native方法invokeFinalizeMethod

其實invokeFinalizeMethod方法就是調了這個f對象的finalize方法,看到這里大家應該恍然大悟了,整個過程都串起來了

f對象的finalize方法拋出異常會導致FinalizeThread退出嗎

不知道大家有沒有想過如果f對象的finalize方法拋了一個沒捕獲的異常,這個FinalizerThread會不會退出呢,細心的讀者看上面的代碼其實就可以找到答案,在runFinalizer方法里對Throwable的異常都進行了捕獲,因此不可能出現FinalizerThread因異常未捕獲而退出的情況。

f對象的finalize方法會執行多次嗎

如果我們在f對象的finalize方法里重新將當前對象賦值出去,變成可達對象,當這個f對象再次變成不可達的時候還會被執行finalize方法嗎?答案是否定的,因為在執行完***次finalize方法之后,這個f對象已經和之前的Finalizer對象關系剝離了,也就是下次gc的時候不會再發現Finalizer對象指向該f對象了,自然也就不會調用這個f對象的finalize方法了。

Finalizer對象何時被放到ReferenceQueue里

除了這里要說的環節之外,整個過程大家應該都比較清楚了。

當gc發生的時候,gc算法會判斷f類對象是不是只被Finalizer類引用(f類對象被Finalizer對象引用,然后放到Finalizer對象鏈里),如果這個類僅僅被Finalizer對象引用的時候,說明這個對象在不久的將來會被回收了現在可以執行它的finalize方法了,于是會將這個Finalizer對象放到Finalizer類的ReferenceQueue里,但是這個f類對象其實并沒有被回收,因為Finalizer這個類還對他們持有引用,在gc完成之前,jvm會調用ReferenceQueue里的lock對象的notify方法(當ReferenceQueue為空的時候,FinalizerThread線程會調用ReferenceQueue的lock對象的wait方法直到被jvm喚醒),此時就會執行上面FinalizeThread線程里看到的其他邏輯了。

Finalizer導致的內存泄露

這里舉一個簡單的例子,我們使用挺廣的socket通信,SocksSocketImpl的父類其實就實現了finalize方法:

其實這么做的主要目的是萬一用戶忘記關閉socket了,那么在這個對象被回收的時候能主動關閉socket來釋放一些系統資源,但是如果真的是用戶忘記關閉了,那這些socket對象可能因為FinalizeThread遲遲沒有執行到這些socket對象的finalize方法,而導致內存泄露,這種問題我們碰到過多次,需要特別注意的是對于已經沒有地方引用的這些f對象,并不會在最近的那一次gc里馬上回收掉,而是會延遲到下一個或者下幾個gc時才被回收,因為執行finalize方法的動作無法在gc過程中執行,萬一finalize方法執行很長呢,所以只能在這個gc周期里將這個垃圾對象重新標活,直到執行完finalize方法從queue里刪除,這樣下次gc的時候就真的是漂浮垃圾了會被回收,因此給大家的一個建議是千萬不要在運行期不斷創建f對象,不然會很悲劇。

Finalizer的客觀評價

上面的過程基本對Finalizer的實現細節進行完整剖析了,java里我們看到有構造函數,但是并沒有看到析構函數一說,Finalizer其實是實現了析構函數的概念,我們在對象被回收前可以執行一些『收拾性』的邏輯,應該說是一個特殊場景的補充,但是這種概念的實現給我們的f對象生命周期以及gc等帶來了一些影響:

  • f對象因為Finalizer的引用而變成了一個臨時的強引用,即使沒有其他的強引用了,還是無法立即被回收
  • f對象至少經歷兩次GC才能被回收,因為只有在FinalizerThread執行完了f對象的finalize方法的情況下才有可能被下次gc回收,而有可能期間已經經歷過多次gc了,但是一直還沒執行f對象的finalize方法
  • cpu資源比較稀缺的情況下FinalizerThread線程有可能因為優先級比較低而延遲執行f對象的finalize方法
  • 因為f對象的finalize方法遲遲沒有執行,有可能會導致大部分f對象進入到old分代,此時容易引發old分代的gc,甚至fullgc,gc暫停時間明顯變長
  • f對象的finalize方法被調用了,但是這個對象其實還并沒有被回收,雖然可能在不久的將來會被回收

【本文是51CTO專欄作者李嘉鵬的原創文章,轉載請通過微信公眾號(你假笨,id:lovestblog)聯系作者本人獲取授權】

戳這里,看該作者更多好文

責任編輯:武曉燕 來源: 你假笨
相關推薦

2020-05-26 18:50:46

JVMAttachJava

2017-01-11 14:02:32

JVM源碼內存

2017-01-11 14:19:26

JVM源碼All

2017-02-27 11:48:58

JVM源碼分析Java

2020-07-21 14:19:18

JVM編程語言

2024-10-31 09:24:42

2021-03-11 08:10:48

JVM對象的創建School

2011-05-26 10:05:48

MongoDB

2010-09-27 10:30:42

JVM對象生命周期

2023-02-26 08:42:10

源碼demouseEffect

2012-09-20 10:07:29

Nginx源碼分析Web服務器

2021-07-06 09:29:38

Cobar源碼AST

2021-03-23 09:17:58

SpringMVCHttpServletJavaEE

2024-06-13 07:55:19

2011-05-26 16:18:51

Mongodb

2020-10-30 08:35:23

Java Virtua

2022-09-30 15:35:47

json 文件前端開源

2021-07-14 09:18:19

Python插值算法

2020-07-09 07:00:00

HashMap

2023-09-08 08:42:01

數據場景項目
點贊
收藏

51CTO技術棧公眾號

99在线视频首页| 欧美大片黄色| 鲁鲁在线中文| 舔着乳尖日韩一区| 欧美亚洲一区三区| 国产原创精品在线| 视频在线观看91| 欧美自拍视频在线观看| 欧美日韩尤物久久| 91精品国产色综合久久 | 国产精品亚洲专一区二区三区| 亚洲一区二区不卡免费| 91av成人在线| 久久精品女人天堂av免费观看| 日韩av一区二区三区| 亚洲精品免费av| 精品一区二区三| 亚洲精品乱码久久久久久久久| 欧美国产乱视频| 亚洲综合婷婷久久| 久久久综合视频| 18性欧美xxxⅹ性满足| 高清一区二区| 欧美日产国产成人免费图片| 久久免费福利| 中文字幕中文字幕中文字幕亚洲无线| 欧美成人免费大片| 成年免费网站| 午夜一区二区三区视频| 国产区在线视频| 欧美精品一区二区精品网| 17videosex性欧美| 日韩在线观看成人| 亚洲涩涩av| 精品一区二区视频| 成人国产精品久久| 美女精品久久久| 国产综合久久久| 欧美变态tickle挠乳网站| 成年女人在线看片| 国内精久久久久久久久久人| 乱中年女人伦av一区二区| 影音先锋久久| 蜜月aⅴ免费一区二区三区| 成人午夜大片| 成人羞羞国产免费| 最新国产精品久久久| 先锋影音一区二区三区| 国产精品一区二区91| 亚洲一本大道| 亚洲精品综合久久中文字幕| 亚洲一区二区电影| 久久久久久欧美精品色一二三四| 国产精品亚洲专一区二区三区| 在线观看视频污| 日韩一区精品视频| 99热手机在线| 亚洲精品一区二区三区影院| 欧美日韩国产免费观看视频| 偷拍视频一区二区| 一区二区三区91| 视频二区不卡| 久久国产主播精品| 亚洲精品国产精品乱码不99| 国产精品实拍| 国产精品视频久久久| www.av亚洲| 亚洲 国产 日韩 综合一区| 中文天堂在线一区| abab456成人免费网址| 欧美精品一区二区三区在线看午夜 | 粉嫩久久久久久久极品| 欧美一区二区三区电影在线观看| 日韩高清在线免费观看| 色在人av网站天堂精品| 日本中文字幕一区二区有限公司| 写真福利理论片在线播放| 欧美激情免费看| 不卡的av中国片| 9.1麻豆精品| 国产91|九色| 91亚洲精品一区二区乱码| 六月婷婷久久| 91成人网在线| 丝袜美腿一区二区三区| 欧美人体视频xxxxx| 国产福利片一区二区| 日韩精品一二三四区| 亚洲天堂1区| 日韩精品一区二区三区不卡| 国产精品国产三级国产三级人妇 | 国内自拍一区| 日本电影一区二区在线观看| 99在线高清视频在线播放| 欧美自拍偷拍一区| 激情文学综合丁香| 国产一区精品二区| 国产1区2区3区| 亚洲一区美女视频在线观看免费| 欧美性欧美巨大黑白大战| 精品一区二区国语对白| 狼人天天伊人久久| 色哟哟免费在线观看| 国产一区二区片| 热re99久久精品国产66热| 5月丁香婷婷综合| 国产综合色激情| 国产h色视频在线观看| 国产一区二区免费电影| 欧美国产日韩在线观看| 欧美1区免费| 中文成人在线| 国产成人午夜| 97国产精东麻豆人妻电影| 欧美日韩一区二区三区高清 | 91精品国产麻豆国产自产在线| 成人一区二区在线观看| 一级毛片在线| www.日日操| 久久久精彩视频| 国产成人亚洲综合91| 91麻豆精品视频| 国产日韩精品视频一区二区三区 | 国产伦精品一区二区三区在线播放| av女优在线| 婷婷六月激情| 69堂免费视频| 日韩精品久久久毛片一区二区| 一区二区三区在线视频播放| 国产.欧美.日韩| 日本大胆欧美人术艺术动态| 一区三区视频| 91精品久久久久久久蜜月| 天堂av一区二区三区在线播放| 24小时免费看片在线观看| 91九色在线porn| 导航福利在线| 成人毛片高清视频观看| 99色精品视频| 国产成人手机视频| 亚洲一区二区蜜桃| 日韩中文字幕免费在线| 久久久久久久久久网| 国产一级大片免费看| 亚洲熟妇av日韩熟妇在线| 日韩中文字幕三区| 99热在线这里只有精品| 日韩有码在线电影| 欧美专区日韩专区| 亚洲女人天堂视频| 亚洲第一页中文字幕| 日韩一二三区视频| 欧美一区二区三区免费| 色一情一伦一子一伦一区| 欧美日韩国产精品一区| 精品国产一区二区三区噜噜噜| 91精品网站在线观看| 深夜福利一区二区三区| 精品国产一区二| 久草在线成人| 日韩电影网址| 日韩大片在线永久免费观看网站| 18视频免费网址在线观看| 国产美女一区视频| rebdb初裸写真在线观看| 日韩高清成人| 一区二区三区亚洲变态调教大结局 | 91av视频导航| 成人午夜激情网| 日本免费一区二区三区| 老太脱裤子让老头玩xxxxx| 国产情侣av自拍| 偷拍25位美女撒尿视频在线观看| 久久大胆人体| av在线日韩| 日韩av密桃| 国内精品伊人久久久久av一坑| 亚洲综合免费观看高清完整版在线 | 欧美日韩国产成人在线| 国内揄拍国内精品少妇国语| 国产精品99一区| 中文字幕一区二区中文字幕| 激情丁香婷婷| huan性巨大欧美| 日本女优一区| 久久美女艺术照精彩视频福利播放| 精品久久久精品| 久久精品免费电影| 欧美一级二级三级| 一个人看的www一区| av在线不卡精品| 欧美日韩天堂| 国产精品美女久久久久aⅴ国产馆 国产精品美女久久久久av爽李琼 国产精品美女久久久久高潮 | 亚洲aⅴ天堂av在线电影软件| 四虎最新网站| 亚洲欧洲二区| 国产激情精品久久久第一区二区| 日本道免费精品一区二区三区| 中文字幕av一区二区三区| 欧美电影免费观看完整版|