jvm內存共分為虛擬機棧瞄崇,堆 员串,方法區(qū)勇哗,程序計數(shù)器,本地方法區(qū)五個部分寸齐。
程序計數(shù)器(線程私有):
是當前線程所執(zhí)行的字節(jié)碼的行號指示器欲诺,每條線程都要有一個獨立的程序計數(shù)器,這類內存也稱為“線程私有”的內存渺鹦。
正在執(zhí)行java方法的話扰法,計數(shù)器記錄的是虛擬機字節(jié)碼指令的地址(當前指令的地址)。如果還是Native方法毅厚,則為空塞颁。
這個內存區(qū)域是唯一一個在虛擬機中沒有規(guī)定任何OutOfMemoryError情況的區(qū)域。
Java虛擬機棧(線程私有):
也是線程私有的。
每個方法在執(zhí)行的時候會創(chuàng)建一個棧幀祠锣,存儲了局部變量表酷窥,操作數(shù)棧,動態(tài)連接锤岸,方法返回地址等竖幔。
每個方法從調用到執(zhí)行完畢,對應一個棧幀在虛擬機棧中的入棧和出棧是偷。
通常所說的棧拳氢,一般是指虛擬機棧中的局部變量表部分。
局部變量表所需的內存在編譯期間完成分配蛋铆。
如果線程請求的棧深度大于虛擬機所允許的深度馋评,則StackOverflowError。
如果虛擬機棿汤玻可以動態(tài)擴展留特,擴展到無法申請足夠的內存,則OutOfMemoryError玛瘸。
本地方法棧(線程私有):
和虛擬機棧類似蜕青,主要為虛擬機使用到的Native方法服務。
也會拋出StackOverflowError和OutOfMemoryError糊渊。
Java堆(線程共享):
被所有線程共享的一塊內存區(qū)域右核,在虛擬機啟動時創(chuàng)建,用于存放對象實例渺绒。
堆可以按照可擴展來實現(xiàn)(通過-Xmx和-Xms來控制)
當堆中沒有內存可以分配給實例贺喝,也無法再擴展時,則拋出OutOfMemoryError異常宗兼。
方法區(qū)(線程共享):
被所有線程共享的一塊內存區(qū)域躏鱼。
用于存儲已被虛擬機加載的類信息殷绍,常量染苛,靜態(tài)變量等主到。
這個區(qū)域的內存回收目標主要針對常量池的回收和對類型的卸載。
當方法區(qū)無法滿足內存分配需求時镰烧,則拋出OutOfMemoryError異常拢军。
在HotSpot虛擬機中,用永久代來實現(xiàn)方法區(qū)怔鳖,將GC分代收集擴展至方法區(qū),但是這樣容易遇到內存溢出的問題。
JDK1.7中度陆,已經(jīng)把放在永久代的字符串常量池移到堆中。
JDK1.8撤銷永久代懂傀,引入元空間趾诗。
運行時常量池:
是方法區(qū)的一部分,用于存放編譯期生成的各種字面量和符號引用蹬蚁。
當常量池無法再申請到內存時恃泪,則拋出OutOfMemoryError異常犀斋。
直接內存:
不是運行時數(shù)據(jù)區(qū)的一部分,但也可能拋出OutOfMemoryError異常叽粹。
在JDK1.4中新加入的NOI類,引入了一種基于通道與緩沖區(qū)的I/O方式虫几,它可以使用Native函數(shù)直接分配堆外內存,
然后通過一個存儲在Java堆中的DirectByteBuffer對象作為這塊內存的引用進行操作