JAVA -Xms -Xmx -XX:PermSize -XX:MaxPermSize 區別

曾燕輝發表於2018-06-25

java  -Xms -Xmx -XX:PermSize -XX:MaxPermSize

轉載自:https://www.cnblogs.com/koik/p/4452029.html


    在做java開發時尤其是大型軟體開發時經常會遇到記憶體溢位的問題,比如說OutOfMemoryError等。這是個讓開發人員很痛苦、也很糾結的問題,因為我們有時不知道什麼樣的操作導致了這種問題的發生。所以我們不得不通過不斷的優化自己的程式碼結構,重構了一次又一次。雖然說不斷的重構自己的程式碼對公對私都是一件非常好的事,但是有時我們會發現有些時候不單單是通過重構自身的程式碼就能夠解決這樣的問題,因為也可能是由於我們對java虛擬機器執行時的記憶體分配的不得當導致了記憶體溢位現象的不斷髮生。為了解決這一問題,java開發團隊提供了一個使用者自定義的方式按需配置java虛擬機器執行時的所需的記憶體——通過引數配置的形式實現引數分配自定義化。

    在解析如何通過引數來配置JVM執行時記憶體分配之前,要說明一下JVM執行時記憶體的格局。

JVM按照其儲存資料的內容將所需記憶體分配為堆區與非堆區兩個部分:
所謂堆區即為通過new的方式建立的物件(類例項)所佔用的記憶體空間;非堆區即為程式碼、常量、外部訪問(如檔案訪問流所佔資源)等。然而雖然java的垃圾回收機制雖然能夠很好的解決記憶體浪費的問題,但是這種機制也僅僅的是回收堆區的資源,而對於非堆區的資源就束手無策了,針對這樣的資源回收只能憑藉開發人員自身的約束來解決。就算是這樣(堆區有java回收機制、非堆區開發人員能夠很好的解決),當執行時所需記憶體瞬間激增的時候JVM無奈的也要中止程式的執行。所以本文講述的是如何解決後者的問題。
好了,說了這麼多是時候講一下配置JVM記憶體的幾種引數及其如何使用了。
首先,常見引數種類(配置記憶體):(-Xms 、-Xmx、-XX:newSize、-XX:MaxnewSize、-Xmn)、(-XX:PermSize、-XX:MaxPermSize)。可以從列舉的方式上看出我的用意,引數的配置是分組的,前者是用來配置堆區的,後者是用來配置非堆區的。
    第一組配置引數:-Xms 、-Xmx、-XX:newSize、-XX:MaxnewSize、-Xmn
    
    1、-Xms :表示java虛擬機器堆區記憶體初始記憶體分配的大小,通常為作業系統可用記憶體的1/64大小即可,但仍需按照實際情況進行分配。有可能真的按照這樣的一個規則分配時,設計出的軟體還沒有能夠執行得起來就掛了。
    2、-Xmx: 表示java虛擬機器堆區記憶體可被分配的最大上限,通常為作業系統可用記憶體的1/4大小。但是開發過程中,通常會將 -Xms 與 -Xmx兩個引數的配置相同的值,其目的是為了能夠在java垃圾回收機制清理完堆區後不需要重新分隔計算堆區的大小而浪費資源。

    一般來講對於堆區的記憶體分配只需要對上述兩個引數進行合理配置即可,但是如果想要進行更加精細的分配還可以對堆區記憶體進一步的細化,那就要用到下面的三個引數了-XX:newSize、-XX:MaxnewSize、-Xmn。當然這源於對堆區的進一步細化分:新生代、中生代、老生代。java中每新new一個物件所佔用的記憶體空間就是新生代的空間,當java垃圾回收機制對堆區進行資源回收後,那些新生代中沒有被回收的資源將被轉移到中生代,中生代的被轉移到老生代。而接下來要講述的三個引數是用來控制新生代記憶體大小的。

    1、-XX:newSize:表示新生代初始記憶體的大小,應該小於 -Xms的值;
    2、-XX:MaxnewSize:表示新生代可被分配的記憶體的最大上限;當然這個值應該小於 -Xmx的值;
    3、-Xmn:至於這個引數則是對 -XX:newSize、-XX:MaxnewSize兩個引數的同時配置,也就是說如果通過-Xmn來配置新生代的記憶體大小,那麼-XX:newSize = -XX:MaxnewSize = -Xmn,雖然會很方便,但需要注意的是這個引數是在JDK1.4版本以後才使用的。

    上面所述即為java虛擬機器對外提供的可配置堆區的引數,接下來講述java虛擬機器對非堆區記憶體配置的兩個引數:
    
    1、-XX:PermSize:表示非堆區初始記憶體分配大小,其縮寫為permanent size(持久化記憶體)
    2、-XX:MaxPermSize:表示對非堆區分配的記憶體的最大上限。
    
    這裡面非常要注意的一點是:在配置之前一定要慎重的考慮一下自身軟體所需要的非堆區記憶體大小,因為此處記憶體是不會被java垃圾回收機制進行處理的地方。並且更加要注意的是 最大堆記憶體與最大非堆記憶體的和絕對不能夠超出作業系統的可用記憶體。

相關文章