程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> JVM內存構造---《深化了解Java虛擬機》學習總結

JVM內存構造---《深化了解Java虛擬機》學習總結

編輯:關於JAVA

JVM內存構造---《深化了解Java虛擬機》學習總結。本站提示廣大學習愛好者:(JVM內存構造---《深化了解Java虛擬機》學習總結)文章只能為提供參考,不一定能成為您想要的結果。以下是JVM內存構造---《深化了解Java虛擬機》學習總結正文


Java虛擬機在執行Java順序的進程中會把它所管理的內存劃分為若干個不同的數據區域。這些區域的用處各不相反,同時也根據著各自的執行規則,獨立的創立和銷毀數據。

虛擬機內存的劃分,如圖所示:

線程之間相互獨立的區域有:

虛擬機棧 、本中央法棧、順序計數器

線程可以共享數據的區域:

辦法區 、堆

每個區域的作用辨別如下:

順序計數器 Program Counter Register:

眾所周知,虛擬機處置多線程時,是經過輪番的切換線程,來獲取cpu的執行時機的。在虛擬機執行順序的進程中,當線程執行到某一地位時,虛擬機將cpu的執行時機出讓給了其他線程,此時原有線程的執行(防盜銜接:本文首發自http://www.cnblogs.com/jilodream/ )地位需求被記載上去,而新失掉執行時機的線程,又需求提供上次執行的地位,以此來保證順序中的多個線程可以繼續的並行的執行下去。

順序計數器的作用就是將各個線程下次所執行的(字節碼)行號(精確來說是指令的地址)記載上去,以保證其下次執行時可以正確的執行。

依據順序計數器的作用,我們可以知道:

1、每個線程都在這個區域中都應該擁有一個只為自己提供服務的順序計數器,它們之間是獨立存儲,互不影響的存在。

2、我們還可以知道,順序計數器只記載字節碼的行號,因而當線程執行本中央法(Native method)時,計數器的值是空。

3、順序計數器所消耗的內存空間十分小,因而這個區域是不會拋出OutOfMemoryError錯誤的。

虛擬機棧 VM Stack:

線程想要正常的運轉下去,單靠順序計數器來記載行號是遠遠不止的。線程還需求擁有自己的運轉空間,在這個空間中,虛擬機可以保管辦法的執行順序、辦法的外部部分變量,辦法在運算時,所需求的內存空間等。

在數據構造中,棧的特性最滿足辦法的進入前往的構造的。而這塊區域的主(防盜銜接:本文首發自http://www.cnblogs.com/jilodream/ )要作用就是線程在執行java辦法時所需求記載的數據。因而我們將這塊區域稱之為虛擬機棧。但是要記住這裡與我們在任務中通常指的棧並不同等,這個我會在後邊引見。

虛擬機棧的構造如下:

而關於每一個棧幀外部的劃分又是這樣的:

每一局部的作用如下:

(1)部分變量表:每一個辦法都可以定義一個只屬於自己的部分變量,當這個辦法運轉完畢後,這個部分變量的生命周期也就宣告完畢。所以每一個辦法都應該擁有一個塊屬於自己的內存區域用來保管辦法外部定義的部分變量。這塊區域就是部分變量表,我們往常任務中所指的棧,實踐上指的是虛擬機棧中的棧幀中的部分變量表。

(2)操作數棧:每個辦法的外部都可以計算數據,而計算數據勢必需求擁有一塊內存區域,為虛擬機用來停止數值計算。因而在棧幀中,就需求有一塊區域專門為以後辦法計算數據運用,它就是操作數棧。

在每停止一次完好的計算之後,棧中的數據都曾經出棧,所以操作數棧的空間在一個辦法外部是可以重復運用的。所以虛擬機在分配內存大小時,只分配以後辦法,單次完好計算所需求的最大內存空間給以後棧幀,以增加內存的耗費。

同時為了添加運轉效率,增加數據的不時復制,在大局部虛擬機的完成中,將以後辦法的部分變量表和下層辦法的操作數棧的內存構成局部堆疊,從而增加參數的不時復制而惹起的功能消費。(防盜銜接:本文首發自http://www.cnblogs.com/jilodream/ )

(3)靜態銜接:

虛擬機在執行辦法時有兩種方式被用來確定執行指令所對應的辦法,

第一種是類加載時,可以直接確定要執行的辦法,譬如靜態辦法,公有辦法,final辦法等。這種方式叫做靜態解析。

第二種是在真正運轉時,依據對象的真實援用來判別以後真正要執行的辦法。這種方式稱之為靜態銜接。

在字節碼文件中,都存在一個常量池,在這個常量池中保管有少量的符號援用,這個符號援用是每一個辦法的直接援用。在字節碼指令的中,運用的是這個符號援用。但是在運轉時階段,一定需求調用到要執行辦法在內存中真實的地址。這就需求將直接援用轉化成直接援用。而這裡的“靜態銜接”就是為了保證在運轉時階段,辦法可以正確的找到要調用的辦法,每個棧幀將自己在運轉時常量池中所對應的真實地址記載的地位。

這裡需求留意的是,在棧幀中的靜態銜接和查找符號援用為真實援用中的靜態銜接,是兩個概念。前者表示的是一個區域,後者表示的是一種查找方式。

(4)前往地址:

加入以後辦法的方式有兩種,第一種是遇到前往指令時,正常的加入以後辦法。另一種方式是遇到沒有捕捉而被拋出的異常。無論何種前往方式,在辦法加入後,棧幀的頂端都應是以後加入辦法的下層辦法。同時下層辦法的執行形態也需求依據以後的前往後果重新調整。所以每個棧幀可以應用“前往地址”這塊區域協助下層辦法恢復形態。

(5)附加信息:關於虛擬機標准中沒有聲明的,擁有指定寄存地位的信息可以由各個虛擬機自己決議,放置到這個區域中。

本中央法棧 Native Stack

在虛擬機中,不但運轉java辦法,還會運轉本中央法,也就是罕見的Native 關鍵字修飾的辦法。在虛擬機棧中,會為每個線程獨立的開拓一個專門運轉java言語(更精確的說應該是字節碼)的辦法(防盜銜接:本文首發自http://www.cnblogs.com/jilodream/ )棧,但是關於本中央法,則是運用另外的一塊內存區域來保管線程的調用形態,這塊區域就是本中央法棧。他的作用跟虛擬機棧根本類似,其區別就是一個為java辦法服務,一個為Native發光法服務。在虛擬機標准中,關於本中央法棧中的構造、辦法的言語、方式,都沒有強迫規則,各個虛擬機可以自在的完成它。

Java堆 Java Heap

我們往常所說的,在堆中創立一個實例,指的就是這個堆。這是虛擬機所管理的內存中最大的一塊。在虛擬機中,簡直一切的實例以及數組所分配的內存空間都會被放置在這個堆中。

由於java堆是對象實例的的次要寄存地位,因而虛擬機的渣滓回收機制的次要任務區域。

依據Java的內存回收機制,我們可以將堆的大小和內容劃分紅如下的方式:

依據java堆的特性,我們也可以知道,這塊區域是一塊線程共享的區域。同時我們也可以看出來,這塊區域,所可以運用在物理上非延續的內存,只需在邏輯上堅持延續即可。

辦法區 Method Area

辦法區的次要作用是保管類信息、常量、靜態變量以及即時編譯後的代碼等數據。這個區域中的數據依然會被GC的代回收所觸及到。我們往常所說的永世代,指的就是這個區域。

雖然這個區域也被稱之為永世代,但是當數據進入這個區域中,依然能夠會被回收。這個區域的回收目的次要是常量池的回收,以及類型的卸載。

運轉時常量池 Runtime Constant Pool

這塊區域屬於辦法區的中的一塊子區域。

在Class文件中,除了有類版本、字段、辦法、接口等,還有一個信息區(防盜銜接:本文首發自http://www.cnblogs.com/jilodream/ )域是常量池。常量池中的數據將會在類被加載後,存在到運轉時常量池中。

而類文件中的常量池次要包括各種字面量和符號援用。符號援用在解說棧幀時,有所觸及。

字面量可以了解為java言語中的常量,如字符串、final修飾的變量等。

符號援用則是指以下三種固定信息:

(1)類和接口的全限定稱號

(2)字段的稱號和描繪符

(3)辦法的稱號和描繪符

java言語在編譯成Class文件後,並沒有關於辦法和字段在內存中最終規劃的信息。所以當虛擬機運用這些變量或辦法時,需求先從常量池中,找到這些數據對應的符號援用,然後在辦法的棧幀中的靜態銜接區域中找到其對應的內存真實地位。

在日常任務中,我們常常會遇到兩種內存溢出的錯誤:

1、OutOfMemoryError

2、StackOverflowError

OutOfMemoryError指的是一個區域中,由於數據的不時添加,招致區域無法再從物理內存總請求到更大的空間,或許是區域所請求的空間曾經抵達虛擬機運轉參數所給該區域設定的最大值,那麼就會拋出這個錯誤。

StackOverflowError則指的是內存中的棧構造在不時的入棧,最終招致棧的深度超越了虛擬機所允許的棧深度時,所拋出的錯誤。

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved