一 、JVM(數據類型、堆、棧)

目錄

 

數據類型

基本類型

引用數據類型

Java中的參數傳遞時傳值呢?還是傳引用?

但是傳引用的錯覺是如何造成的呢?

操作系統的堆和棧

爲什麼jvm的內存是分佈在操作系統的堆中呢?

java虛擬機的生命週期

java虛擬機與main方法的關係

GC

 jvm

 jvm內存結構與操作系統內存佈局進行類比說明

運行時數據區圖


數據類型

基本類型

基本類型的變量保存原始值,即:他代表的值就是數值本身

包括:

byte:8位,最大存儲數據量是255,存放的數據範圍是-128~127之間。

short:16位,最大數據存儲量是65536,數據範圍是-32768~32767之間。

int:32位,最大數據存儲容量是2的32次方減1,數據範圍是負的2的31次方到正的2的31次方減1。

long:64位,最大數據存儲容量是2的64次方減1,數據範圍爲負的2的63次方到正的2的63次方減1。

float:32位,數據範圍在3.4e-45~1.4e38,直接賦值時必須在數字後加上f或F。

double:64位,數據範圍在4.9e-324~1.8e308,賦值時可以加d或D也可以不加。

boolean:只有true和false兩個取值。

char:16位,存儲Unicode碼,用單引號賦值。

returnAddress 數據只存在於字節碼層面,與編程語言無關,也就是說,我們在 Java 語言中是不會直接與 returnAddress 類型的數據打交道的。

引用數據類型

引用類型的變量保存引用值。

“引用值”代表了某個對象的引用,而不是對象本身,對象本身存放在這個引用值所表示的地址的位置

包括:

類類型,接口類型和數組。

Java中的參數傳遞時傳值呢?還是傳引用

      Java中沒有指針的概念, 程序運行永遠都是在棧中進行的,因而參數傳遞時,只存在傳遞基本類型和對象引用的問題。不會直接傳對象本身。Java在方法調用傳遞參數時,因爲沒有指針,所以它都是進行傳值調用

但是傳引用的錯覺是如何造成的呢?

      在運行棧中,基本類型和引用的處理是一樣的,都是傳值。所以,如果是傳引用的方法調用,也同時可以理解爲“傳引用值”的傳值調用,即引用的處理跟基本類型是完全一樣的。但是當進入被調用方法時,被傳遞的這個引用的值,被程序解釋(或查找)到堆中的對象,這個時候纔對應到真正的對象。如果此時進行修改,修改的是引用對應的對象,而不是引用本身,即:修改的是堆中的數據。所有這個修改是可以保持的。

      對象,從某種意義上說,是由基本類型組成的。可以把一個對象看作爲一棵樹,對象的屬性如果也是對象,則也是一顆樹(即非葉子節點),基本類型則作爲樹的葉子節點。程序參數傳遞時,被傳遞的值本身都是不能進行修改的,但是,如果這個值是一個非葉子節點(即一個對象引用),則可以修改這個節點下面的所有內容。

堆和棧中,棧是程序運行最根本的東西。程序運行可以沒有堆,但是不能沒有棧。而堆是爲棧進行數據存儲服務,說白了堆就是一塊共享的內存。不過,正是因爲堆和棧的分離的思想,才使得Java的垃圾回收成爲可能。

     Java中,棧的大小通過-Xss來設置,當棧中存儲數據比較多時,需要適當調大這個值,否則會出現java.lang.StackOverflowError異常。常見的出現這個異常的是無法返回的遞歸,因爲此時棧中保存的信息都是方法返回的記錄點。

操作系統的堆和棧

一般由程序員分配釋放,若程序員不釋放,程序結束時可能由OS回收,分配方式類似於鏈表。

由操作系統自動分配釋放,存放函數的參數值,局部變量值等。操作方式與數據結構中的棧相類似。

爲什麼jvm的內存是分佈在操作系統的堆中呢?

因爲操作系統的棧是操作系統管理的,它隨時會被回收,所以如果jvm放在棧中,那java的一個null對象就很難確定會被誰回收了,那gc的存在就一點意義都莫有了,而要對棧做到自動釋放也是jvm需要考慮的,所以放在堆中就最合適不過了。

java虛擬機的生命週期

聲明週期起點是當一個java應用main函數啓動時虛擬機也同時被啓動,而只有當在虛擬機實例中的所有非守護進程都結束時,java虛擬機實例才結束生命。

java虛擬機與main方法的關係

main函數就是一個java應用的入口,main函數被執行時,java虛擬機就啓動了。啓動了幾個main函數就啓動了幾個java應用,同時也啓動了幾個java的虛擬機。

GC

虛擬機的gc(垃圾回收機制)就是一個典型的守護線程。

GC垃圾回收機制不是創建的變量爲空是就被立刻回收,而是超出變量的作用域後就被自動回收。

 jvm

 jvm內存結構與操作系統內存佈局進行類比說明

上圖表明:

  • jvm內存是存在於計算機內存中,並根據自身需求將內存劃分爲:pc寄存器、虛擬機棧、本地方法棧、jvm堆以及方法區,這些區域共同組成了運行時數據區,其中gc主要發生在堆區,棧由jvm自行管理
  • pc寄存器:其主要職責是指示線程要執行的下一條指令的地址,具體執行過程參考下文:Class文件的執行過程
  • 棧:主要是有棧幀組成,每個棧幀代表一個方法,且位於棧頂的棧幀是當前正在執行的方法。
  • 堆:java中一切皆對象,所有對象都是在堆中生成,有gc垃圾回收器進行回收
  • 方法區:類似計算機的硬盤,主要存放class文件,其中class文件基本組織結構可以參考Class文件的內存信息
     

運行時數據區圖

 

上圖表明:

方法區和堆是線程共享的,虛擬機棧、本地方法棧和程序計數器都是線程私有的,這裏的程序計數器是線程私有的是因爲線程可以被切換暫停的,當恢復運行時由程序計數器執行接着執行的指令地址。

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章