最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

終于有人把Java內(nèi)存區(qū)域說清楚了

2021-03-22 11:35 作者:安于長情Jessie  | 我要投稿

很多人會誤以為Java內(nèi)存區(qū)域和內(nèi)存模型是同一個東西,其實并不是。


Java內(nèi)存區(qū)域是指 JVM運行時將數(shù)據(jù)分區(qū)域存儲 ,簡單的說就是不同的數(shù)據(jù)放在不同的地方。通常又叫 運行時數(shù)據(jù)區(qū)域。


Java內(nèi)存模型(JMM)定義了程序中各個變量的訪問規(guī)則,即在虛擬機中將變量存儲到內(nèi)存和從內(nèi)存中取出變量這樣的底層細節(jié)。


?


1、Java內(nèi)存區(qū)域

1.8 之前:

?


JDK1.8(含)之后:


區(qū)別就是 1.8有一個元數(shù)據(jù)區(qū)替代方法區(qū)了。


?


JDK 1.7 其實是并沒完全移除方法區(qū),但是不會像1.6以前報 “java.lang.OutOfMemoryError: PermGen space”,而是報 java.lang.OutOfMemoryError: Java heap space


1.7部分內(nèi)容(比如 常量池、靜態(tài)變量有方法區(qū)轉(zhuǎn)移到了堆)

演變


那么,Java 8 中 PermGen 為什么被移出 HotSpot JVM 了?我總結了兩個主要原因(詳見:JEP 122: Remove the Permanent Generation):


由于 PermGen 內(nèi)存經(jīng)常會溢出,引發(fā)惱人的 java.lang.OutOfMemoryError: PermGen,因此 JVM 的開發(fā)者希望這一塊內(nèi)存可以更靈活地被管理,不要再經(jīng)常出現(xiàn)這樣的 OOM


移除 PermGen 可以促進 HotSpot JVM 與 JRockit VM 的融合,因為 JRockit 沒有永久代。


?


根據(jù)上面的各種原因,PermGen 最終被移除,方法區(qū)移至 Metaspace,字符串常量移至 Java Heap。


?


?


下面逐一介紹一下jvm管轄的這幾種內(nèi)存區(qū)域。


?


2、程序計數(shù)器

程序計數(shù)器(Program Counter Register)是一塊較小的內(nèi)存空間,由于JVM可以并發(fā)執(zhí)行線程,因此會存在線程之間的切換,而這個時候就程序計數(shù)器會記錄下當前程序執(zhí)行到的位置,以便在其他線程執(zhí)行完畢后,恢復現(xiàn)場繼續(xù)執(zhí)行。


JVM會為每個線程分配一個程序計數(shù)器,與線程的生命周期相同。


如果線程正在執(zhí)行的是應該Java方法,這個計數(shù)器記錄的是正在執(zhí)行虛擬機字節(jié)碼指令的地址。


如果正在執(zhí)行的是Native方法,計數(shù)器的值則為空(undefined)


程序計數(shù)器是唯一一個在 Java 虛擬機規(guī)范中沒有規(guī)定任何 OutOfMemoryError 情況的區(qū)域。


?


3、Java虛擬機棧

?


虛擬機棧 描述的是 Java 方法執(zhí)行的內(nèi)存模型:


每個方法在執(zhí)行的同時都會創(chuàng)建一個棧幀(Stack Frame,是方法運行時的基礎數(shù)據(jù)結構)用于存儲局部變量表、操作數(shù)棧、動態(tài)鏈接、方法出口等信息。每一個方法從調(diào)用直至執(zhí)行完成的過程,就對應著一個棧幀在虛擬機棧中入棧到出棧的過程。


虛擬機棧是每個線程獨有的,隨著線程的創(chuàng)建而存在,線程結束而死亡。


在虛擬機棧內(nèi)存不夠的時候會OutOfMemoryError,在線程運行中需要更大的虛擬機棧時會出現(xiàn)StackOverFlowError。


虛擬機棧包含很多棧幀,每個方法執(zhí)行的同時會創(chuàng)建一個棧幀,棧幀又存儲了方法的局部變量表、操作數(shù)棧、動態(tài)連接和方法返回地址等信息。


在活動線程中,只有位于棧頂?shù)臈攀怯行У?,稱為當前棧幀,與這個棧幀相關聯(lián)的方法稱為當前方法。


1)局部變量表

局部變量表是存放方法參數(shù)和局部變量的區(qū)域。


全局變量是放在堆的,有兩次賦值的階段,一次在類加載的準備階段,賦予系統(tǒng)初始值;另外一次在類加載的初始化階段,賦予代碼定義的初始值。


而局部變量沒有賦初始值是不能使用的。


2)操作數(shù)棧

一個先入后出的棧。


當一個方法剛剛開始執(zhí)行的時候,這個方法的操作數(shù)棧是空的,在方法的執(zhí)行過程中,會有各種字節(jié)碼指令往操作數(shù)棧中寫入和提取內(nèi)容,也就是出棧/入棧操作。


3) 動態(tài)連接

每個棧幀都包含一個指向運行時常量池中該棧幀所屬方法的引用。持有這個引用是為了支持方法調(diào)用過程中的動態(tài)連接(Dynamic Linking)。


常量池可以便于指令的識別




方法調(diào)用并不等同于方法執(zhí)行,方法調(diào)用階段唯一的任務就是確定被調(diào)用方法的版本(即調(diào)用哪一個方法),這也是Java強大的擴展能力,在運行期間才能確定目標方法的直接引用。


所有方法調(diào)用中的目標方法在Class文件里面都是一個常量池中的符號引用,在類加載的解析階段,會將其中的一部分符號引用轉(zhuǎn)化為直接引用。




4)方法返回地址(方法出口)

返回分為 正常返回 和 異常退出。


無論何種退出情況,都將返回至方法當前被調(diào)用的位置,這也程序才能繼續(xù)執(zhí)行。


一般來說,方法正常退出時,調(diào)用者的PC計數(shù)器的值可以作為返回地址,棧幀中會保存這個計數(shù)器值。


方法退出的過程相當于彈出當前棧幀。


?


4、本地方法棧

Java虛擬機棧是調(diào)用Java方法;本地方法棧是調(diào)用本地native方法,可以認為是通過 JNI (Java Native Interface) 直接調(diào)用本地 C/C++ 庫,不受JVM控制。


?

Native方法

Java虛擬機棧與本地方法棧的調(diào)用過程

本地方法棧也會拋出 StackOverflowError 和 OutOfMemoryError 異常


?


5、Java堆

Java 堆是被所有線程共享的一塊內(nèi)存區(qū)域,在虛擬機啟動時創(chuàng)建。此內(nèi)存區(qū)域的唯一目的就是存放對象實例,幾乎所有的對象實例都在這里分配內(nèi)存。


堆是垃圾收集器管理的主要區(qū)域,又稱為“GC堆”,可以說是Java虛擬機管理的內(nèi)存中最大的一塊。


現(xiàn)在的虛擬機(包括HotSpot VM)都是采用分代回收算法。在分代回收的思想中, 把堆分為:新生代+老年代+永久代(1.8沒有了); 新生代 又分為 Eden + From Survivor + To Survivor區(qū)。

6、方法區(qū)

方法區(qū)(Method Area)與 Java 堆一樣,是所有線程共享的內(nèi)存區(qū)域。


方法區(qū)用于存儲已經(jīng)被虛擬機加載的類信息(即加載類時需要加載的信息,包括版本、field、方法、接口等信息)、final常量、靜態(tài)變量、編譯器即時編譯的代碼等。


方法區(qū)邏輯上屬于堆的一部分,但是為了與堆進行區(qū)分,通常又叫“非堆”。


方法區(qū)比較重要的一部分是運行時常量池(Runtime Constant Pool),為什么叫運行時常量池呢?是因為運行期間可能會把新的常量放入池中,比如說常見的String的intern()方法。




在編譯階段就把所有的字符串文字放到一個常量池中,復用同一個(比如說上述的“I am HaC”),節(jié)省空間。


關于方法區(qū)和元空間的關系:


方法區(qū)是JVM規(guī)范概念,而永久代則是Hotspot虛擬機特有的概念,簡單點理解:方法區(qū)和堆內(nèi)存的永久代其實一個東西,但是方法區(qū)是包含了永久代。


只有 HotSpot 才有 “PermGen space”,而對于其他類型的虛擬機,如 JRockit(Oracle)、J9(IBM) 并沒有“PermGen space”


?

7、元空間

1.8就把方法區(qū)改用元空間了。類的元信息被存儲在元空間中。元空間沒有使用堆內(nèi)存,而是與堆不相連的本地內(nèi)存區(qū)域。所以,理論上系統(tǒng)可以使用的內(nèi)存有多大,元空間就有多大,所以不會出現(xiàn)永久代存在時的內(nèi)存溢出問題。


可以通過 -XX:MetaspaceSize 和 -XX:MaxMetaspaceSize 來指定元空間的大小。


?

8、總結:

?

Java內(nèi)存區(qū)域

?

如果你也正在學習Java或者想要了解Java,渴望成為一名合格的Java開發(fā)工程師,你可以評論區(qū)留言!

我是一個從事Java開發(fā)的程序員,給正在學習Java的小伙伴整理了干貨哦


?

作者:Java講解

原鏈接:https://www.bilibili.com/read/cv8675068

出處: bilibili



終于有人把Java內(nèi)存區(qū)域說清楚了的評論 (共 條)

分享到微博請遵守國家法律
石楼县| 新兴县| 科技| 凭祥市| 怀宁县| 灌云县| 西和县| 当雄县| 合肥市| 九台市| 合水县| 望城县| 怀安县| 江津市| 虹口区| 白水县| 金溪县| 游戏| 安西县| 湖北省| 黎城县| 南部县| 徐汇区| 临沧市| 原平市| 湟中县| 全椒县| 垫江县| 武清区| 光山县| 玉溪市| 沛县| 吴堡县| 张北县| 平果县| 台北市| 沈阳市| 肥东县| 酒泉市| 朝阳市| 临泉县|