程序計(jì)數(shù)器是一塊較小的內(nèi)存空間,主要功能是作為當(dāng)前線(xiàn)程所執(zhí)行字節(jié)碼當(dāng)前行號(hào)指示器。當(dāng)其運(yùn)行java方法時(shí),指向的是虛擬機(jī)字節(jié)碼指令的地址,當(dāng)其運(yùn)行native方法時(shí),則為空。程序計(jì)數(shù)器是java虛擬機(jī)規(guī)范中唯一沒(méi)有OutOfMemoryError情況的區(qū)域.
虛擬機(jī)棧描述的主要是java方法執(zhí)行的內(nèi)存模型,用于存儲(chǔ)方法調(diào)用時(shí)的創(chuàng)建的棧幀,棧幀存儲(chǔ)了局部變量表,操作數(shù)棧,動(dòng)態(tài)連接,方法出口等信息。線(xiàn)程請(qǐng)求的棧深度大于虛擬機(jī)所允許的深度時(shí),拋出stackoverflowError異常,如果虛擬機(jī)可以動(dòng)態(tài)擴(kuò)展,但擴(kuò)展時(shí)無(wú)法申請(qǐng)足夠的內(nèi)存,則會(huì)拋出OutOfMemoryError異常。
本地方法棧實(shí)現(xiàn)的功能和虛擬機(jī)棧類(lèi)似,不過(guò)它處理的是native方法。
堆的主要功能是存放對(duì)象實(shí)例,幾乎所有的數(shù)組和對(duì)象實(shí)例都是在堆中分配.并且它也是垃圾回收的主要區(qū)域.如果堆中沒(méi)有內(nèi)存來(lái)分配實(shí)例,并且不能擴(kuò)展,則會(huì)拋出outOfMemoryError
方法區(qū)用于存放已被虛擬機(jī)加載的類(lèi)信息,常量,靜態(tài)變量,即時(shí)編譯編譯后的代碼(動(dòng)態(tài)代理等)等數(shù)據(jù)。當(dāng)方法區(qū)無(wú)法滿(mǎn)足分配需求時(shí),將拋出OutOfMemoyError異常
jdk1.4中新加入了NIO類(lèi),引入了一種基于通道與緩沖區(qū)的I/O方式,它可以使用Native函數(shù)直接分配堆外內(nèi)存,然后通過(guò)一個(gè)存儲(chǔ)在java堆中的DirectByteBuffer對(duì)象作為這塊內(nèi)存的引用進(jìn)行操作。這樣避免了java堆和native堆之間來(lái)回復(fù)制數(shù)據(jù),提高了性能。
虛擬機(jī)遇到一條new指令時(shí),首先將先檢查這個(gè)指令的參數(shù)是否能在常量池中定位到一個(gè)類(lèi)的符號(hào)引用,并且檢查這個(gè)符號(hào)是否被加載,解析,初始化過(guò)。如果沒(méi)有,則執(zhí)行類(lèi)加載過(guò)程。在類(lèi)加載后,就是對(duì)對(duì)象分配內(nèi)存,對(duì)于java內(nèi)存規(guī)整的情況,使用的是"指針碰撞",而不規(guī)整的則采用"空閑列表"的分配方式。經(jīng)過(guò)上面的操作后,執(zhí)行<init>將對(duì)象按照程序員的意愿進(jìn)行初始化。
在hotspot虛擬機(jī)中,對(duì)象的內(nèi)存中的存儲(chǔ)的布局可以分為三個(gè)部分對(duì)象頭 ,實(shí)例數(shù)據(jù) ,對(duì)齊填充。對(duì)象頭主要有兩部分信息,第一部分為用于存儲(chǔ)對(duì)象自身的運(yùn)行時(shí)數(shù)據(jù),如哈希碼,GC分代年齡,鎖狀態(tài)標(biāo)志,線(xiàn)程持有的鎖,偏向線(xiàn)程ID,偏向時(shí)間戳等。另一部分為類(lèi)型指針,指向類(lèi)的元數(shù)據(jù)信息。對(duì)于數(shù)組還有一部分為數(shù)組長(zhǎng)度信息。實(shí)例數(shù)據(jù)存儲(chǔ)的即為各種類(lèi)型的字段內(nèi)容。
主要是使用句柄和直接指針兩種方式。句柄是java堆中會(huì)分出一塊內(nèi)存來(lái)作為句柄池,reference存儲(chǔ)的是對(duì)象的句柄地址,而句柄中存儲(chǔ)的是對(duì)象數(shù)據(jù)和類(lèi)數(shù)據(jù)地址。直接地址方式是reference直接指向的就對(duì)象地址句柄的優(yōu)勢(shì)是對(duì)象移動(dòng)不用修改reference指針,只需要修改句柄指針,而直接指針的優(yōu)勢(shì)是訪(fǎng)問(wèn)速度更快.
import java.util.ArrayList;import java.util.List;/** * -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError * -Xms設(shè)置堆的最小值為20MB * -Xmx設(shè)置堆的最大值為20MB * -XX:+HeapDumpOnOutOfMemoryError內(nèi)存溢出時(shí)dump堆信息 */public class HeapOOM { static class OOMObject{ } public static void main(String[] args) { List<OOMObject> list = new ArrayList<>() ; while(true){ list.add(new OOMObject()) ; } } }輸出:java.lang.OutOfMemoryError: Java heap spaceDumping heap to java_pid6992.hPRof ...Heap dump file created [27980588 bytes in 0.197 secs]Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOf(Unknown Source) at java.util.Arrays.copyOf(Unknown Source) at java.util.ArrayList.grow(Unknown Source) at java.util.ArrayList.ensureExplicitCapacity(Unknown Source) at java.util.ArrayList.ensureCapacityInternal(Unknown Source) at java.util.ArrayList.add(Unknown Source) at com.HeapOOM.main(HeapOOM.java:20)3.2 虛擬機(jī)棧和本地方法棧溢出
/** * -Xss128k * -Xss設(shè)置堆棧內(nèi)存 * */public class JVMSOF { private int stackDepth = 1; public void stackLeak(){ stackDepth++ ; stackLeak(); } public static void main(String[] args) { JVMSOF jvmsof = new JVMSOF() ; try{ jvmsof.stackLeak(); }catch(Throwable e){ e.printStackTrace(); System.out.println(jvmsof.stackDepth); } }}結(jié)果:986Exception in thread "main" java.lang.StackOverflowError at com.JVMSOF.stackLeak(JVMSOF.java:13) at com.JVMSOF.stackLeak(JVMSOF.java:14) at com.JVMSOF.stackLeak(JVMSOF.java:14)3.3 方法區(qū)OOM
import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;/** * -XX:PermSize=10M -XX:MaxPermSize=10M * -XX:PermSize設(shè)置方法區(qū)的大小 * 這兩個(gè)參數(shù)在java8中忽略,并且下面代碼在java8后沒(méi)有memoryOutOfError異常 * */public class RuntimeConstantPoolOOM { public static void main(String[] args) { while(true){ Enhancer enhancer = new Enhancer() ; enhancer.setSuperclass(RCPOOMObject.class); enhancer.setUseCache(false); enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { return proxy.invokeSuper(obj, args); } }); enhancer.create() ; } } static class RCPOOMObject{ }}
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注