在Java中智嚷,堆與棧都是內(nèi)存中存放數(shù)據(jù)的地方。變量分為基本數(shù)據(jù)類型和引用類型纺且,基本數(shù)據(jù)類型的變量(int盏道、short、long载碌、byte猜嘱、float、double嫁艇、boolea朗伶、char等)以及對(duì)象的引用,其內(nèi)存都分配在棧上步咪,變量除了作用域就會(huì)自動(dòng)釋放论皆,而引用類型的變量,其內(nèi)存分配在堆上或者常量池(例如字符串常量和基本數(shù)據(jù)類型常量)中猾漫,需要通過new等方式進(jìn)行創(chuàng)建纯丸。
棧內(nèi)存的管理是通過壓棧和彈棧操作來完成的,以棧幀為基本單位來管理程序的調(diào)用關(guān)系静袖,每當(dāng)由函數(shù)調(diào)用時(shí)觉鼻,都會(huì)通過壓棧方式創(chuàng)建新的棧幀,每當(dāng)函數(shù)調(diào)用結(jié)束后都會(huì)通過彈棧的方式釋放棧幀队橙。
堆內(nèi)存用來存放運(yùn)行時(shí)創(chuàng)建的對(duì)象坠陈。一般來講,通過new關(guān)鍵字創(chuàng)建出來的對(duì)象都存放到堆內(nèi)存中捐康。由于JVM是基于堆棧的虛擬機(jī)仇矾,而每個(gè)java程序都運(yùn)行在一個(gè)單獨(dú)的JVM實(shí)例上,每一個(gè)實(shí)例唯一對(duì)應(yīng)一個(gè)堆解总,一個(gè)java程序內(nèi)的多個(gè)線程也就運(yùn)行在同一個(gè)單獨(dú)的JVM實(shí)例上贮匕,因此這些線程之間會(huì)共享堆內(nèi)存,因此多線程在訪問堆中的數(shù)據(jù)時(shí)需要堆數(shù)據(jù)進(jìn)行同步花枫。
在堆中產(chǎn)生了一個(gè)數(shù)組或?qū)ο蠛罂萄危€可以在棧中定義一個(gè)特殊的變量掏膏,讓棧中的這個(gè)變量的取值等于數(shù)組或?qū)ο笤诙褍?nèi)存中的首地址,棧中的這個(gè)變量就成了數(shù)據(jù)或?qū)ο蟮囊米兞慷匦俊R米兞烤拖喈?dāng)于是為數(shù)組或?qū)ο笃鸬囊粋€(gè)名稱馒疹,以后就可以在程序中使用棧中的引用變量來訪問堆中的數(shù)組或?qū)ο蟆_@就是java中引用的用法
從堆和棧的功能及作用來比較乙墙,堆主要用來存放對(duì)象颖变,棧主要用來執(zhí)行程序的。相較于堆听想,棧的存取速度更快腥刹,但棧的大小和生命周期必須是確定的,因此缺乏一定的靈活性汉买。而堆卻可以在運(yùn)行時(shí)動(dòng)態(tài)地分配內(nèi)存衔峰,生存期不用提前告訴編譯器,但這樣導(dǎo)致了其存取速度的緩慢录别。