JVM內(nèi)存分配
先了解下JVM中的內(nèi)存分配,此處以hotspot vm為例(官方j(luò)dk采用的vm)
程序計數(shù)器
棧
1. 虛擬機(jī)棧
2. 本地方法棧
Java堆
堆內(nèi)存是各個線程共享的區(qū)域
方法區(qū)
它用于存儲已經(jīng)被虛擬機(jī)加載的類信息、常量、靜態(tài)變量、即編譯器編譯后的代碼等數(shù)據(jù)。靜態(tài)變量、常量在方法區(qū),所有方法,包括靜態(tài)和非靜態(tài)的,也在方法區(qū)
這里解釋一下方法區(qū):
首先方法區(qū)不是在堆中,在java8之前是用永久代實(shí)現(xiàn)的,永久代是 Hotspot 虛擬機(jī)特有的概念,雖然 Java 虛擬機(jī)規(guī)范把方法區(qū)描述為堆的一個邏輯部分,但是它卻有一個別名叫做 Non-Heap(非堆),目的應(yīng)該是與 Java 堆區(qū)分開來
java8之后是用元空間實(shí)現(xiàn)的,元空間并不在虛擬機(jī)中,而是使用本地內(nèi)存。
只是 JVM 規(guī)范中定義的一個概念,用于存儲被 JVM 加載的類信息、常量、靜態(tài)變量、即時編譯器編譯后的代碼等數(shù)據(jù)
?文章來源地址http://www.zghlxwxcb.cn/news/detail-413135.html
常量池
常量池分為靜態(tài)常量池和運(yùn)行時常量池
1. 靜態(tài)常量池
也叫 class文件常量池,主要存放編譯期生成的各種字面量(Literal)和符號引用(Symbolic References)。
final類型的常量在編譯期間就會進(jìn)行分配。
靜態(tài)常量池指的是在編譯期確定,保存在class文件中的一些數(shù)據(jù)。
靜態(tài)常量池是在編譯期間生成的,存儲在.class文件中。
?
字面量(Literal)和符號引用量,字面量相當(dāng)于Java語言層面常量的概念,如文本字符串、聲明為final的常量值等,符號引用則屬于編譯原理方面的概念,包括了如下三種類型的常量:
-
-
2、字段的名稱和描述符;
-
3、方法的名稱和描述符。
2. 運(yùn)行時常量池
當(dāng)類加載到內(nèi)存中后,JVM就會將class常量池中的內(nèi)容存放到運(yùn)行時常量池中;運(yùn)行時常量池里面存儲的主要是編譯期間生成的字面量、符號引用等等。
類加載在鏈接環(huán)節(jié)的解析過程,會符號引用轉(zhuǎn)換成直接引用(靜態(tài)鏈接)。此處得到的直接引用也是放到運(yùn)行時常量池中的。
運(yùn)行期間可以動態(tài)放入新的常量
運(yùn)行時常量池內(nèi)存位置:java8之前都在方法區(qū)中,java8之后在元空間
2.1 字符串常量池
字符串常量池,也可以理解成運(yùn)行時常量池分出來的一部分。類加載到內(nèi)存的時候,字符串會存到字符串常量池里面。利用池的概念,避免大量頻繁創(chuàng)建字符串
-
JDK6時字符串常量池位于運(yùn)行時常量池,JDK7挪到堆中。
Hotspot8之前,使用持久代實(shí)現(xiàn)方法區(qū),由于持久代內(nèi)存不好估算,很容易到值OOM:Perm Gen異常。而元空間是本地內(nèi)存,取決于操作系統(tǒng)分配內(nèi)存。
字符串常量池位置變遷
Jdk1.6及之前: 有永久代, 運(yùn)行時常量池在永久代,運(yùn)行時常量池包含字符串常量池
Jdk1.7:有永久代,但已經(jīng)逐步“去永久代”,字符串常量池從永久代里的運(yùn)行時常量池分離到堆里
Jdk1.8及之后: 無永久代,運(yùn)行時常量池在元空間,字符串常量池里依然在堆里
?
?
參考文章
文章來源:http://www.zghlxwxcb.cn/news/detail-413135.html
?
到了這里,關(guān)于JVM的內(nèi)存分配及各種常量池的區(qū)別(靜態(tài)常量池、運(yùn)行時常量池、字符串常量池)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!