App下載

初步了解JavaJVM 及堆內(nèi)存和棧內(nèi)存的概念和區(qū)別

猿友 2021-07-15 17:17:43 瀏覽數(shù) (2974)
反饋

學(xué)習(xí)Java語(yǔ)言需要學(xué)習(xí)一些和Java相關(guān)的底層原理,這將有利之后對(duì)于Java代碼的理解和使用。本文將著重介紹Java中的JVM和堆棧內(nèi)存的概念和區(qū)別。

JVM

JVM(全稱Java Virtual Machine),也就是Java虛擬機(jī)。

Java程序在運(yùn)行的時(shí)候都要開(kāi)辟一個(gè)空間,也就是說(shuō)任何軟件在運(yùn)行的時(shí)候都需要開(kāi)辟空間,同樣JVM也不例外,也需要開(kāi)辟空間。JVM運(yùn)行時(shí)在內(nèi)存中開(kāi)辟的內(nèi)存區(qū)域,啟動(dòng)時(shí)在這片區(qū)域內(nèi)自己還會(huì)進(jìn)行更細(xì)致的劃分,因?yàn)樘摂M機(jī)中每片內(nèi)存處理的方式都不一樣,所以要分別單獨(dú)進(jìn)行管理。

JVM內(nèi)存的劃分主要是下列五個(gè):

  1. 寄存器
  2. 本地方法去
  3. 方法區(qū)
  4. 棧內(nèi)存
  5. 堆內(nèi)存

棧內(nèi)存

棧內(nèi)存里面存儲(chǔ)的都是局部變量。

什么是局部變量?凡是定義在方法中的都是局部變量,for循環(huán)內(nèi)定義的也是局部變量。

先加載函數(shù)才能進(jìn)行局部變量的定義,所以在方法進(jìn)棧后,然后再定義變量,變量是有自己的作用域,一旦離開(kāi)這個(gè)作用域,變量就會(huì)馬上被釋放。也因此,棧內(nèi)存的更新速度非???,這也是因?yàn)榫植孔兞康纳芷诙己芏獭?/p>


堆內(nèi)存

堆內(nèi)存里面存儲(chǔ)的是數(shù)組和對(duì)象。(數(shù)組也算是對(duì)象的一種。)
什么是對(duì)象?凡是?new?建立的都是在堆中,堆中存放的都是實(shí)體(也就是對(duì)象)。
實(shí)體用于封裝數(shù)據(jù),而是封裝了多個(gè),如果一個(gè)數(shù)據(jù)消失,這個(gè)實(shí)體卻沒(méi)消失,則還可以使用。所以堆是不會(huì)隨時(shí)釋放的,但是棧就不一樣了,棧里面存放的都是單個(gè)變量,變量被釋放了,就消失了。堆里的實(shí)體雖然不會(huì)被釋放,但會(huì)被Java垃圾回收機(jī)制當(dāng)做垃圾不定時(shí)的收取。

例子:
?int[] arr = new int[3];?在內(nèi)存中是怎樣被定義的?
棧內(nèi)存和堆內(nèi)存圖例1
如圖所示,主函數(shù)首先進(jìn)入了棧中,在棧中定義了一個(gè)?arr?的變量,但右邊不是一個(gè)具體值,是一個(gè)實(shí)體。
實(shí)體是被創(chuàng)建在堆內(nèi)存里面的,在堆里面首先通過(guò)?new?開(kāi)辟了空間。內(nèi)存在存儲(chǔ)數(shù)據(jù)的時(shí)候,都是通過(guò)地址值來(lái)體現(xiàn)的,地址值是一塊連續(xù)的二進(jìn)制,然后給這個(gè)實(shí)體分配了一個(gè)內(nèi)存地址。
數(shù)組都是有一個(gè)索引,數(shù)組這個(gè)實(shí)體在堆內(nèi)存中產(chǎn)生后每一個(gè)空間都會(huì)進(jìn)行默認(rèn)的初始化,不同的類型初始化的值不一樣。
所以在棧和堆當(dāng)中分別創(chuàng)建了變量和實(shí)體。
    棧內(nèi)存和堆內(nèi)存的圖例2

那么棧內(nèi)存和堆內(nèi)存要怎么聯(lián)系起來(lái)?

前文提到,每個(gè)實(shí)體進(jìn)入堆內(nèi)存后,都被分配一個(gè)內(nèi)存地址。把這個(gè)內(nèi)存地址賦給變量?arr?,?arr?就可以通過(guò)地址找到數(shù)組。所以?arr?想要操縱數(shù)組,就得通過(guò)地址,而不是直接把實(shí)體都賦給它。所以,這種我們不再稱呼為基本數(shù)據(jù)類型,而是引用數(shù)據(jù)類型,稱為?arr?引用了堆內(nèi)存當(dāng)中的實(shí)體。


如果當(dāng) ?int[] arr = null;?

?arr?不做任何指向,?null?的作用就是取消引用數(shù)據(jù)類型的指向。

當(dāng)一個(gè)實(shí)體沒(méi)有引用數(shù)據(jù)類型指向的時(shí)候,是不會(huì)被釋放掉,而是會(huì)被當(dāng)做垃圾。

Java有一個(gè)自動(dòng)回收機(jī)制,會(huì)自動(dòng)檢測(cè)堆里是否存有垃圾,如果有,那么就會(huì)回收垃圾,但是至于什么時(shí)候回收就不一定了。


堆內(nèi)存和棧內(nèi)存的區(qū)別

通過(guò)以上內(nèi)容,可以得出以下幾點(diǎn)不同:

  • 棧內(nèi)存存儲(chǔ)的是局部變量;堆內(nèi)存存儲(chǔ)的是實(shí)體。
  • 棧內(nèi)存的更新速度要快于堆內(nèi)存,是因?yàn)榫植孔兞康纳芷诙獭?/li>
  • 棧內(nèi)存存放的變量一旦結(jié)束就會(huì)釋放;堆內(nèi)存存放的實(shí)體會(huì)被垃圾回收機(jī)制不定時(shí)回收。

總結(jié)

以上就是關(guān)于Java底層JVM,以及JVM下的棧內(nèi)存和堆內(nèi)存簡(jiǎn)要知識(shí)點(diǎn)的全部?jī)?nèi)容。如果還想要了解更多關(guān)于Java底層知識(shí)的小伙伴,請(qǐng)多多關(guān)注并支持W3Cschool!


0 人點(diǎn)贊