深刻理解JVM內存分配和常量池

一.虛擬機的構成

虛擬結主要由運行時數據區、執行引擎、類加載器三者構成:java

而咱們所說的JVM內存模型指的就是運行時數據區,下面具體分析一下運行時數據區:緩存

二.運行時數據區組成和各個區域的做用

咱們看到運行時數據區能夠分爲線程共享和線程不共享兩部分,其中堆內存和方法區線程共享,本地方法棧、虛擬機棧、程序計數器線程不共享。性能

接下來咱們介紹每個區域的做用:spa

2.1.程序計數器

程序計數器(Program Counter Register),也有稱做爲PC寄存器。想必學過彙編語言的朋友對程序計數器這個概念並不陌生,在彙編語言中,程序計數器是指CPU中的寄存器,它保存的是程序當前執行的指令的地址(也能夠說保存下一條指令的所在存儲單元的地址),當CPU須要執行指令時,須要從程序計數器中獲得當前須要執行的指令所在存儲單元的地址,而後根據獲得的地址獲取到指令,在獲得指令以後,程序計數器便自動加1或者根據轉移指針獲得下一條指令的地址,如此循環,直至執行完全部的指令。線程

2.2虛擬機棧

虛擬機棧也叫java棧,棧中存儲的是幀棧,每個方法對應一個幀棧,方法執行完畢後進行彈棧,讓出棧內存,幀棧中存儲着方法中定義的變量,若是是基本數據類型,就在棧中進行值的存儲,若是是引用數據類型,存儲的是引用指向對象的地址。翻譯

虛擬機棧也叫棧內存,是在線程建立時建立,它的生命期是跟隨線程的生命,線程結束棧內存也就釋放,對於棧來講不存在垃圾回收問題,只要線程一結束,該棧就 Over,因此不存在垃圾回收。也有一些資料翻譯成JAVA方法棧,大概是由於它所描述的是java方法執行的內存模型,每一個方法執行的同時建立幀棧(Strack Frame)用於存儲局部變量表(包含了對應的方法參數和局部變量),操做棧(Operand Stack,記錄出棧、入棧的操做),動態連接、方法出口等信息,每一個方法被調用直到執行完畢的過程,對應這幀棧在虛擬機棧的入棧和出棧的過程。3d

局部變量表存放了編譯期可知的各類基本數據類型(boolean、byte、char、short、int、float、long、double)、對象的引用(reference類型,不等同於對象自己,根據不一樣的虛擬機實現,多是一個指向對象起始地址的引用指針,也多是一個表明對象的句柄或者其餘與對象相關的位置)和 returnAdress類型(指向下一條字節碼指令的地址)。局部變量表所需的內存空間在編譯期間完成分配,在方法在運行以前,該局部變量表所須要的內存空間是固定的,運行期間也不會改變。指針

2.3本地方法棧

和虛擬機棧功能類似,不過本地方法棧存儲針對本地方法。code

2.4堆內存

堆內存主要用來存儲被建立的對象,一個類new出一個對象,會在堆中開闢內存空間,並在棧中存儲一個引用,存儲着對象在堆中的地址。堆內存中的對象存儲着本身的成員變量,並不保存對象的方法,方法被保存在幀棧中,堆內存也稱爲gc堆,是主要用來進行垃圾回收的內存。對象

2.5方法區

方法區是一個很是重要的區域,也是被線程共享的區域,方法區存儲了每一個類的信息(類的名稱、方法信息、字段信息),靜態變量、常量以及編譯後的代碼等。

方法區還包括一個常量池,用來存儲編譯期間生成的字面量和符號引用。這部份內容在類被加載後,都會存儲到方法區中的RCP。值得注意的是,運行時產生的新常量也能夠被放入常量池中,好比 String 類中的 intern() 方法產生的常量。

常量池就是這個類型用到的常量的一個有序集合。包括直接常量(基本類型,String)對其餘類型、方法、字段的符號引用.

三.常量池的使用

3.1什麼是常量?

常量是指被final修飾的變量,值一旦肯定就沒法改變。

final能夠修飾靜態變量、實例變量和局部變量。

3.2Clss文件中的常量池

咱們知道方法區中存放着class文件的信息,還包括用來存儲class常量的常量池,方法區中還存在運行時常量池二者什麼關係?

常量池主要用來存放兩大類常量:字面量和符號引用量,字面量至關於Java語言的常量,如文本字符串,聲明爲final的常量等,符號引用包括如下三種

類和接口的全限定名

字段名稱和描述符

方法名稱和描述符

3.3方法區中的運行常量池

class文件中的常量池中的內容會在類加載後進入方法區的運行時常量池。相對於常量池,運行時常量池的重要特徵是具備動態性,java並不要求常量只有在編譯器纔會產生,運行期間也能夠將新的常量存放入池中,這種特性用的最多的String類中的intern()方法。

3.4常量池的做用和==號的意義

常量池是爲了不頻繁的建立和銷燬對象形成系統性能的浪費,實現了對象的共享。

==號比較基本數據類型,就是比值,比較引用數據類型比較的是內存中存放的地址。

3.2常量池的應用

對於byte、short、long、char、boolean對應的包裝器類都有對應的常量池,這五種包裝器類默認建立在-128到127的對象會存放在在緩存中。

對於兩種浮點數沒有實現常量池技術。

3.4String類和常量池

String str1="abc";
String str2=new String("abc");
System.out.println(str1==str2);

結果爲false;

相關文章
相關標籤/搜索