java你可能不知道的事(2)--堆和栈
為什么80%的碼農(nóng)都做不了架構(gòu)師?>>> ??
在java語(yǔ)言的學(xué)習(xí)和使用當(dāng)中你可能已經(jīng)了解或者知道堆和棧,但是你可能沒(méi)有完全的理解它們。今天我們就一起來(lái)學(xué)習(xí)堆、棧的特點(diǎn)以及它們的區(qū)別。認(rèn)識(shí)了這個(gè)之后,你可能對(duì)java有更深的理解。
Java堆內(nèi)存(Heap Memory)
堆內(nèi)存在Java運(yùn)行時(shí)主要去回收對(duì)象和JRE的類。當(dāng)我們創(chuàng)建了一個(gè)對(duì)象(也就是 new一個(gè)對(duì)象),在堆內(nèi)存就會(huì)為對(duì)象分配一個(gè)空間,Java垃圾回收器(GC)運(yùn)行在堆內(nèi)存里,一旦發(fā)現(xiàn)沒(méi)有任何地方引用到這個(gè)對(duì)象,就釋放這個(gè)對(duì)象所占的內(nèi)存。
被創(chuàng)建的對(duì)象存在于堆內(nèi)存,并且擁有全局權(quán)限,能被應(yīng)用的任何地方引用到。
Java棧內(nèi)存(Stack Memory)
堆內(nèi)存是單線程執(zhí)行的,它的空間比堆內(nèi)存空間要小。它里面會(huì)包括定義在方法里的、短時(shí)間存在的局部變量,這些局部變量總是引用到堆內(nèi)存的對(duì)象。堆內(nèi)存還有個(gè)特點(diǎn)就是后進(jìn)先出。當(dāng)一個(gè)方法被調(diào)用之后,在棧內(nèi)存就會(huì)為這個(gè)方法產(chǎn)生一個(gè)內(nèi)存區(qū)域來(lái)保存方法里的基本數(shù)據(jù)類型數(shù)據(jù)和引用了堆內(nèi)存中對(duì)象的局部變量。當(dāng)這個(gè)方法執(zhí)行完畢,這個(gè)塊沒(méi)有用了,就會(huì)被垃圾回收器回收,接著繼續(xù)下一個(gè)方法。
加深理解
先來(lái)看一段簡(jiǎn)單的代碼
public class TestMemory {public static void main(String[] args) {int i = 666;//line1Object object = new Object();//line2TestMemory testMemory = new TestMemory();//line3testMemory.test(object);//line4} //line5private void test(Object params){//line6String str = params.toString();//line7System.out.println(str);//line8} } //line9下面這張圖片展示了上面代碼的內(nèi)存信息。
1、當(dāng)程序運(yùn)行時(shí),JVM會(huì)先加載運(yùn)行時(shí)的類和我們自己寫的類信息,這些類信息加載后存在堆內(nèi)存當(dāng)中。
2、接著進(jìn)入到main方法,第一行l(wèi)ine1創(chuàng)建了一個(gè)基本數(shù)據(jù)類型i=666,所以創(chuàng)建了一個(gè)main方法的內(nèi)存塊,它里面同時(shí)存放了i=666;
3、接著line2和line3的位置
Object object = new Object();
TestMemory testMemory = new TestMemory();創(chuàng)建了兩個(gè)局部變量,object和testMemory,同時(shí)在堆里存放了兩個(gè)新的對(duì)象Object和TestMemory。(每次我們new 一個(gè)對(duì)象都會(huì)在堆區(qū)產(chǎn)生一塊內(nèi)存區(qū)給它分配空間)。同時(shí)object和testMemory引用了new出來(lái)的對(duì)象。
4、現(xiàn)在到了line4,test方法了,當(dāng)調(diào)用到test方法的時(shí)候,在棧的頂層創(chuàng)建了一塊test()方法的內(nèi)存區(qū)(我們說(shuō)過(guò)棧的特點(diǎn)就是后進(jìn)先出),由于在 Java里的傳遞是值傳遞,所以就有了參數(shù)object產(chǎn)生了一個(gè)新的引用。
5、最后調(diào)用了toString產(chǎn)生了一個(gè)字符串常量存放在了String pool里,并且str 引用了它。(如果你有String類感興趣,你可能喜歡 》 Java你可能不知道的事系列1_String類
6、當(dāng)test方法結(jié)束,它里面的變量也就被GC回收掉了。接著main方法也就結(jié)束。Java在運(yùn)行時(shí)釋放這些內(nèi)存并結(jié)束程序的運(yùn)行。
總結(jié)
1、當(dāng)一個(gè)對(duì)象被創(chuàng)建,總是會(huì)在堆內(nèi)存為它分配空間并且存儲(chǔ),如果有賦值就會(huì)將變量引用到對(duì)象。而棧內(nèi)存就是存放這些引用對(duì)象的局部變量。
2、棧內(nèi)存的生命周期很短,而堆內(nèi)存從程序執(zhí)行開(kāi)始到結(jié)束一只都需要工作。因?yàn)闂?nèi)存沒(méi)當(dāng)執(zhí)行完一個(gè)方法,它們所占的內(nèi)存區(qū)就會(huì)被釋放。而堆內(nèi)存里的對(duì)象只有在沒(méi)有任何變量引用到它的時(shí)候才可能會(huì)被釋放。
3、棧內(nèi)存大小相比于堆內(nèi)存非常小。但是它相對(duì)于堆內(nèi)存又比較快。
轉(zhuǎn)載于:https://my.oschina.net/313155/blog/637706
總結(jié)
以上是生活随笔為你收集整理的java你可能不知道的事(2)--堆和栈的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Mybatis源码研究5:数据源的实现
- 下一篇: vim的使用技巧