內(nèi)存分配策略中无牵,堆和棧的區(qū)別

根據(jù)編譯原理,程序在運(yùn)行時(shí)的內(nèi)存分配策略有三種:

1.靜態(tài) Static

指在編譯時(shí)就能確定的每個(gè)數(shù)據(jù)目標(biāo)在運(yùn)行時(shí)刻需要的存儲(chǔ)空間需求。因而在編譯的時(shí)候就可以給他們分配固定的存儲(chǔ)空間席镀。 這種數(shù)據(jù)目標(biāo)在編譯時(shí)就為他們分配固定的內(nèi)存。

限制:

  • 代碼中不能有可變數(shù)據(jù)結(jié)構(gòu)夏漱,如數(shù)組豪诲。
  • 代碼中不允許有遞歸或嵌套結(jié)構(gòu)的出現(xiàn)。
public class EaseConstant {
    public static final String MESSAGE_ATTR_IS_VOICE_CALL = "is_voice_call";
    public static final String MESSAGE_ATTR_IS_VIDEO_CALL = "is_video_call";
   
    public static final String MESSAGE_ATTR_IS_BIG_EXPRESSION = "em_is_big_expression";
    public static final String MESSAGE_ATTR_EXPRESSION_ID = "em_expression_id";
   
    public static final String MESSAGE_ATTR_AT_MSG = "em_at_list";
    public static final String MESSAGE_ATTR_VALUE_AT_MSG_ALL = "ALL";

    public static final int CHATTYPE_SINGLE = 1;
    public static final int CHATTYPE_GROUP = 2;
    public static final int CHATTYPE_CHATROOM = 3;
    
    public static final String EXTRA_CHAT_TYPE = "chatType";
    public static final String EXTRA_USER_ID = "userId";
}

2.棧式 Stack

棧式存儲(chǔ)分配可稱為動(dòng)態(tài)存儲(chǔ)分配挂绰,是由一個(gè)類似于堆棧的運(yùn)行棧來(lái)實(shí)現(xiàn)的屎篱,和靜態(tài)存儲(chǔ)分配相反,在棧式存儲(chǔ)方案中扮授,程序?qū)?shù)據(jù)區(qū)的需求在編譯時(shí)是完全未知的芳室,只有到運(yùn)行的時(shí)候才能知道。

指在編譯時(shí)不能確定大小刹勃,但在運(yùn)行的時(shí)候能夠確定,且規(guī)定在運(yùn)行中進(jìn)入一個(gè)程序模塊時(shí)嚎尤,就必須知道該模塊所需要的數(shù)據(jù)區(qū)大小荔仁,才能為其分配內(nèi)存,和我們?cè)跀?shù)據(jù)結(jié)構(gòu)中所知道的棧一樣,內(nèi)存分配為e棧原則乏梁,先進(jìn)后出的原則進(jìn)行分配次洼。

分配是在運(yùn)行時(shí)執(zhí)行的,但是大小是在編譯時(shí)確定的遇骑;

特點(diǎn):
在C/C++中卖毁,所有的方法調(diào)用都是通過(guò)棧來(lái)進(jìn)行的,所有局部變量落萎,形式參數(shù)都是從棧中分配內(nèi)存空間的亥啦。

棧的分配和回收:

棧分配內(nèi)存空間:從棧低向棧頂,依次存儲(chǔ)练链;
椣柰眩回收內(nèi)存空間:修改棧頂指針的位置,完成棧中內(nèi)容銷毀媒鼓,這樣的模式速度很快届吁。

棧 :存放基本數(shù)據(jù)類型,速度快

  • 棧中主要存放一些基本類型的變量(int, short, long, byte, float, double, boolean, char)和對(duì)象句柄绿鸣;
  • 棧的存取速度比堆要快疚沐;
  • 棧數(shù)據(jù)可以共享;
  • 棧的數(shù)據(jù)大小與生存期必須是確定的潮模,缺乏靈活性濒旦。

3.堆式 Heap

指編譯時(shí),運(yùn)行時(shí)模塊入口都不能確定存儲(chǔ)要求的數(shù)據(jù)結(jié)構(gòu)的內(nèi)存分配再登。
比如可變長(zhǎng)度的串和對(duì)象實(shí)例尔邓。
堆由大片的可利用的塊或空閑組成,堆中的內(nèi)存可以按照任意順序分配和釋放锉矢。

堆是在運(yùn)行的時(shí)候梯嗽,請(qǐng)求操作系統(tǒng)分配給自己內(nèi)存,由于從操作系統(tǒng)管理的內(nèi)存分配沽损,所以在分配和銷毀的時(shí)候都要占用時(shí)間灯节,因此對(duì)的效率低下。

堆的優(yōu)點(diǎn):編譯時(shí)不必知道要從堆里分配多少存儲(chǔ)空間绵估,也不必知道存儲(chǔ)的數(shù)據(jù)要在堆里停留多長(zhǎng)時(shí)間鳞滨,因此堆存儲(chǔ)數(shù)據(jù)時(shí),靈活性比較大粘姜;

在面向?qū)ο缶幊讨械廖拢咽潜夭豢缮俚模驗(yàn)槊嫦驅(qū)ο蟮亩鄳B(tài)性缝左,多態(tài)變量所需的存儲(chǔ)空間只有在運(yùn)行時(shí)創(chuàng)建了對(duì)象之后才能確定亿遂。

堆: 用new建立浓若,垃圾自動(dòng)回收負(fù)責(zé)回收

  • 堆是一個(gè)"運(yùn)行時(shí)"數(shù)據(jù)區(qū),類實(shí)例化的對(duì)象就是從堆上去分配空間的蛇数;
  • 在堆上分配空間是通過(guò)"new"等指令建立的挪钓;
  • Java針對(duì)堆的操作和C++的區(qū)別就是,Java不需要在空間不用的時(shí)候來(lái)顯式的釋放耳舅;
  • Java的堆是由Java的垃圾回收機(jī)制來(lái)負(fù)責(zé)處理的碌上,堆是動(dòng)態(tài)分配內(nèi)存大小,垃圾收集器可以自動(dòng)回收不再使用的內(nèi)存空間浦徊。
  • 但缺點(diǎn)是馏予,因?yàn)樵谶\(yùn)行時(shí)動(dòng)態(tài)分配內(nèi)存,所以內(nèi)存的存取速度較慢辑畦。

4. 堆和棧的比較

比較方面
功能的比較 存放對(duì)象 執(zhí)行程序
存儲(chǔ)內(nèi)容 new關(guān)鍵字創(chuàng)建的內(nèi)容 局部變量吗蚌,形式參數(shù)
存儲(chǔ)速度 快(所以用來(lái)執(zhí)行程序)

5.JVM中的堆棧

JVM是基于堆棧的虛擬機(jī),JVM中的堆棧是兩塊不同的存儲(chǔ)區(qū)域纯出。

JVM為每個(gè)線程程都分配了一個(gè)堆和棧蚯妇,所以對(duì)于java程序來(lái)說(shuō),程序的運(yùn)行是通過(guò)對(duì)堆棧的操作來(lái)完成的暂筝。

JVM 堆 JVM 棧
是存儲(chǔ)的單位 是運(yùn)行時(shí)的單位
JVM堆解決的是數(shù)據(jù)存儲(chǔ)的問(wèn)題箩言,即數(shù)據(jù)怎么放、放在哪兒焕襟。 JVM棧解決程序的運(yùn)行問(wèn)題陨收,即程序如何執(zhí)行,或者說(shuō)如何處理數(shù)據(jù);
JVM堆中存的是對(duì)象鸵赖。 JVM棧中存的是基本數(shù)據(jù)類型和JVM堆中對(duì)象的引用

一個(gè)對(duì)象的大小是不可估計(jì)的务漩,或者說(shuō)是可以動(dòng)態(tài)變化的,但是在JVM棧中它褪,一個(gè)對(duì)象只對(duì)應(yīng)了一個(gè)4btye的引用(JVM堆JVM棧分離的好處:))饵骨。

為什么不把基本類型放JVM堆中呢?
因?yàn)榛绢愋推湔加玫目臻g一般是1~8個(gè)字節(jié)(需要空間比較少),而且因?yàn)槭腔绢愋兔4颍圆粫?huì)出現(xiàn)動(dòng)態(tài)增長(zhǎng)的情況(長(zhǎng)度固定)居触,因此JVM棧中存儲(chǔ)就夠了,如果把他存在JVM堆中是沒有什么意義的(還會(huì)浪費(fèi)空間老赤,后面說(shuō)明)轮洋。可以這么說(shuō)抬旺,基本類型和對(duì)象的引用都是存放在JVM棧中弊予,而且都是幾個(gè)字節(jié)的一個(gè)數(shù),因此在程序運(yùn)行時(shí)嚷狞,他們的處理方式是統(tǒng)一的块促。

但是基本類型荣堰、對(duì)象引用和對(duì)象本身就有所區(qū)別了床未,因?yàn)橐粋€(gè)是JVM棧中的數(shù)據(jù)一個(gè)是JVM堆中的數(shù)據(jù)的引用竭翠。最常見的一個(gè)問(wèn)題就是,Java中參數(shù)傳遞時(shí)的問(wèn)題薇搁。

JAVA中堆棧的應(yīng)用

Java中的參數(shù)傳遞時(shí)傳值呢?還是傳引用?

要說(shuō)明這個(gè)問(wèn)題斋扰,先要明確兩點(diǎn):
1.不要試圖與C進(jìn)行類比,Java中沒有指針的概念
2.程序運(yùn)行永遠(yuǎn)都是在JVM棧中進(jìn)行的啃洋,因而參數(shù)傳遞時(shí)传货,只存在傳遞基本類型和對(duì)象引用的問(wèn)題,不會(huì)直接傳對(duì)象本身宏娄。

總結(jié):傳遞的是對(duì)象的引用值或是基本類型的值问裕;

明確以上兩點(diǎn)后。Java在方法調(diào)用傳遞參數(shù)時(shí)孵坚,因?yàn)闆]有指針粮宛,所以它都是進(jìn)行傳值調(diào)用(這點(diǎn)可以參考C的傳值調(diào)用)。因此卖宠,很多書里面都說(shuō)Java是進(jìn)行傳值調(diào)用巍杈,這點(diǎn)沒有問(wèn)題,而且也簡(jiǎn)化的C中復(fù)雜性扛伍。

但是傳引用的錯(cuò)覺是如何造成的呢?
在運(yùn)行JVM棧中筷畦,基本類型和引用的處理是一樣的,都是傳值刺洒,所以鳖宾,如果是傳引用的方法調(diào)用,也同時(shí)可以理解為“傳引用值”的傳值調(diào)用逆航,即引用的處理跟基本類型是完全一樣的鼎文。但是當(dāng)進(jìn)入被調(diào)用方法時(shí),被傳遞的這個(gè)引用的值纸泡,被程序解釋(或者查找)到JVM堆中的對(duì)象漂问,這個(gè)時(shí)候才對(duì)應(yīng)到真正的對(duì)象。如果此時(shí)進(jìn)行修改女揭,修改的是引用對(duì)應(yīng)的對(duì)象蚤假,而不是引用本身,即:修改的是JVM堆中的數(shù)據(jù)吧兔。所以這個(gè)修改是可以保持的了磷仰。

對(duì)象,從某種意義上說(shuō)境蔼,是由基本類型組成的灶平∷磐ǎ可以把一個(gè)對(duì)象看作為一棵樹,對(duì)象的屬性如果還是對(duì)象逢享,則還是一顆樹(即非葉子節(jié)點(diǎn))罐监,基本類型則為樹的葉子節(jié)點(diǎn)。程序參數(shù)傳遞時(shí)瞒爬,被傳遞的值本身都是不能進(jìn)行修改的弓柱,但是,如果這個(gè)值是一個(gè)非葉子節(jié)點(diǎn)(即一個(gè)對(duì)象引用)侧但,則可以修改這個(gè)節(jié)點(diǎn)下面的所有內(nèi)容矢空。

JVM堆和JVM棧中,JVM棧是程序運(yùn)行最根本的東西禀横。程序運(yùn)行可以沒有JVM堆屁药,但是不能沒有JVM棧。而JVM堆是為JVM棧進(jìn)行數(shù)據(jù)存儲(chǔ)服務(wù)柏锄,說(shuō)白了JVM堆就是一塊共享的內(nèi)存酿箭。不過(guò),正是因?yàn)镴VM堆和JVM棧的分離的思想绢彤,才使得Java的垃圾回收成為可能七问。

JVM中線程堆棧
線程(thread),有時(shí)被稱為輕量級(jí)進(jìn)程(Lightweight Process,LWP)茫舶,是程序執(zhí)行流的最小單元械巡。一個(gè)標(biāo)準(zhǔn)的線程由線程ID,當(dāng)前指令指針(PC)饶氏,寄存器集合和堆棧組成讥耗。另外,線程是進(jìn)程中的一個(gè)實(shí)體疹启,是被系統(tǒng)獨(dú)立調(diào)度和分派的基本單位古程,線程自己不擁有系統(tǒng)資源,只擁有一點(diǎn)在運(yùn)行中必不可少的資源喊崖,但它可與同屬一個(gè)進(jìn)程的其它線程共享進(jìn)程所擁有的全部資源挣磨。一個(gè)線程可以創(chuàng)建和撤消另一個(gè)線程,同一進(jìn)程中的多個(gè)線程之間可以并發(fā)執(zhí)行荤懂。由于線程之間的相互制約茁裙,致使線程在運(yùn)行中呈現(xiàn)出間斷性。線程也有就緒节仿、阻塞和運(yùn)行三種基本狀態(tài)晤锥。  線程是程序中一個(gè)單一的順序控制流程.在單個(gè)程序中同時(shí)運(yùn)行多個(gè)線程完成不同的工作,稱為多線程。

1矾瘾、線程與進(jìn)程
線程和進(jìn)程的區(qū)別在于,子進(jìn)程和父進(jìn)程有不同的代碼和數(shù)據(jù)空間,而多個(gè)線程則共享數(shù)據(jù)空間,每個(gè)線程有自己的執(zhí)行堆棧和程序計(jì)數(shù)器為其執(zhí)行上下文.多線程主要是為了節(jié)約CPU時(shí)間,發(fā)揮利用,根據(jù)具體情況而定. 線程的運(yùn)行中需要使用計(jì)算機(jī)的內(nèi)存資源和CPU

通常在一個(gè)進(jìn)程中可以包含若干個(gè)線程女轿,它們可以利用進(jìn)程所擁有的資源。在引入線程的操作系統(tǒng)中壕翩,通常都是把進(jìn)程作為分配資源的基本單位蛉迹,而把線程作為獨(dú)立運(yùn)行和獨(dú)立調(diào)度的基本單位。由于線程比進(jìn)程更小戈泼,基本上不擁有系統(tǒng)資源婿禽,故對(duì)它的調(diào)度所付出的開銷就會(huì)小得多赏僧,能更高效的提高系統(tǒng)內(nèi)多個(gè)程序間并發(fā)執(zhí)行的程度大猛。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市淀零,隨后出現(xiàn)的幾起案子挽绩,更是在濱河造成了極大的恐慌,老刑警劉巖驾中,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件唉堪,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡肩民,警方通過(guò)查閱死者的電腦和手機(jī)唠亚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)持痰,“玉大人灶搜,你說(shuō)我怎么就攤上這事」で希” “怎么了割卖?”我有些...
    開封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)患雏。 經(jīng)常有香客問(wèn)我鹏溯,道長(zhǎng),這世上最難降的妖魔是什么淹仑? 我笑而不...
    開封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任丙挽,我火速辦了婚禮,結(jié)果婚禮上匀借,老公的妹妹穿的比我還像新娘颜阐。我一直安慰自己,他們只是感情好怀吻,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開白布瞬浓。 她就那樣靜靜地躺著,像睡著了一般蓬坡。 火紅的嫁衣襯著肌膚如雪猿棉。 梳的紋絲不亂的頭發(fā)上磅叛,一...
    開封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音萨赁,去河邊找鬼弊琴。 笑死,一個(gè)胖子當(dāng)著我的面吹牛杖爽,可吹牛的內(nèi)容都是我干的敲董。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼慰安,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼腋寨!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起化焕,我...
    開封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤萄窜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后撒桨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體查刻,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年凤类,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了穗泵。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谜疤,死狀恐怖佃延,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情茎截,我是刑警寧澤苇侵,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站企锌,受9級(jí)特大地震影響榆浓,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜撕攒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一陡鹃、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧抖坪,春花似錦萍鲸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春嘿期,著一層夾襖步出監(jiān)牢的瞬間品擎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工备徐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留萄传,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓蜜猾,卻偏偏與公主長(zhǎng)得像秀菱,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蹭睡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 從三月份找實(shí)習(xí)到現(xiàn)在衍菱,面了一些公司,掛了不少棠笑,但最終還是拿到小米梦碗、百度、阿里蓖救、京東、新浪印屁、CVTE循捺、樂(lè)視家的研發(fā)崗...
    時(shí)芥藍(lán)閱讀 42,240評(píng)論 11 349
  • JVM內(nèi)存模型Java虛擬機(jī)(Java Virtual Machine=JVM)的內(nèi)存空間分為五個(gè)部分,分別是: ...
    光劍書架上的書閱讀 2,504評(píng)論 2 26
  • 在函數(shù)中定義的一些基本類型的變量和對(duì)象的引用變量都在函數(shù)的棧內(nèi)存中分配雄人。 當(dāng)在一段代碼塊定義一個(gè)變量時(shí)从橘,Java就...
    木有魚丸啦閱讀 553評(píng)論 0 0
  • Java把內(nèi)存分成兩種,一種叫做棧內(nèi)存础钠,一種叫做堆內(nèi)存 在函數(shù)中定義的一些基本類型的變量和對(duì)象的引用變量都是在函數(shù)...
    keyu88888閱讀 1,291評(píng)論 3 47
  • 在開始分享這個(gè)故事前香府,我想問(wèn)大家?guī)讉€(gè)很有趣的問(wèn)題。首先码倦,第一個(gè)問(wèn)題企孩,年輕的你們,可曾有過(guò)這樣一種豪情袁稽,那就是勿璃,心想...
    多爾Z先生閱讀 152評(píng)論 0 0