當我開始學習Java編程時我不知道什麼是堆內存或堆空間我甚至不知道當對象創建時它們被放在了哪裡當我開始正式寫一些程序後我會經常遇到javalangoutOfMemoryError的報錯之後我才開始關注什麼是堆內存或者說堆空間(heap space)對大多數程序員都經歷過這樣的過程因為學習一種語言是非常容易來的但是學習基礎是非常難的因為沒有什麼特定的流程讓你學習編程的每個基礎使你發覺編程的秘訣
對於程序員來說知道堆空間設置堆空間處理堆空間的outOfMemoryError錯誤分析heap dump是非常重要的這個關於Java堆的教程是給我剛開始學編程的兄弟看的如果你知道這個基礎知識或者知道底層發生了什麼當然可能幫助不是那麼大除非你知道了對象被創建在堆中否則你不會意識到OutOfMemoryError是發生在堆空間中的我盡可能的將我所知道的所有關於堆的知識都寫下來了也希望你們能夠盡可能多的貢獻和分享你的知識以便可以讓其他人也受益
Java中的堆空間是什麼?
當Java程序開始運行時JVM會從操作系統獲取一些內存JVM使用這些內存這些內存的一部分就是堆內存堆內存通常在存儲地址的底層向上排列當一個對象通過new關鍵字或通過其他方式創建後對象從堆中獲得內存當對象不再使用了被當做垃圾回收掉後這些內存又重新回到堆內存中要學習垃圾回收請閱讀Java中垃圾回收的工作原理
如何增加Java堆空間
在大多數位機Sun的JVM上Java的堆空間默認的大小為MB但也有例外例如在未Solaris操作系統(SPARC平台版本)上默認的最大堆空間和起始堆空間大小為 Xms=K 和 Xmx=M對於位操作系統一般堆空間大小增加約%但你使用Java 的throughput垃圾回收器默認最大的堆大小為物理內存的四分之一而起始堆大小為物理內存的十六分之一要想知道默認的堆大小的方法可以用默認的設置參數打開一個程序使用JConsole(JDK 之後都支持)來查看在VM Summary頁面可以看到最大的堆大小
用這種方法你可以根據你的程序的需要來改變堆內存大小我強烈建議采用這種方法而不是默認值如果你的程序很大有很多對象需要被創建的話你可以用Xms and Xmx這兩個參數來改變堆內存的大小Xms表示起始的堆內存大小Xmx表示最大的堆內存的大小另外有一個參數 Xmn它表示new generation(後面會提到)的大小有一件事你需要注意你不能任意改變堆內存的大小你只能在啟動JVM時設定它
堆和垃圾回收
我們知道對象創建在堆內存中垃圾回收這樣一個進程它將已死對象清除出堆空間並將這些內存再還給堆為了給垃圾回收器使用堆主要分成三個區域分別叫作New GenerationOld Generation或叫Tenured Generation以及Perm spaceNew Generation是用來存放新建的對象的空間在對象新建的時候被使用如果長時間還使用的話它們會被垃圾回收器移動到Old Generation(或叫Tenured Generation)Perm space是JVM存放Meta數據的地方例如類方法字符串池和類級別的詳細信息你可以查看Java中垃圾回收的工作原理來獲得更多關於堆和垃圾回收的信息
Java堆中的OutOfMemoryError錯誤
當JVM啟動時使用了Xms 參數設置的對內存當程序繼續進行創建更多對象JVM開始擴大堆內存以容納更多對象JVM也會使用垃圾回收器來回收內存當快達到Xmx設置的最大堆內存時如果沒有更多的內存可被分配給新對象的話JVM就會拋出javalangoutofmemoryerror你的程序就會當掉在拋出 OutOfMemoryError之前JVM會嘗試著用垃圾回收器來釋放足夠的空間但是發現仍舊沒有足夠的空間時就會拋出這個錯誤為了解決這個問題你需要清楚你的程序對象的信息例如你創建了哪些對象哪些對象占用了多少空間等等你可以使用profiler或者堆分析器來處理 OutOfMemoryError錯誤javalangOutOfMemoryError Java heap space表示堆沒有足夠的空間了不能繼續擴大了javalangOutOfMemoryError PermGen space表示permanent generation已經裝滿了你的程序不能再裝在類或者再分配一個字符串了
Java Heap dump
Heap dump是在某一時間對Java堆內存的快照它對於分析堆內存或處理內存洩露和Javalangoutofmemoryerror錯誤是非常有用的在JDK中有一些工具可以幫你獲取heap dump也有一些堆分析工具來幫你分析heap dump你可以用jmap來獲取heap dump它幫你創建heap dump文件然後你可以用jhat(堆分析工具)來分析這些heap dump
Java堆內存(heap memory)的十個要點
Java堆內存是操作系統分配給JVM的內存的一部分
當我們創建對象時它們存儲在Java堆內存中
為了便於垃圾回收Java堆空間分成三個區域分別叫作New Generation Old Generation或叫作Tenured Generation還有Perm Space
你可以通過用JVM的命令行選項 Xms Xmx Xmn來調整Java堆空間的大小不要忘了在大小後面加上M或者G來表示單位舉個例子你可以用 Xmxm來設置堆內存最大的大小為MB
你可以用JConsole或者 RuntimemaxMemory() RuntimetotalMemory() RuntimefreeMemory()來查看Java中堆內存的大小
你可以使用命令jmap來獲得heap dump用jhat來分析heap dump
Java堆空間不同於棧空間棧空間是用來儲存調用棧和局部變量的
Java垃圾回收器是用來將死掉的對象(不再使用的對象)所占用的內存回收回來再釋放到Java堆空間中
當你遇到javalangoutOfMemoryError時不要緊張有時候僅僅增加堆空間就可以了但如果經常出現的話就要看看Java程序中是不是存在內存洩露了
請使用Profiler和Heap dump分析工具來查看Java堆空間可以查看給每個對象分配了多少內存
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26778.html