日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

加载文件流_未关闭的文件流会引起内存泄露么?

發(fā)布時(shí)間:2023/12/10 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 加载文件流_未关闭的文件流会引起内存泄露么? 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

專注于Java領(lǐng)域優(yōu)質(zhì)技術(shù),歡迎關(guān)注

來(lái)自:技術(shù)小黑屋

最近接觸了一些面試者,在面試過(guò)程中有涉及到內(nèi)存泄露的問(wèn)題,其中有不少人回答說(shuō),如果文件打開(kāi)后,沒(méi)有關(guān)閉會(huì)導(dǎo)致內(nèi)存泄露。當(dāng)被繼續(xù)追問(wèn),為什么會(huì)導(dǎo)致內(nèi)存泄露時(shí),大部分人都沒(méi)有回答出來(lái)。

本文將具體講一講 文件(流)未關(guān)閉與內(nèi)存泄露的關(guān)系。

什么是內(nèi)存泄露

  • 定義:當(dāng)生命周期長(zhǎng)的實(shí)例L 不合理地持有一個(gè)生命周期短的實(shí)例S,導(dǎo)致S實(shí)例無(wú)法被正常回收

舉例說(shuō)明

上面的代碼可能會(huì)發(fā)生內(nèi)存泄露

  • 我們調(diào)用AppSettings.getInstance.setup()傳入一個(gè)Activity實(shí)例
  • 當(dāng)上述的Activity退出時(shí),由于被AppSettings中屬性mAppContext持有,進(jìn)而導(dǎo)致內(nèi)存泄露。

為什么上面的情況就會(huì)發(fā)生內(nèi)存泄露

  • 以 Android 為例,GC 回收對(duì)象采用GC Roots強(qiáng)引用可到達(dá)機(jī)制。
  • Activity實(shí)例被AppSettings.sInstance持有
  • AppSettings.sInstance由于是靜態(tài),被AppSettings類持有
  • AppSettings類被加載它的類加載器持有
  • 而類加載器就是GC Roots的一種
  • 由于上述關(guān)系導(dǎo)致Activity實(shí)例無(wú)法被回收銷毀。

驗(yàn)證是否引起內(nèi)存泄露

因此,想要證明未關(guān)閉的文件流是否導(dǎo)致內(nèi)存泄露,需要查看文件流是否是GC Roots強(qiáng)引用可到達(dá)。

示例代碼1(輔助驗(yàn)證GC 發(fā)生)

示例代碼2

這里我們這樣操作

  • 點(diǎn)擊textview視圖,觸發(fā)多次testInputStream
  • 過(guò)幾秒后,我們執(zhí)行heap dump。
  • 我們使用 MAT 對(duì)上一步的dump文件進(jìn)行分析(需進(jìn)行格式轉(zhuǎn)換)
  • 分析上圖,我們發(fā)現(xiàn)

    • FileInputStream 只被 FinalizerReference 這個(gè)類(GC Root)持有
    • 上述持有的原因是,FileInputStream重寫了finalize,會(huì)被加入到FinalizerReference的析構(gòu)處理集合
    • 上述引用會(huì)隨著Finalizer守護(hù)線程處理后解除,即FileInputStream實(shí)例徹底銷毀。

    所以,我們?cè)賮?lái)操作一波,驗(yàn)證上面的結(jié)論。

    • 然后利用工具執(zhí)行強(qiáng)制GC回收
    • 過(guò)幾秒后,我們執(zhí)行heap dump。
    • 我們使用 MAT 對(duì)上一步的dump文件進(jìn)行分析(需進(jìn)行格式轉(zhuǎn)換)
    • 堆分析文件,查找MyBufferedReader或者FileInputStream或者InputStreamReader 沒(méi)有發(fā)現(xiàn)這些實(shí)例,說(shuō)明已經(jīng)GC回收
    • 出于謹(jǐn)慎考慮,我們按照包名查找java.io在排除無(wú)關(guān)實(shí)例外,依舊無(wú)法找到testInputStream中的實(shí)例。再次證明已經(jīng)被GC回收

    因而我們可以確定,正常的使用流,不會(huì)導(dǎo)致內(nèi)存泄露的產(chǎn)生。

    當(dāng)然,如果你刻意顯式持有Stream實(shí)例,那就另當(dāng)別論了。

    為什么需要關(guān)閉流

    首先我們看一張圖

    如上圖從左至右有三張表

    • file descriptor table 歸屬于單個(gè)進(jìn)程
    • global file table(又稱open file table) 歸屬于系統(tǒng)全局
    • inode table 歸屬于系統(tǒng)全局

    從一次文件打開(kāi)說(shuō)起

    當(dāng)我們嘗試打開(kāi)文件/path/myfile.txt

    1.從inode table 中查找到對(duì)應(yīng)的文件節(jié)點(diǎn)

    2.根據(jù)用戶代碼的一些參數(shù)(比如讀寫權(quán)限等)在open file table 中創(chuàng)建open file 節(jié)點(diǎn)

    3.將上一步的open file節(jié)點(diǎn)信息保存,在file descriptor table中創(chuàng)建 file descriptor

    4.返回上一步的file descriptor的索引位置,供應(yīng)用讀寫等使用。

    file descriptor 和流有什么關(guān)系

    • 當(dāng)我們這樣FileInputStream("/sdcard/a.txt") 會(huì)獲取一個(gè)file descriptor。
    • 出于穩(wěn)定系統(tǒng)性能和避免因?yàn)檫^(guò)多打開(kāi)文件導(dǎo)致CPU和RAM占用居高的考慮,每個(gè)進(jìn)程都會(huì)有可用的file descriptor 限制。
    • 所以如果不釋放file descriptor,會(huì)導(dǎo)致應(yīng)用后續(xù)依賴file descriptor的行為(socket連接,讀寫文件等)無(wú)法進(jìn)行,甚至是導(dǎo)致進(jìn)程崩潰。
    • 當(dāng)我們調(diào)用FileInputStream.close后,會(huì)釋放掉這個(gè)file descriptor。

    因此到這里我們可以說(shuō),不關(guān)閉流不是內(nèi)存泄露問(wèn)題,是資源泄露問(wèn)題(file descriptor 屬于資源)。

    不手動(dòng)關(guān)閉會(huì)怎樣

    不手動(dòng)關(guān)閉的真的會(huì)發(fā)生上面的問(wèn)題么? 其實(shí)也不完全是。

    因?yàn)閷?duì)于這些流的處理,源代碼中通常會(huì)做一個(gè)兜底處理。以FileInputStream為例

    是的,在finalize方法中有調(diào)用close來(lái)釋放file descriptor.

    但是finalize方法執(zhí)行速度不確定,不可靠

    所以,我們不能依賴于這種形式,還是要手動(dòng)調(diào)用close來(lái)釋放file descriptor。

    關(guān)閉流實(shí)踐

    Java 7 之后,可以使用try-with-resource方式處理

    Kotlin 可以使用use

    當(dāng)然,還有最基礎(chǔ)的手動(dòng)關(guān)閉的形式

    Reference

    • https://stackoverflow.com/questions/26541513/why-is-it-good-to-close-an-inputstream
    • https://www.reddit.com/r/learnjava/comments/577769/why_do_you_need_to_close_streams/

    來(lái)自:https://droidyue.com/blog/2019/06/09/will-unclosed-stream-objects-cause-memory-leaks/

    總結(jié)

    以上是生活随笔為你收集整理的加载文件流_未关闭的文件流会引起内存泄露么?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。