excel求和與計算器求和相差0.01(excel求和0.00)
985
2022-05-29
對于Java程序員來說,內存是由JVM自動管理的,所以一旦出現內存泄漏或溢出的問題,不了解JVM的內存結構和各個內存區域的工作職責,將對解決問題帶來很大的麻煩,本文參照周志明的《深入理解Java虛擬機》,介紹JVM內存結構,比較枯燥,但對知其然,不知所以然的編碼人員來說還是有一定幫助的。
按照Java虛擬機規范的規定,JVM自動管理的內存將會包括以下幾個運行時數據區域。
程序計數器
程序計數器(Program Counter Register)是JVM中一塊較小的內存區域,保存著當前線程執行的虛擬機字節碼指令的內存地址。Java多線程的實現,其實是通過線程間的輪流切換并分配處理器執行時間的方式來實現的,在任何時刻,處理器都只會執行一個線程中的指令。在多線程場景下,為了保證線程切換回來后,還能恢復到原先狀態,找到原先執行的指令,所以每個線程都會設立一個程序計數器,并且各個線程之間不會互相影響,程序計數器為"線程私有"的內存區域。
如果當前線程正在執行Java方法,則程序計數器保存的是虛擬機字節碼的內存地址,如果正在執行的是Native方法(非Java方法,JVM底層有許多非Java編寫的函數實現),計數器則為空。程序計數器是唯一一個在Java規范中沒有規定任何OutOfMemory場景的區域。
虛擬機棧
虛擬機棧(Java Virtual Machine Stacks)和線程是緊密聯系的,每創建一個線程時就會對應創建一個Java棧,所以Java棧也是"線程私有"的內存區域,這個棧中又會對應包含多個棧幀,每調用一個方法時就會往棧中創建并壓入一個棧幀,棧幀是用來存儲方法數據和部分過程結果的數據結構,每一個方法從調用到最終返回結果的過程,就對應一個棧幀從入棧到出棧的過程。
虛擬機棧是一個后入先出的數據結構,線程運行過程中,只有一個棧幀是處于活躍狀態的,被稱為"當前活動幀棧",當前活動幀棧始終是虛擬機棧的棧頂元素。
本地方法棧
本地方法棧(Native Method Stack)和虛擬機棧的作用相似,不過虛擬機棧是為Java方法服務的,而本地方法棧是為Native方法服務的。
方法區
方法區(Method Area)是用于存儲類結構信息的地方,包括常量池、靜態變量、構造函數等類型信息,類型信息是由類加載器在類加載時從類文件中提取出來的。
方法區同樣存在垃圾收集,因為用戶通過自定義加載器加載的一些類同樣會成為垃圾,JVM會回收一個未被引用類所占的空間,以使方法區的空間達到最小。
方法區中還存在著常量池,常量池包含著一些常量和符號引用(加載類的連接階段中的解析過程會將符號引用轉換為直接引用)。
方法區是線程共享的。
堆
堆(heap)是存儲java實例或者對象的地方,是GC的主要區域,同樣是線程共享的內存區域。
案例分析一
案例分析二
上面main方法中運行的程序過程如下:
(1)用戶創建了一個Student對象,運行時JVM首先會去方法區尋找該對象的類型信息,沒有則使用類加載器classloader將Student.class字節碼文件加載至內存中的方法區,并將Student類的類型信息存放至方法區。
(2)接著JVM在堆中為新的Student實例分配內存空間,這個實例持有著指向方法區的Student類型信息的引用,引用指的是類型信息在方法區中的內存地址。
(3)在此運行的JVM進程中,會首先起一個線程跑該用戶程序,而創建線程的同時也創建了一個虛擬機棧,虛擬機棧用來跟蹤線程運行中的一系列方法調用的過程,每調用一個方法就會創建并往棧中壓入一個棧幀,棧幀用來存儲方法的參數,局部變量和運算過程的臨時數據。上面程序中的stu是對Student的引用,就存放于棧中,并持有指向堆中Student實例的內存地址。
(4)JVM根據stu引用持有的堆中對象的內存地址,定位到堆中的Student實例,由于堆中實例持有指向方法區的Student類型信息的引用,從而獲得add()方法的字節碼信息,接著執行add()方法包含的指令。
總結
1、所有線程共享的內存數據區:方法區,堆。而虛擬機棧,本地方法棧和程序計數器都是線程私有的。
2、存放于棧中的東西如下:
2.1每個線程包含一個棧區,棧中只保存基礎數據類型的對象和自定義對象的引用(不是對象)。對象都存放在堆區中。
2.2每個棧中的數據(基礎數據類型和對象引用)都是私有的,其他棧不能訪問。
2.3方法的形式參數,方法調用完后從棧空間回收
2.4引用對象的地址,引用完后,棧空間地址立即被回收,堆空間等待GC
3、存放于堆中的東西如下:
3.1存儲的全部是對象,每個對象包含一個與之對應的class信息
3.2?Jvm只有一個堆區(heap)被所有線程共享,堆區中不存放基本類型和對象引用,只存放對象本身
4、存放于方法區中的東西如下:
4.1存放線程所執行的字節碼指令
4.2跟堆一樣.被所有線程共享.方法區包含:所有的class和static變量
4.3常量池位于方法區中,見如下圖示說明
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。