學習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)存的劃分主要是下列五個:
- 寄存器
- 本地方法去
- 方法區(qū)
- 棧內(nèi)存
- 堆內(nèi)存
棧內(nèi)存
棧內(nèi)存里面存儲的都是局部變量。
什么是局部變量?凡是定義在方法中的都是局部變量,for循環(huán)內(nèi)定義的也是局部變量。
先加載函數(shù)才能進行局部變量的定義,所以在方法進棧后,然后再定義變量,變量是有自己的作用域,一旦離開這個作用域,變量就會馬上被釋放。也因此,棧內(nèi)存的更新速度非常快,這也是因為局部變量的生命周期都很短。
堆內(nèi)存
new
?建立的都是在堆中,堆中存放的都是實體(也就是對象)。int[] arr = new int[3];
?在內(nèi)存中是怎樣被定義的?arr
?的變量,但右邊不是一個具體值,是一個實體。new
?開辟了空間。內(nèi)存在存儲數(shù)據(jù)的時候,都是通過地址值來體現(xiàn)的,地址值是一塊連續(xù)的二進制,然后給這個實體分配了一個內(nèi)存地址。那么棧內(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)存存放的實體會被垃圾回收機制不定時回收。