JAVA內(nèi)存區(qū)域
JVM在執(zhí)行Java程序的過程中會把它管理的內(nèi)存劃分為若干個不同的數(shù)據(jù)區(qū)域,包括程序計數(shù)器蜻底、Java虛擬機(jī)棧卖词、本地方法棧、Java堆悟狱、方法區(qū)等。前三者為線程私有的堰氓,后兩者為線程共享區(qū)域挤渐。
1. 程序計數(shù)器(Program Counter Register)
程序計數(shù)器是一塊較小的內(nèi)存空間,可以看作是當(dāng)前線程所執(zhí)行的字節(jié)碼行號指示器双絮。
因為JVM的多線程是通過線程輪換并分配處理器執(zhí)行時間來實現(xiàn)的浴麻,所以在任意時刻,一個處理器都只會執(zhí)行一條線程中的指令囤攀。所以為了切換后能夠恢復(fù)到正確的執(zhí)行位置软免,每條線程都需要一個獨立的計數(shù)器,它們互不影響焚挠。因此膏萧,程序計數(shù)器是線程私有的。
如果線程執(zhí)行的是一個Java方法蝌衔,計數(shù)器記錄正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址榛泛。如果是Native方法,能為空噩斟。
2. Java虛擬機(jī)棧(Java Virtual Machine Stacks)
Java虛擬機(jī)棧描述的是Java方法執(zhí)行的內(nèi)存模型: 每個方法執(zhí)行的時候會創(chuàng)建一個棧幀(Stack Frame)用于存儲局部變量表曹锨、操作數(shù)棧、動態(tài)鏈接亩冬、方法出口等信息艘希。一個方法從執(zhí)行到返回,就對應(yīng)一個棧幀在虛擬機(jī)棧中入棧和出棧的過程硅急。
局部變量表
局部變量表存放的是編譯期可知的各種基本數(shù)據(jù)類型覆享、對象引用(reference類型)、returnAddress類型营袜。其中64位長度的long和double類型數(shù)據(jù)會占用2個局部變量空間(Slot)撒顿,其余只占用1個。局部變量表所需空間在變異期間完成分配荚板,所以當(dāng)進(jìn)入一個方法時凤壁,這個方法需要在幀中分配多大的局部變量空間完全確定吩屹,運行期間不會改變。
3. 本地方法棧(Native Method Stack)
本地方法棧和虛擬機(jī)棧的作用非常相似拧抖、區(qū)別在于一個執(zhí)行的是Java方法煤搜,一個執(zhí)行的是Native方法。
使用native關(guān)鍵字表示的方法是原生函數(shù)唧席,也就是這個方法是用C/C++語言實現(xiàn)的擦盾,并且被編譯成了DLL,由Java去調(diào)用淌哟。
4. Java堆(Java Heap)
Java堆是被所有線程共享的一塊內(nèi)存區(qū)域迹卢,在虛擬機(jī)啟動時創(chuàng)建。這個內(nèi)存區(qū)域的唯一目的就是存放對象實例以及數(shù)組徒仓。Java堆是垃圾收集器的主要區(qū)域腐碱。從內(nèi)存回收的角度來看,現(xiàn)代收集器都是使用分代收集算法掉弛,所以可以細(xì)分為:新生代和老年代症见,新生代還可以分為Eden空間、From Survivor空間殃饿、To Survivor空間等筒饰。
Java堆的JVM參數(shù)主要是 -Xms和-Xmn。
5. 方法區(qū)(Method Area)
方法區(qū)和Java堆一樣壁晒,是各個線程共享的內(nèi)存區(qū)域,它被用于存儲已被虛擬機(jī)加載的類信息业栅、常量秒咐、靜態(tài)變量、即時編譯期編譯后的代碼等數(shù)據(jù)碘裕。
運行時常量池(Runtime Constant Pool)
運行時常量池是方法區(qū)的一部分携取。 Class文件中除了類的版本、字段帮孔、方法雷滋、接口等描述信息,還有常量池(Constant Pool Table)文兢,主要包括編譯期生成的各種字面量(Literal)和符號引用量(Symbolic References)晤斩。字面量相當(dāng)于Java語言層面常量的概念,如文本字符串姆坚,聲明為final的常量值等澳泵,符號引用則屬于編譯原理方面的概念,符號引用以一組符號來描述所引用的目標(biāo)兼呵,符號可以是任何形式的字面量兔辅,只要使用時能夠無歧義的定位到目標(biāo)即可腊敲。包括了如下三種類型的常量:
- 類和接口的全限定名
- 字段名稱和描述符
- 方法名稱和描述符
這部分內(nèi)容在類加載后進(jìn)入方法區(qū)的運行時常量池存放。
運行時常量池相對于CLass文件常量池的另外一個重要特征是具備動態(tài)性维苔,Java語言并不要求常量一定只有編譯期才能產(chǎn)生碰辅,也就是并非預(yù)置入CLass文件中常量池的內(nèi)容才能進(jìn)入方法區(qū)運行時常量池,運行期間也可能將新的常量放入池中介时,這種特性被開發(fā)人員利用比較多的就是String類的intern()方法没宾。
常量池的好處
常量池是為了避免頻繁的創(chuàng)建和銷毀對象而影響系統(tǒng)性能,其實現(xiàn)了對象的共享潮尝。
例如字符串常量池榕吼,在編譯階段就把所有的字符串文字放到一個常量池中。 - 節(jié)省內(nèi)存空間:常量池中所有相同的字符串常量被合并勉失,只占用一個空間羹蚣。
- 節(jié)省運行時間:比較字符串時,==比equals()快乱凿。對于兩個引用變量顽素,只用==判斷引用是否相等,也就可以判斷實際值是否相等徒蟆。
雙等號==的含義 - 基本數(shù)據(jù)類型之間應(yīng)用雙等號胁出,比較的是他們的數(shù)值。
- 復(fù)合數(shù)據(jù)類型(類)之間應(yīng)用雙等號段审,比較的是他們在內(nèi)存中的存放地址全蝶。