<dfn id="w48us"></dfn><ul id="w48us"></ul>
  • <ul id="w48us"></ul>
  • <del id="w48us"></del>
    <ul id="w48us"></ul>
  • Java的內(nèi)存劃分全解析

    時(shí)間:2024-08-02 02:13:41 JAVA認(rèn)證 我要投稿
    • 相關(guān)推薦

    Java的內(nèi)存劃分全解析

      Java把內(nèi)存劃分成兩種:一種是棧內(nèi)存,一種是堆內(nèi)存。以下是小編整理的Java的內(nèi)存劃分全解析,希望對(duì)大家有所幫助。

      棧內(nèi)存

      存放對(duì)象:函數(shù)中基本類型的變量和對(duì)象的引用變量、靜態(tài)類方法

      特點(diǎn):棧有一個(gè)很重要的特殊性,就是存在棧中的數(shù)據(jù)可以共享。假設(shè)我們同時(shí)定義:

      inta=3;

      intb=3;

      編譯器先處理inta=3;首先它會(huì)在棧中創(chuàng)建一個(gè)變量為a的引用,然后查找棧中是否有3這個(gè)值,如果沒(méi)找到,就將3存放進(jìn)來(lái),然后將a指向3。

      接著處理intb=3;在創(chuàng)建完b的引用變量后,因?yàn)樵跅V幸呀?jīng)有3這個(gè)值,便將b直接指向3。這樣,就出現(xiàn)了a與b同時(shí)均指向3的情況。

      堆內(nèi)存

      存放對(duì)象:用來(lái)存放由new創(chuàng)建的對(duì)象和數(shù)組。

      特點(diǎn):在堆中分配的內(nèi)存,由Java虛擬機(jī)的自動(dòng)垃圾回收器來(lái)管理。

      在堆中產(chǎn)生了一個(gè)數(shù)組或?qū)ο蠛螅可以在棧中定義一個(gè)特殊的變量,讓棧中這個(gè)變量的取值等于數(shù)組或?qū)ο笤诙褍?nèi)存中的首地址,棧中的這個(gè)變量就成了數(shù)組或?qū)ο蟮囊米兞俊?/p>

      引用變量就相當(dāng)于是為數(shù)組或?qū)ο笃鸬囊粋(gè)名稱,以后就可以在程序中使用棧中的引用變量來(lái)訪問(wèn)堆中的數(shù)組或?qū)ο蟆?/p>

      Q:static關(guān)鍵字,是一個(gè)修飾符,用于修飾成員(成員變量和成員函數(shù)),有什么特點(diǎn)

      A:1、想要實(shí)現(xiàn)對(duì)象中的共性數(shù)據(jù)的對(duì)象共享。可以將這個(gè)數(shù)據(jù)進(jìn)行靜態(tài)修飾。

      2、被靜態(tài)修飾的成員,可以直接被類名所調(diào)用。也就是說(shuō),靜態(tài)的成員多了一種調(diào)用方式。類名.靜態(tài)方式。

      3、靜態(tài)隨著類的加載而加載。而且優(yōu)先于對(duì)象存在。

      Java內(nèi)存回收

      Java的內(nèi)存分配和回收也主要在Java的堆上進(jìn)行的,Java的堆中存儲(chǔ)了大量的對(duì)象實(shí)例,所以Java的堆也叫GC堆。

      下面主要說(shuō)一下對(duì)于java堆的內(nèi)存回收 。

      什么樣的內(nèi)存可以回收

      判斷法1:引用計(jì)數(shù)

      方法:每有一個(gè)引用指向這個(gè)對(duì)象,那么這個(gè)對(duì)象的引用計(jì)數(shù)+1,反之,每有一個(gè)引用改變了指向,那么他原來(lái)指向的對(duì)象引用計(jì)數(shù)-1,當(dāng)引用計(jì)數(shù)為0的時(shí)候,這個(gè)對(duì)象也就不可能被使用了那么就可以被回收了

      問(wèn)題:可能會(huì)出現(xiàn)環(huán)狀的引用,導(dǎo)致不可能被使用的對(duì)象永遠(yuǎn)不可能被回收

      示例:

      Class A {

      A a;

      Public static void main(String[] args){

      A gc1 = new A();

      A gc2 = new A();

      Gc1.a = gc2;

      Gc2.a = gc1;

      Gc1= null;

      Gc2 = null;

      }

      Gc1和gc2都被設(shè)置成null了,他們都應(yīng)該被清理,但是因?yàn)間c1的a對(duì)象指向gc2,gc2的a對(duì)象指向gc1,導(dǎo)致他們的引用計(jì)數(shù)永遠(yuǎn)為1,但是他們都永遠(yuǎn)不可能被使用了,所以這種方法存在漏洞

      判斷2:可達(dá)性分析算法

      方法:從一個(gè)叫做GC ROOTS的節(jié)點(diǎn)出發(fā),所有能夠到達(dá)的引用對(duì)象標(biāo)記起來(lái),直到走到完全沒(méi)有引用的地方為止,這樣從這個(gè)節(jié)點(diǎn)連起來(lái)的所有的點(diǎn)(引用鏈),構(gòu)成的路線就是不可回收的,那么所有沒(méi)有被到達(dá)過(guò)的對(duì)象均可以被回收

      什么可以做GC ROOTS:虛擬機(jī)棧(棧幀中的本地變量表)中的引用的對(duì)象、方法區(qū)中類靜態(tài)屬性引用的對(duì)象、方法區(qū)中常量引用的對(duì)象、本地方法棧中JNI引用的對(duì)象

      這些對(duì)象的特點(diǎn):不可變并且隨時(shí)可能被用到,生命周期長(zhǎng)

      補(bǔ)充:可達(dá)性分析的算法,那么沒(méi)有在引用鏈上的對(duì)象都一定會(huì)被清理嗎?不一定。當(dāng)運(yùn)行可達(dá)性分析的算法之后,會(huì)對(duì)所有沒(méi)有在引用鏈上的對(duì)象進(jìn)行一次標(biāo)記和篩選,篩選的條件為:該對(duì)象覆蓋了finallize()方法(這個(gè)方法是GC的時(shí)候如果這個(gè)對(duì)象要被回收則執(zhí)行的方法,但是在Thinking in java中不推薦用來(lái)處理收尾工作),并且這個(gè)方法沒(méi)有被執(zhí)行過(guò),那么就會(huì)把這個(gè)對(duì)象放到一個(gè)低優(yōu)先級(jí)隊(duì)列中執(zhí)行,也就是這個(gè)對(duì)象的最后搶救的機(jī)會(huì),如果這個(gè)時(shí)候這個(gè)對(duì)象把自己和在引用鏈上的引用連了起來(lái),那么他在執(zhí)行完finallize方法之后,再次判斷時(shí)就不會(huì)被清理,否則會(huì)在第二次可達(dá)性判斷的時(shí)候直接清理(因?yàn)閒inallize已經(jīng)執(zhí)行過(guò)一次了),如果沒(méi)有覆蓋這個(gè)方法,那么對(duì)不起,再見(jiàn)

      回收算法介紹:

      回收算法1:標(biāo)記清理(Mark——sweep)算法

      標(biāo)記所有需要回收對(duì)象,然后將他們清理回收

      問(wèn)題:會(huì)產(chǎn)生內(nèi)存碎片

      優(yōu)點(diǎn):不需要暫停所有線程(Stop the world)

      回收算法2:復(fù)制

      標(biāo)記后,將所有不需要回收的對(duì)象全部復(fù)制到一個(gè)空的內(nèi)存中,然后清理剛剛使用的內(nèi)存塊

      問(wèn)題:浪費(fèi)資源,會(huì)有一些內(nèi)存堆無(wú)法被使用

      解決:用在新生代,新生代會(huì)有80%以上的對(duì)象經(jīng)過(guò)一次GC就會(huì)死亡,因此采用Eden + Survivor * 2的辦法,Eden = 8 * Survivor大小(HotSpot默認(rèn)),那么每次使用一個(gè)Eden + 一個(gè)Survivor,然后進(jìn)行復(fù)制清理的時(shí)候,清理Eden + Survivor中,然后將可用的對(duì)象復(fù)制到空閑的Survivor中,然后全部清空前面的使用區(qū),然后使用Eden 和復(fù)制到的Survivor

      又一個(gè)問(wèn)題:如果Survivor不夠怎么辦?向老年代借空間,叫做分配擔(dān)保,不夠存放的對(duì)象會(huì)通過(guò)分配擔(dān)保進(jìn)入老年代

      問(wèn)題:需要 stop the world

      回收算法3:標(biāo)記整理(Mark——compact)

      標(biāo)記后,將可用內(nèi)存向一側(cè)擺放,然后清理掉可用內(nèi)存邊緣外部的所有內(nèi)存區(qū)域

      優(yōu)點(diǎn):沒(méi)有內(nèi)存碎片的問(wèn)題

      問(wèn)題:需要stop the world

      回收算法4:分代收集

      將堆分代(老年代、新生代),老年代采用標(biāo)記整理、標(biāo)記清理等方法,新生代采用復(fù)制方法。

      為什么:因?yàn)槔夏甏蟛糠謱?duì)象是可用的,因此如果采用復(fù)制算法,雖然沒(méi)有內(nèi)存碎片,但是空間浪費(fèi)大,而且大部分對(duì)象沒(méi)有變化,而在新生代使用復(fù)制算法,可以犧牲很小的內(nèi)存空間就獲得較好的效率

      HotSpot中內(nèi)存回收算法

      枚舉根節(jié)點(diǎn)(GC ROOTs)

      Java虛擬機(jī)采用準(zhǔn)確式GC,有一個(gè)OOPmap來(lái)標(biāo)記哪個(gè)位置有個(gè)對(duì)象,這樣在查找引用鏈的時(shí)候可以較快的找齊所有的引用鏈

      Safepoint

      在OOPmap的協(xié)助下,這個(gè)可以快速且準(zhǔn)確的完成枚舉,但是問(wèn)題就是導(dǎo)致這個(gè)oopmap變化的指令非常多,如果為每一條指令生成oopmap,那么會(huì)需要大量額外空間,因此采用在特定點(diǎn)的地方生成,這些點(diǎn)同時(shí)也是safepoint的點(diǎn),那么當(dāng)需要枚舉根節(jié)點(diǎn)的時(shí)候,就讓線程運(yùn)行到這個(gè)地方再停止。

      一種方法:先停止所有線程,然后再讓沒(méi)有到安全點(diǎn)的線程自己跑到安全點(diǎn)再停下來(lái),基本不適用,搶先試中斷

      另一種方法:主動(dòng)式中斷,設(shè)置一個(gè)標(biāo)記,在執(zhí)行的時(shí)候去輪詢,而需要中斷的時(shí)候,直接將這個(gè)位置的內(nèi)存設(shè)置不可達(dá),那么線程就會(huì)進(jìn)入一個(gè)自陷異常,就自己會(huì)中斷

    【Java的內(nèi)存劃分全解析】相關(guān)文章:

    Java內(nèi)存溢出的類型10-03

    客廳設(shè)計(jì)要點(diǎn)全解析07-21

    JAVA垃圾收集算法與內(nèi)存泄露的解決方法12-04

    日本留學(xué)費(fèi)用全解析10-05

    java命令行參數(shù)解析201608-12

    2017高考攝影藝考全解析01-07

    2017藝考動(dòng)畫專業(yè)全解析01-07

    加拿大中學(xué)留學(xué)申請(qǐng)全解析09-10

    ERP人力資源管理全解析08-06

    主站蜘蛛池模板: 国产色婷婷五月精品综合在线| 欧美激情精品久久久久| 国产l精品国产亚洲区在线观看| 狠狠精品干练久久久无码中文字幕| 国产精品色内内在线播放| 香港aa三级久久三级老师2021国产三级精品三级在 | A级精品国产片在线观看| 欧美日韩精品久久久久| 99re66在线观看精品免费| 成人国内精品久久久久一区| 亚洲av午夜成人片精品网站| 久久久久国产成人精品亚洲午夜| 91亚洲精品自在在线观看| 国产成人精品日本亚洲专一区| 亚洲国产另类久久久精品 | 精品人人妻人人澡人人爽人人 | 青青草国产精品久久久久| 精品黑人一区二区三区| 亚洲日韩欧美制服精品二区| 无码人妻精品一区二区三区99不卡 | 欧美日韩精品一区二区三区不卡 | 亚洲国产欧美日韩精品一区二区三区 | 色婷婷在线精品国自产拍| 日本Aⅴ大伊香蕉精品视频| 精品国产91久久久久久久a | 精品人无码一区二区三区| 久久精品视频网| 九九热在线视频观看这里只有精品| 日韩精品专区在线影院重磅 | 精品精品国产理论在线观看| 亚洲午夜久久久精品影院| 欧美精品第欧美第12页| 国产精品污视频| 国产精品1区2区| 国产成人精品免费视频动漫| 1000部精品久久久久久久久| 亚洲AV日韩精品久久久久久久| 777国产盗摄偷窥精品0OOO| 国产精品毛片久久久久久久| 97久久国产亚洲精品超碰热| 国产精品免费观看调教网|