垃圾回收是Java程序員瞭解最少的一部分。他們認爲Java虛擬機接管了垃圾回收,所以不必去擔憂內存的申請,分配等問題。可是隨着應用愈來愈複雜,垃圾回收也愈來愈複雜,一旦垃圾回收變的複雜,應用的性能將會大打折扣。因此,Java程序員瞭解垃圾回收的機制而且知道怎樣解決「內存溢出」問題會有很大的益處。在Java中,有兩個很是廣泛的內存溢出問題。一個是堆內存溢出,另外一個是持久代內存溢出。html
Java對象是java 類的實例。每當建立一個Java對象時,Java虛擬機都會建立該對象的內部引用而且保存在堆中。若是一個類是第一次訪問,那麼它必須經過Java虛擬機加載進來。類加載是定位,尋找,加載class文件和解析class文件結構的過程。類加載器負責確保加載正確的class文件。Java程序裏面每個class文件須要被同一個類加載加載。類加載器是 java.lang.ClassLoader 類的實例。目前爲止,類加載器是在持久代空間裏面加載類的。java
Java虛擬機也建立了Java類的內部引用保存在持久代。在垃圾回收期間,Java對象和類都當作對象處理而且以一樣的方式回收。最初Java對象和類都是保存在堆中。程序員
一個性能優化措施:一旦持久代建立後,就會把classes放入裏面。Classes是Java虛擬機的部分實現,咱們不該該用咱們的數據結構填滿Java堆。持久代包含如下類信息:apache
如今咱們知道了持久代是什麼,接下來看看在這塊會是什麼緣由引發內存問題。數組
當Java虛擬機須要加載定義的一個新class,可是在持久代中沒有足夠的空間就會拋出‘Java.Lang.OutOfMemoryError: PermGen Space’異常。默認分配給持久代的大小在server模式下是64MB ,在client模式下是32MB 。這就有兩個緣由可能會引發持久代內存溢出問題的發生。tomcat
第一個緣由多是你應用或者服務器已經有很是多的class在你的持久代中,已經不能容納全部的class了。性能優化
若是是由於大量的class致使持久代的空間的不足引發的問題,那麼你能夠增長持久代的大小經過–XX:MaxPermSize=XXm 參數。這將增長持久代的可用空間來保存class。看起來像這樣: -XX:MaxPermSize=256m服務器
這個參數表示在使用CMS垃圾回收機制的時候是否啓用類卸載功能。默認這個是設置爲不啓用的,因此你想啓用這個功能你須要在Java參數中明確的設置下面的參數:數據結構
-XX:+CMSClassUnloadingEnabled框架
若是你啓用了CMSClassUnloadingEnabled ,垃圾回收會清理持久代,移除再也不使用的classes。這個參數只有在 UseConcMarkSweepGC 也啓用的狀況下才有用。參數以下:
-XX:+UseConcMarkSweepGC
這個參數表示是否會清理持久代。默認是不清理的,所以咱們須要明確設置這個參數來調試持久代內存溢出問題。這個參數在Java6中被移除了,所以你須要使用 -XX:+CMSClassUnloadingEnabled 若是你是使用Java6或者後面更高的版本。那麼解決持久代內存大小問題的參數看起來會是下面這樣子:
-XX:MaxPermSize=128m -XX:+UseConcMarkSweepGC XX:+CMSClassUnloadingEnabled
第二個緣由多是內存泄露。那麼加載的類怎樣變成不用的呢?
在Java中一般class是永久存在的。一旦class被加載,他們就呆在內存中,即便服務器上的應用停掉了。像cglib這樣能夠動態產生class的類庫會使用不少持久代空間,由於它動態的建立不少class。頻繁的使用在運行時建立的代理類。當一個類定義能夠爲多個實例重用時很容易建立新的代理類。
Sping和Hibernate常常會代理某些class。這些代理的class是經過類加載器加載的。產生的類定義若是一直不回收就會致使持久代空間很快就滿了。
你須要肯定是否是內存泄露引發的持久代空間的問題,同時解決它。增長持久代空間大小將不會有用,這隻會延遲它的發生,由於在某個時間點持久代仍是會被填滿。
若是你正在使用tomcat遇到了內存泄露問題,最新版本的tomcat有能力處理一些內存泄露問題。詳細請看:
一旦你遇到了持久代內容溢出問題,你須要找出這個問題是由於加載了大量的class文件仍是內存泄露引發的。若是是由於class的數量過多,你能夠增長持久代分配的空間大小來解決這個問題。若是是由於內存泄露,你須要引發內存泄露的根源所在而且定位它。一些框架像cglib,Spring,Hibernate會建立大量的動態類,所以對於使用這些框架的應用最好是分配多一點的持久代空間。
原文連接: http://www.javacodegeeks.com/2013/12/decoding-java-lang-outofmemoryerror-permgen-space.html