java內存區域與內存溢出異常

編程語言 Java 0verflow 技術 曹州錦衣衛指揮使 曹州錦衣衛指揮使 2017-09-23

一、運行時數據區域

1.程序計數器

2.java虛擬機棧

a.線程私有

b.他的生命週期與線程相同,它描述的是java方法執行的內存模型:方法在執行時會創建一個棧幀用於存放局部變量表、操作數棧、動態鏈接、方法出口等信息

c.局部變量表中存放的是:編譯期可知的基本數據類型、對象引用和returnAddress類型

d.如果線程請求的棧深度大於虛擬機所允許的深度,會拋出StackOverflowError異常;如果擴展時無法申請到足夠的內存時會拋出OutOfMemoryError異常

3.本地方法棧

4.java堆

a.線程共享

b.所有對象實例和數據都要在堆上分配空間

c.根據分代回收還分為:新生代和老年代,新生代又可分為:Eden空間、From Survivor空間、ToSurvivor空間。

d.堆若無空間時會拋出OutOfMemoryError異常

5.方法區

a.線程共享

b.存放已經被虛擬機加載的類信息、常量、靜態變量、即時編譯編譯的代碼等

c.

6.運行時常量池

a.

常量池(Constant Pool):常量池數據編譯期被確定,是Class文件中的一部分。存儲了類、方法、接口等中的常量,當然也包括字符串常量。

字符串池/字符串常量池(String Pool/String Constant Pool):是常量池中的一部分,存儲編譯期類中產生的字符串類型數據。(jdk1.7移至堆中)

運行時常量池(Runtime Constant Pool):方法區的一部分,所有線程共享。虛擬機加載Class後把常量池中的數據放入到運行時常量池。

b.在無法申請內存空間時會拋出OutOfMemoryError異常

7.直接內存

a.java引入nio,引入了基於通到(Channel)與緩衝區(Buffer)的I/O方式,使用native直接分配堆外內存


二、 虛擬機對象

1.對象的創建

a.首先檢查這個指令的參數是否能在常量池中定位一個類的符號引用,並檢查這個符號引用代表的類是否被加載、解析和初始化。若無,,則執行

b.接下來就是分配內存,所需大小在加載完畢就確定。堆中內存不規整,需要維護一個內存記錄表,內存是否規整由回收期決定

2.對象的內存佈局

a.可分為三塊:對象頭(Header)、實例數據(Instance Data)和對齊填充(Padding)

b.對象頭包括兩部分:第一部分,存儲對象自身的運行時數據,如hash、GC分代年齡、鎖狀態標誌、偏向線程ID、偏向時間戳;另外一部分是類型指針,即對象指向它的類元數據的指針,虛擬機通過這個指針來確定這個對象是哪個類的實例

3,.對象的訪問定位

a.使用句柄和直接指針

b.使用句柄 reference中存放的是句柄地址,不會改變,指針則訪問比較快

4.可能存在OOM的地方

a.堆

只要不斷創建對象(調小最大堆的值-Xmx)就能跑出OOM異常(分為內存洩漏Memory leak和內存溢出Memory Overflow)

b.虛擬機棧和本地方法棧

棧容量由-Xss參數設定,兩種異常:如果線程請求的棧深度大於虛擬機所允許的深度拋出StackOverflowError;如果虛擬機擴展時無法申請到足夠多的內存空間,拋出OOM

使用遞歸的方法可以拋出異常

c.方法區和運行時常量池

使用-XX:PermSize和-XX:MaxPermSize限制大小

使用String.intern():如果字符串常量池中已經包含一個等於此String對象的字符串,則返回代表池中這個String對象,否則將此String對象的字符串加到常量池,並返回對象的引用。

5.本機直接內存

使用-XX:MaxDirectMemorySize

通過反射獲取Unsafe實例

這是我的第一個頭條文章,接下來我會繼續寫關於java或者web服務相關的內容,包括自己的總結和轉載的,謝謝。


相關推薦

推薦中...