Tomcat 內存與優化
一、Tomcat 運行環境介紹
1.Tomcat 本身無法直接在計算機上運行,需要依賴硬件基礎上的操作系統和Java虛擬機;
2.Java 程序啟動時JVM都會分配一個初始內存和最大內存給這個應用;
3.當應用程序用到最大內存的時刻,就會觸發JVM做垃圾回收(GC)動作,釋放被占用的內存;
4.因此想要調整Java程序啟動時的初始內存和最大內存,需要向JVM申請;
5.如果初始內存大小設置過小,且此時初始化的應用對象過多,虛擬機就必須重復的加載內存來滿足使用;
6.基於以上原因,最好把初始內存大小(Xms)和最大內存(Xmx)設置成一樣;
7.JVM上所有的對象都在"""堆區(heap)"""上分配內存(也有在"棧"上分配內存的)
8.堆區的大小是可以動態擴展的,但"""堆"""的大小受限於系統使用的物理內存,當應用程序需要的內存超出"堆"的最大值時,JVM虛擬機就會拋出內存溢出異常,並且導致應用程序奔潰;
9.基於以上原因,建議“堆”的大小設置成物理內存的80%
二、Tomcat 內存設置(for Linux)
1.<CATALINA_HOME>/bin/catalina.sh #路徑以及修改內存的文件
2.JAVA_OPTS="-Xms256m -Xmx512m -Xss1024K -XX:PermSize=256m -XX:MaxPermSize=512m" #內存參數以及值
3.-Xms:初始內存大小
4.-Xmx:最大內存
5.-Xss:每個線程所消耗的內存大小(如-Xss15120是指每增加一個線程就會消耗15M內存),最好設置成128K,默認值為512K
6.-XX:PermSize:設定內存的永久保存區初始大小,默認為64M(永久是指方法區、永久代,還有年輕代、老年代)
7.-XX:MaxPermSize:設定內存永久保存區最大大小,默認為64M
8.其他參數:
a) -XX:SurvivorRatio=2: #生還者池的大小,默認是2,如果垃圾回收變成了瓶頸,可以嘗試定制生還者池設置
b) -XX:NewSize: #新生成的池的初始大小,默認為2M
c) -XX:MaxNewSize: #新生成的池的最大大小,默認為32M
d) +XX:AggressiveHeap #該參數會使得Xms沒有意義,這個參數讓參數JVM忽略Xmx參數,瘋狂的吃掉一個G的物理內存,再瘋狂的吃掉一個G的swap
e) -verbose:gc #實現垃圾收集信息
f) -Xloggc:gc.log #指定來及收集日志文件
g) -Xmn: #年輕代的堆區大小,一般設置成Xmx的3、4分之一
h) -XX:+UseParNewGC #縮短minor收集時間(minor GC是指在年輕代觸發的GC垃圾回收動作)
I) -XX:+UseConcMarkSweepGC #縮短major收集的時間(major收集是指在年老代觸發Full GC垃圾回收動作),此選項在heap size(堆區大小)比較大而且major收集時間較長的情況下使用更合適
j) -XX:userParNewGC #可用來並行收集(多CPU)
k) -XX:ParallerGCThreads #可用來增加並行度(多CPU)
l) -XX:UseParallerGC #設置后可以使用並行清理收集器(多CPU)
m) 如果JVM的堆大小大於 1G,則應該使用以下配置:
-XX:newSize=640m -XX:MaxNewSize=640m -XX:SurvivorRatio=16
或者將堆的總大小的50%到60%分配給新生成的池,調大新對象區,減少Full GC次數。
9.注意:
a) 虛擬機的"堆區大小"決定了虛擬機花費在收集垃圾上的時間和頻率;
b) 如果"堆的大小"很大,那么執行Full GC垃圾回收就會很慢,但是頻率降低了;
c) 如果把"堆的大小"調小,執行Full GC垃圾收回就會很快,但是會更加頻繁;
d) 因此建議把"堆區大小"設置物理內存的80%左右
e) 建議把內存的最高值和最低值的差值縮小。不然會浪費很多內存;
f) 最低值加大,那么最高值可以隨便設置;
g) 但是要根據實際的物理內存來設置,且大於物理內存,tomcat就無法啟動,可能會導致內存被系統收回,終止進程
三、Tomcat 內存溢出以及調整
1. java.lang.OutOfMemoryError: Java heap space ----JVM Heap(堆)溢出
a) 釋義:
1.JVM在啟動的時刻會自動設置JVM heap的值,其初始空間(即-Xms)是物理內存的1/64,最大空間(-Xmx)不可能超過物理內存;
2.可以利用JVM提供的 -Xmn -Xms -Xmx等選項進行設置;
3.heap的大小是年輕代(Young Generation)和年老代(Tenured Generaion)之和;
4.在JVM中如果98%的時間用於GC,且可用的heap size不足2%的時刻將拋出此異常信息;
b) 解決:
1.手動設置MaxPermSize的大小
2.JAVA_OPTS="-server -Xms256m -Xmx512m -XX:PermSize=64M -XX:MaxPermSize=128m"
2. java.lang.OutOfMemoryError: PermGen space ---- PermGen space溢出
a) 釋義:
1.PermGen Space全程是Permanent Generation space,是指內存的永久保存區域;
2.這里內存溢出的原因是因為這塊內存主要是被JVM存放class和meta信息的,class在被load的時刻被放入PermGen Space區域;
3.PermGen Space區域與存放instance的heap區域不同,GC不會在主程序運行期間對PermGen Space進行清理;
4.基於以上原因,如果你的APP會載入很多class的話,就很可能出現PermGen Space溢出;
b) 解決:
1.手動設置MaxPermSize大小
3.java.lang.StackOverflowError ---- 棧溢出
a) 釋義:
1.JVM采用的是棧式虛擬機,函數的調用過程都體現在堆棧和退棧上;
2.調用構造函數的"層"太多了,以至於把棧區溢出了;
b) 解決:
1.修改程序
4.ava.lang.OutOfMemoryError: GC overhead limit exceeded
a) 這里的意思是指JVM溢出
b) 增加參數,-XX:-UseGCOverheadLimit,關閉這個特性,同時增加heap大小,-Xmx1024m
