溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎樣深入學(xué)習(xí)JVM堆與JVM棧

發(fā)布時(shí)間:2021-10-23 16:52:49 來(lái)源:億速云 閱讀:160 作者:柒染 欄目:編程語(yǔ)言

今天就跟大家聊聊有關(guān)怎樣深入學(xué)習(xí)JVM堆與JVM棧,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

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

JVM基礎(chǔ)概念:JVM堆與JVM棧

數(shù)據(jù)類型

Java虛擬機(jī)中,數(shù)據(jù)類型可以分為兩類:基本類型和引用類型。基本類型的變量保存原始值,即:他代表的值就是數(shù)值本身;而引用類型的變量保存引用值?!耙弥怠贝砹四硞€(gè)對(duì)象的引用,而不是對(duì)象本身,對(duì)象本身存放在這個(gè)引用值所表示的地址的位置。

基本類型包括:byte,short,int,long,char,float,double,Boolean,returnAddress

引用類型包括:類類型,接口類型和數(shù)組。

JVM堆與JVM棧

JVM堆和JVM棧是程序運(yùn)行的關(guān)鍵,很有必要把他們的關(guān)系說(shuō)清楚。

怎樣深入學(xué)習(xí)JVM堆與JVM棧


JVM棧是運(yùn)行時(shí)的單位,而JVM堆是存儲(chǔ)的單位。

JVM棧解決程序的運(yùn)行問(wèn)題,即程序如何執(zhí)行,或者說(shuō)如何處理數(shù)據(jù);JVM堆解決的是數(shù)據(jù)存儲(chǔ)的問(wèn)題,即數(shù)據(jù)怎么放、放在哪兒。

在Java中一個(gè)線程就會(huì)相應(yīng)有一個(gè)線程JVM棧與之對(duì)應(yīng),這點(diǎn)很容易理解,因?yàn)椴煌木€程執(zhí)行邏輯有所不同,因此需要一個(gè)獨(dú)立的線程JVM棧。而JVM堆則是所有線程共享的。JVM棧因?yàn)槭沁\(yùn)行單位,因此里面存儲(chǔ)的信息都是跟當(dāng)前線程(或程序)相關(guān)信息的。包括局部變量、程序運(yùn)行狀態(tài)、方法返回值等等;而JVM堆只負(fù)責(zé)存儲(chǔ)對(duì)象信息。

為什么要把JVM堆和JVM棧區(qū)分出來(lái)呢?JVM棧中不是也可以存儲(chǔ)數(shù)據(jù)嗎?

***,從軟件設(shè)計(jì)的角度看,JVM棧代表了處理邏輯,而JVM堆代表了數(shù)據(jù)。這樣分開(kāi),使得處理邏輯更為清晰。分而治之的思想。這種隔離、模塊化的思想在軟件設(shè)計(jì)的方方面面都有體現(xiàn)。

第二,JVM堆與JVM棧的分離,使得JVM堆中的內(nèi)容可以被多個(gè)JVM棧共享(也可以理解為多個(gè)線程訪問(wèn)同一個(gè)對(duì)象)。這種共享的收益是很多的。一方面這種共享提供了一種有效的數(shù)據(jù)交互方式(如:共享內(nèi)存),另一方面,JVM堆中的共享常量和緩存可以被所有JVM棧訪問(wèn),節(jié)省了空間。

第三,JVM棧因?yàn)檫\(yùn)行時(shí)的需要,比如保存系統(tǒng)運(yùn)行的上下文,需要進(jìn)行地址段的劃分。由于JVM棧只能向上增長(zhǎng),因此就會(huì)限制住JVM棧存儲(chǔ)內(nèi)容的能力。而JVM堆不同,JVM堆中的對(duì)象是可以根據(jù)需要?jiǎng)討B(tài)增長(zhǎng)的,因此JVM棧和JVM堆的拆分,使得動(dòng)態(tài)增長(zhǎng)成為可能,相應(yīng)JVM棧中只需記錄JVM堆中的一個(gè)地址即可。

第四,面向?qū)ο缶褪荍VM堆和JVM棧的***結(jié)合。其實(shí),面向?qū)ο蠓绞降某绦蚺c以前結(jié)構(gòu)化的程序在執(zhí)行上沒(méi)有任何區(qū)別。但是,面向?qū)ο蟮囊耄沟脤?duì)待問(wèn)題的思考方式發(fā)生了改變,而更接近于自然方式的思考。當(dāng)我們把對(duì)象拆開(kāi),你會(huì)發(fā)現(xiàn),對(duì)象的屬性其實(shí)就是數(shù)據(jù),存放在JVM堆中;而對(duì)象的行為(方法),就是運(yùn)行邏輯,放在JVM棧中。我們?cè)诰帉?xiě)對(duì)象的時(shí)候,其實(shí)即編寫(xiě)了數(shù)據(jù)結(jié)構(gòu),也編寫(xiě)的處理數(shù)據(jù)的邏輯。不得不承認(rèn),面向?qū)ο蟮脑O(shè)計(jì),確實(shí)很美。

在Java中,Main函數(shù)就是JVM棧的起始點(diǎn),也是程序的起始點(diǎn)。

程序要運(yùn)行總是有一個(gè)起點(diǎn)的。同C語(yǔ)言一樣,java中的Main就是那個(gè)起點(diǎn)。無(wú)論什么java程序,找到main就找到了程序執(zhí)行的入口:)

JVM堆中存什么?JVM棧中存什么?

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)槭腔绢愋?,所以不?huì)出現(xiàn)動(dòng)態(tài)增長(zhǎng)的情況——長(zhǎng)度固定,因此JVM棧中存儲(chǔ)就夠了,如果把他存在JVM堆中是沒(méi)有什么意義的(還會(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ù)。最常見(jiàn)的一個(gè)問(wèn)題就是,Java中參數(shù)傳遞時(shí)的問(wèn)題。

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

要說(shuō)明這個(gè)問(wèn)題,先要明確兩點(diǎn):

1.不要試圖與C進(jìn)行類比,Java中沒(méi)有指針的概念

2.程序運(yùn)行永遠(yuǎn)都是在JVM棧中進(jìn)行的,因而參數(shù)傳遞時(shí),只存在傳遞基本類型和對(duì)象引用的問(wèn)題。不會(huì)直接傳對(duì)象本身。

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

但是傳引用的錯(cuò)覺(jué)是如何造成的呢?在運(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ì)象看作為一棵樹(shù),對(duì)象的屬性如果還是對(duì)象,則還是一顆樹(shù)(即非葉子節(jié)點(diǎn)),基本類型則為樹(shù)的葉子節(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)行可以沒(méi)有JVM堆,但是不能沒(méi)有JVM棧。而JVM堆是為JVM棧進(jìn)行數(shù)據(jù)存儲(chǔ)服務(wù),說(shuō)白了JVM堆就是一塊共享的內(nèi)存。不過(guò),正是因?yàn)镴VM堆和JVM棧的分離的思想,才使得Java的垃圾回收成為可能。

Java中,JVM棧的大小通過(guò)-Xss來(lái)設(shè)置,當(dāng)JVM棧中存儲(chǔ)數(shù)據(jù)比較多時(shí),需要適當(dāng)調(diào)大這個(gè)值,否則會(huì)出現(xiàn)java.lang.StackOverflowError異常。常見(jiàn)的出現(xiàn)這個(gè)異常的是無(wú)法返回的遞歸,因?yàn)榇藭r(shí)JVM棧中保存的信息都是方法返回的記錄點(diǎn)。

看完上述內(nèi)容,你們對(duì)怎樣深入學(xué)習(xí)JVM堆與JVM棧有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI