Java堆棧的理解

概述

先Copy一個(gè)概念:JVM是基于堆棧的虛擬機(jī)。JVM為每個(gè)新創(chuàng)建的線程都分配一個(gè)堆棧.也就是說,對(duì)于一個(gè)Java程序來說,它的運(yùn)行就是通過對(duì)堆棧的操作來完成的。堆棧以幀為單位保存線程的狀態(tài)。JVM對(duì)堆棧只進(jìn)行兩種操作:以幀為單位的壓棧和出棧操作。

例子分析

堆是用來存儲(chǔ)new出來的對(duì)象,也就是真實(shí)對(duì)象的存儲(chǔ)地方。棧是用來存儲(chǔ)基本變量、局部變量及對(duì)象的引用的。

舉個(gè)來說明吧


class User {
    private int id;
    private String name;
    
    public User(int sid, String sname) {
        this.id = sid;
        this.name = sname;
    }
}

public void test() {
    int a = 10;
    int b = 10;
    b  = 12;
    String c = "hello";
    String d = new String("hello");
    User user = new User(10, "hello");
}

基本變量類型都是存儲(chǔ)在棧中的,所以int型的a、b、c都存在棧中。具體的操作再來分析下:

int a = 10會(huì)檢查棧中有沒有10這個(gè)值,沒有就創(chuàng)建了一個(gè)10的值,再創(chuàng)建了a去指向10。

int b = 10同樣會(huì)檢查棧中有沒有10這個(gè)值,發(fā)現(xiàn)已經(jīng)存在,則創(chuàng)建b指向已存在的10。在棧中,變量值是可以共享的。

b = 12檢查棧中有沒有12這個(gè)值,沒有就創(chuàng)建一個(gè)12的值,再把b的指向12,這樣也不會(huì)影響a的值。

說到String時(shí),先說說JVM有一個(gè)常量存儲(chǔ)區(qū)域,是用來存常量的,像代碼定義直接雙引號(hào)中的內(nèi)容就是存在常量存儲(chǔ)區(qū)域的。String不是基本變量類型。

String c = "hello"會(huì)先到常量存儲(chǔ)區(qū)域找hello,如果沒有,就在常量存儲(chǔ)區(qū)域創(chuàng)建hello值,棧中創(chuàng)建一個(gè)c指向常量區(qū)域的hello。

String d = new String("hello")是new一String對(duì)象,會(huì)先到常量區(qū)域檢查有沒hello值,如果有,就在堆中生成hello的一個(gè)對(duì)象副本,如果沒有就會(huì)在常量區(qū)先創(chuàng)建hello,再在堆中生成一個(gè)副本。在棧中生成d,指向堆中的hello對(duì)象,d是對(duì)象的引用。

User user = new User(10, "hello"),會(huì)構(gòu)造函數(shù),構(gòu)造函數(shù)里的sid,sname是局部變量,會(huì)存儲(chǔ)在棧中,指向的值是棧中的10和常量存儲(chǔ)中的hello。在堆中會(huì)有new User這個(gè)對(duì)象,在棧中會(huì)有user這個(gè)對(duì)象的引用。這里要說一下,sid,sname是構(gòu)造方法執(zhí)行完后,會(huì)自動(dòng)從棧中移除,而成員變量id,name是對(duì)象的屬性,會(huì)在堆中存在,需要等JAVA自動(dòng)回收機(jī)制進(jìn)行回收。

當(dāng)執(zhí)行完test方法后,棧中的基礎(chǔ)變量和值及對(duì)象引用都會(huì)被自動(dòng)移除,釋放內(nèi)存。

通過例子應(yīng)該可以比較好理解哪些數(shù)據(jù)存在堆中,哪些數(shù)據(jù)存在棧中了。

總結(jié)

堆分配內(nèi)存時(shí),大小和生存期都是不確定的,要生成的時(shí)候才知道,遵循先進(jìn)先出的原則,讀取速度比較慢。數(shù)據(jù)不能共享,每new一次都是一個(gè)新的對(duì)象。要由JAVA的垃圾回收機(jī)制來回收,所以容易造成內(nèi)存多高。

棧分配內(nèi)存時(shí)數(shù)據(jù)的大小和生存期是確定的,在編譯時(shí)就知道了,遵循先進(jìn)后出的原則,讀取速度快,接近寄存器了。數(shù)據(jù)可以共享,節(jié)省內(nèi)存,也比較快。在生存期結(jié)束后會(huì)自動(dòng)釋放,效率更高。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容