欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java 垃圾回收機(jī)制詳解及實(shí)例代碼

 更新時(shí)間:2017年02月13日 14:50:18   作者:Java開發(fā)-擱淺  
這篇文章主要介紹了 Java 垃圾回收機(jī)制詳解及實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下

 Java 垃圾回收機(jī)制詳解

乍一看,垃圾回收所做的事情應(yīng)當(dāng)恰如其名——查找并清除垃圾。事實(shí)上卻恰恰相反。垃圾回收會(huì)跟蹤所有仍在使用的對(duì)象,然后將剩余的對(duì)象標(biāo)記為垃圾。牢記了這點(diǎn)之后,我們?cè)賮砩钊氲亓私庀逻@個(gè)被稱為“垃圾回收”的自動(dòng)化內(nèi)存回收在JVM中到底是如何實(shí)現(xiàn)的。

手動(dòng)管理內(nèi)存

在介紹現(xiàn)代版的垃圾回收之前,我們先來簡(jiǎn)單地回顧下需要手動(dòng)地顯式分配及釋放內(nèi)存的那些日子。如果你忘了去釋放內(nèi)存,那么這塊內(nèi)存就無法重用了。這塊內(nèi)存被占有了卻沒被使用。這種場(chǎng)景被稱之為內(nèi)存泄露。

下面是用C寫的一個(gè)手動(dòng)管理內(nèi)存的簡(jiǎn)單例子:

int send_request() {
  size_t n = read_size();
  int *elements = malloc(n * sizeof(int));

  if(read_elements(n, elements) < n) {
    // elements not freed!
    return -1;
  }

  // …

  free(elements)
  return 0;
}

可以看到,你很容易就會(huì)忘了釋放內(nèi)存。內(nèi)存泄露曾經(jīng)是個(gè)非常普遍的問題。你只能通過不斷地修復(fù)自己的代碼來與它們進(jìn)行抗?fàn)?。因此,需要有一種更優(yōu)雅的方式來自動(dòng)釋放無用內(nèi)存,以便減少人為錯(cuò)誤的可能性。這種自動(dòng)化過程又被稱為垃圾回收(簡(jiǎn)稱GC)。

智能指針

自動(dòng)垃圾回收早期的一種實(shí)現(xiàn)便是引用計(jì)數(shù)。你知曉每一個(gè)對(duì)象被引用了幾次,當(dāng)計(jì)數(shù)器歸0的時(shí)候,這個(gè)對(duì)象就可以被安全地回收掉了。C++的共享指針就是一個(gè)非常著名的例子:

int send_request() {
  size_t n = read_size();
  stared_ptr<vector<int>> elements 
       = make_shared<vector<int>&gt();

  if(read_elements(n, elements) < n) {
    return -1;
  }

  return 0;
}

我們使用的sharedptr會(huì)記錄這個(gè)對(duì)象被引用的次數(shù)。如果你將它傳遞給別人則計(jì)數(shù)加一,當(dāng)它離開了作用域后便會(huì)減一。一旦這個(gè)計(jì)數(shù)為0,sharedptr會(huì)自動(dòng)地刪除底層對(duì)應(yīng)的vector。當(dāng)然這只是個(gè)示例,因?yàn)橐灿凶x者指出來了,這個(gè)在現(xiàn)實(shí)中是不太可能出現(xiàn)的,但作為演示是足夠了。

自動(dòng)內(nèi)存管理

在上面的C++代碼中,我們還得顯式地聲明我們需要使用內(nèi)存管理。那如果所有的對(duì)象都采用這個(gè)機(jī)制會(huì)怎樣呢?那簡(jiǎn)直就太方便了,這樣開發(fā)人員便無需 考慮清理內(nèi)存的事情了。運(yùn)行時(shí)會(huì)自動(dòng)知曉哪些內(nèi)存不再使用了,然后釋放掉它。也就是說,它自動(dòng)地回收了這些垃圾。第一代的垃圾回收器是1959年Lisp 引入的,這項(xiàng)技術(shù)迄今為止一直在不斷演進(jìn)。

 引用計(jì)數(shù) 

剛才我們用C++的共享指針?biāo)菔镜南敕梢詰?yīng)用到所有的對(duì)象上來。許多語言比如說Perl, Python以及PHP,采用的都是這種方式。這個(gè)通過一張圖可以很容易說明:

綠色的云代表的是程序中仍在使用的對(duì)象。從技術(shù)層面上來說,這有點(diǎn)像是正在執(zhí)行的某個(gè)方法里面的局部變量,亦或是靜態(tài)變量之類的。不同編程語言的情況可能會(huì)不一樣,因此這并不是我們關(guān)注的重點(diǎn)。

藍(lán)色的圓圈代表的是內(nèi)存中的對(duì)象,可以看到有多少對(duì)象引用了它們。灰色圓圈的對(duì)象是已經(jīng)沒有任何人引用的了。因此,它們屬于垃圾對(duì)象,可以被垃圾回收器清理掉。

看起來還不錯(cuò)對(duì)吧?沒錯(cuò),不過這里存在著一個(gè)重大的缺陷。很容易會(huì)出現(xiàn)一些孤立的環(huán),它們中的對(duì)象都不在任何域內(nèi),但彼此卻互相引用導(dǎo)致引用數(shù)不為0。下面便是一個(gè)例子:

看到了吧,紅色部分其實(shí)就是應(yīng)用程序不再使用的垃圾對(duì)象。由于引用計(jì)數(shù)的缺陷,因此會(huì)存在內(nèi)存泄露。

有幾種方法可以解決這一問題,比如說使用特殊的“弱”引用,或者使用一個(gè)特殊的算法回收循環(huán)引用。之前提到的Perl,Python以及PHP等語言,都是使用類似的方法來回收循環(huán)引用的,不過這已經(jīng)超出本文講述的范圍了。我們準(zhǔn)備詳細(xì)介紹下JVM所采用的方法。

標(biāo)記刪除

首先,JVM對(duì)于對(duì)象可達(dá)性的定義要明確一些。它可不像前面那樣用綠色的云便含糊了事的,而是有著非常明確及具體的垃圾回收根對(duì)象(Garbage Collection Roots)的定義:

  • 局部變量
  • 活動(dòng)線程
  • 靜態(tài)字段
  • JNI引用
  • 其它(后面將會(huì)討論到)

JVM通過標(biāo)記刪除的算法來記錄所有可達(dá)(存活)對(duì)象,同時(shí)確保不可達(dá)對(duì)象的那些內(nèi)存能夠被重用。這包含兩個(gè)步驟:

  • 標(biāo)記是指遍歷所有可達(dá)對(duì)象,然后在本地內(nèi)存中記錄這些對(duì)象的信息
  • 刪除會(huì)確保不可達(dá)對(duì)象的內(nèi)存地址可以在下一次內(nèi)存分配中使用。

JVM中的不同GC算法,比如說Parallel Scavenge,Parallel Mark+Copy, CMS都是這一算法的不同實(shí)現(xiàn),只是各階段略有不同而已,從概念上來講仍然是對(duì)應(yīng)著上面所說的那兩個(gè)步驟。

這種實(shí)現(xiàn)最重要的就是不會(huì)再出現(xiàn)泄露的對(duì)象環(huán)了:

缺點(diǎn)就是應(yīng)用程序的線程需要被暫停才能完成回收,如果引用一直在變的話你是無法進(jìn)行計(jì)數(shù)的。這個(gè)應(yīng)用程序被暫停以便JVM可以收拾家務(wù)的情況又被稱為Stop The World pause(STW)。這種暫停被觸發(fā)的可能性有很多,不過垃圾回收應(yīng)該是最常見的一種。

感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!

相關(guān)文章

  • java動(dòng)態(tài)目錄樹的實(shí)現(xiàn)示例

    java動(dòng)態(tài)目錄樹的實(shí)現(xiàn)示例

    在開發(fā)過程中,常常需要對(duì)目錄結(jié)構(gòu)進(jìn)行操作和展示,本文主要介紹了java動(dòng)態(tài)目錄樹的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-03-03
  • 深扒Java中POJO、VO、DO、DTO、PO、BO、AO、DAO的概念和區(qū)別以及如何應(yīng)用

    深扒Java中POJO、VO、DO、DTO、PO、BO、AO、DAO的概念和區(qū)別以及如何應(yīng)用

    po vo bo dto dao 和 pojo 是軟件開發(fā)中經(jīng)常使用的一些概念,用于設(shè)計(jì)和實(shí)現(xiàn)對(duì)象模型,下面將分別解釋這些概念的含義及其在開發(fā)中的應(yīng)用,這篇文章主要給大家介紹了關(guān)于Java中POJO、VO、DO、DTO、PO、BO、AO、DAO的概念和區(qū)別以及如何應(yīng)用的相關(guān)資料,需要的朋友可以參考下
    2024-08-08
  • Java中的兩種for循環(huán)介紹

    Java中的兩種for循環(huán)介紹

    在學(xué)習(xí)Hibernate的時(shí)候?qū)W習(xí)一種在Java當(dāng)中的for循環(huán),估計(jì)是以前學(xué)習(xí)的時(shí)候沒有記住,忘記了在這里再寫下筆記
    2012-10-10
  • Mybatis中攔截器的簡(jiǎn)單實(shí)現(xiàn)方法

    Mybatis中攔截器的簡(jiǎn)單實(shí)現(xiàn)方法

    這篇文章主要給大家介紹了關(guān)于Mybatis中攔截器的簡(jiǎn)單實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Mybatis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Java8 forEach常用場(chǎng)景代碼實(shí)例

    Java8 forEach常用場(chǎng)景代碼實(shí)例

    這篇文章主要介紹了Java8 forEach常用場(chǎng)景代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Netty客戶端接入流程N(yùn)ioSocketChannel創(chuàng)建解析

    Netty客戶端接入流程N(yùn)ioSocketChannel創(chuàng)建解析

    這篇文章主要為大家介紹了Netty客戶端接入流程N(yùn)ioSocketChannel創(chuàng)建源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-03-03
  • SpringMVC KindEditor在線編輯器之文件上傳代碼實(shí)例

    SpringMVC KindEditor在線編輯器之文件上傳代碼實(shí)例

    這篇文章主要介紹了SpringMVC KindEditor在線編輯器之文件上傳代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-09-09
  • JAVA關(guān)鍵字及作用詳解

    JAVA關(guān)鍵字及作用詳解

    本文主要介紹了Java關(guān)鍵字及作用,具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    2017-02-02
  • Java 動(dòng)態(tài)加載jar和class文件實(shí)例解析

    Java 動(dòng)態(tài)加載jar和class文件實(shí)例解析

    這篇文章主要介紹了Java 動(dòng)態(tài)加載jar和class文件實(shí)例解析,分享了相關(guān)代碼示例,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-02-02
  • Java單鏈表的實(shí)現(xiàn)代碼

    Java單鏈表的實(shí)現(xiàn)代碼

    這篇文章主要介紹了Java單鏈表的實(shí)現(xiàn)代碼的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-07-07

最新評(píng)論