java內(nèi)存區(qū)域與內(nèi)存溢出異常
運行時數(shù)據(jù)區(qū)域
java在運行時主要可以分為兩類,之類是線程獨享的,另外就是線程共享的。下面我分別介紹這里面的數(shù)據(jù)區(qū)域
程序計數(shù)器:
記錄jvm字節(jié)碼指令的地址,我自己的理解就是每個線程在執(zhí)行代碼的時候,一條命令在字節(jié)碼文件中對應(yīng)一條字節(jié)碼,然后你要執(zhí)行下一句指令,就需要知道前一條指令的地址,程序計數(shù)器就起到記錄這個指令地址的作用。需注意,程序計數(shù)器不會拋出OutOfMemoryError
虛擬機棧(本地方法棧):
這兩個區(qū)域大致是差不多的,虛擬機棧是執(zhí)行java方法,本地方法棧是執(zhí)行native方法(本地方法)。
然后他們是java(native)方法在運行時啟動的,運行時會創(chuàng)建一個棧幀,里面包含局部變量表、操作數(shù)棧、動態(tài)鏈接等信息,局部變量表中包含基本數(shù)據(jù)類型、對象引用類型,就是我們所說的棧。方法調(diào)用和結(jié)束其實是一個棧幀入棧出棧操作
上面三個是線程獨享的
java堆:
這是我們平常所說的堆,幾乎所有的對象實例都存放在這里,是GC時的重點區(qū)域(還有下面提到的方法區(qū))
方法區(qū):
里面存放的是虛擬機加載得到的類信息,靜態(tài)變量,常量和編譯器編譯后的代碼
常量池:方法區(qū)的一部分,在之后的class文件結(jié)構(gòu)著重講解
直接內(nèi)存:
又被稱作本地內(nèi)存,就是在我們的計算機里面,為java虛擬機分配好了一個運行內(nèi)存時,然而每個線程的數(shù)據(jù)是先存放在這個本地內(nèi)存上的,通過對運行內(nèi)存共享而達(dá)到線程間數(shù)據(jù)同步,對線程間可見的目的
內(nèi)存泄露、溢出
內(nèi)存泄露、溢出對于學(xué)習(xí)java虛擬機來講,真的很重要,只有懂了這些基礎(chǔ),你才能夠知道java虛擬機調(diào)優(yōu)時候為什么要那樣做。
內(nèi)存溢出:說簡單點就是虛擬機分配的內(nèi)存不夠用了。
內(nèi)存泄露:主要在堆區(qū)發(fā)生,表現(xiàn)為原先創(chuàng)建的應(yīng)該回收對象不夠被虛擬機回收,導(dǎo)致可用的內(nèi)存變得越來越少
接下來講講在配置虛擬機時為防止內(nèi)存溢出的幾個重要參數(shù)
1、-xmx表示分配的最大堆內(nèi)存 -xms表示最小堆內(nèi)存,如果相等表示不允許虛擬機動態(tài)擴展堆內(nèi)存
2、-xss表示每個線程分配的棧容量,需注意這里分配越大,越容易出現(xiàn)內(nèi)存溢出。原因是被堆內(nèi)存,方法區(qū)留下的內(nèi)存大致很固定了,每個線程分配的棧容量越大,在持續(xù)不斷的線程建立過程中,必定導(dǎo)致內(nèi)存不夠用可采用的處理方法:用減少內(nèi)存換取線程
3、-XX:PermSize -MaxPermSize用來設(shè)置最大方法區(qū)內(nèi)存