App下載

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

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

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

JVM

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

Java程序在運行的時候都要開辟一個空間,也就是說任何軟件在運行的時候都需要開辟空間,同樣JVM也不例外,也需要開辟空間。JVM運行時在內(nèi)存中開辟的內(nèi)存區(qū)域,啟動時在這片區(qū)域內(nèi)自己還會進行更細致的劃分,因為虛擬機中每片內(nèi)存處理的方式都不一樣,所以要分別單獨進行管理。

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

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

棧內(nèi)存

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

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

先加載函數(shù)才能進行局部變量的定義,所以在方法進棧后,然后再定義變量,變量是有自己的作用域,一旦離開這個作用域,變量就會馬上被釋放。也因此,棧內(nèi)存的更新速度非常快,這也是因為局部變量的生命周期都很短。


堆內(nèi)存

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

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

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

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


如果當 ?int[] arr = null;?

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

當一個實體沒有引用數(shù)據(jù)類型指向的時候,是不會被釋放掉,而是會被當做垃圾。

Java有一個自動回收機制,會自動檢測堆里是否存有垃圾,如果有,那么就會回收垃圾,但是至于什么時候回收就不一定了。


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

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

  • 棧內(nèi)存存儲的是局部變量;堆內(nèi)存存儲的是實體。
  • 棧內(nèi)存的更新速度要快于堆內(nèi)存,是因為局部變量的生命周期短。
  • 棧內(nèi)存存放的變量一旦結束就會釋放;堆內(nèi)存存放的實體會被垃圾回收機制不定時回收。

總結

以上就是關于Java底層JVM,以及JVM下的棧內(nèi)存和堆內(nèi)存簡要知識點的全部內(nèi)容。如果還想要了解更多關于Java底層知識的小伙伴,請多多關注并支持W3Cschool!


0 人點贊