啟動文件修改
在windows環(huán)境下,tomcat下的~/bin/catalina.bat文件,在文件頭部加入:
set "JAVA_OPTS=%JAVA_OPTS% -server -Xms5120m -Xmx10240m -XX:PermSize=640M -XX:MaxPermSize=2560m"
在linux環(huán)境下,tomcat下的~/bin/catalina.sh文件,在文件頭部加入:
JAVA_OPTS="$JAVA_OPTS -server -Xms4096m -Xmx6144m -XX:PermSize=256m -XX:MaxPermSize=2048m"
重啟tomcat,即可。
驗證
可以通過訪問 http://localhost:8080/manager/status 可以查看jvm的信息。tomcat的管理員配置詳見tomcat管理員配置
常用參數(shù)詳解:
-server:一定要作為第一個參數(shù),在多個 CPU 時性能佳,還有一種叫 -client 的模式,特點是啟動速度比較快,但運(yùn)行時性能和內(nèi)存管理效率不高,通常用于客戶端應(yīng)用程序或開發(fā)調(diào)試,在 32 位環(huán)境下直接運(yùn)行 Java 程序默認(rèn)啟用該模式。Server 模式的特點是啟動速度比較慢,但運(yùn)行時性能和內(nèi)存管理效率很高,適用于生產(chǎn)環(huán)境,在具有 64 位能力的 JDK 環(huán)境下默認(rèn)啟用該模式,可以不配置該參數(shù)。
-Xms:表示 Java 初始化堆的大小,-Xms 與-Xmx 設(shè)成一樣的值,避免 JVM 反復(fù)重新申請內(nèi)存,導(dǎo)致性能大起大落,默認(rèn)值為物理內(nèi)存的 1/64,默認(rèn)(MinHeapFreeRatio參數(shù)可以調(diào)整)空余堆內(nèi)存小于 40% 時,JVM 就會增大堆直到 -Xmx 的最大限制。
-Xmx:表示最大 Java 堆大小,當(dāng)應(yīng)用程序需要的內(nèi)存超出堆的最大值時虛擬機(jī)就會提示內(nèi)存溢出,并且導(dǎo)致應(yīng)用服務(wù)崩潰,因此一般建議堆的最大值設(shè)置為可用內(nèi)存的最大值的80%。如何知道我的 JVM 能夠使用最大值,使用 java -Xmx512M -version 命令來進(jìn)行測試,然后逐漸的增大 512 的值,如果執(zhí)行正常就表示指定的內(nèi)存大小可用,否則會打印錯誤信息,默認(rèn)值為物理內(nèi)存的 1/4,默認(rèn)(MinHeapFreeRatio參數(shù)可以調(diào)整)空余堆內(nèi)存大于 70% 時,JVM 會減少堆直到-Xms 的最小限制。
-Xss:表示每個 Java 線程堆棧大小,JDK 5.0 以后每個線程堆棧大小為 1M,以前每個線程堆棧大小為 256K。根據(jù)應(yīng)用的線程所需內(nèi)存大小進(jìn)行調(diào)整,在相同物理內(nèi)存下,減小這個值能生成更多的線程,但是操作系統(tǒng)對一個進(jìn)程內(nèi)的線程數(shù)還是有限制的,不能無限生成,經(jīng)驗值在 3000~5000 左右。一般小的應(yīng)用, 如果棧不是很深, 應(yīng)該是128k 夠用的,大的應(yīng)用建議使用 256k 或 512K,一般不易設(shè)置超過 1M,要不然容易出現(xiàn)out ofmemory。這個選項對性能影響比較大,需要嚴(yán)格的測試。
-XX:NewSize:設(shè)置新生代內(nèi)存大小。
-XX:MaxNewSize:設(shè)置最大新生代新生代內(nèi)存大小
-XX:PermSize:設(shè)置持久代內(nèi)存大小
-XX:MaxPermSize:設(shè)置最大值持久代內(nèi)存大小,永久代不屬于堆內(nèi)存,堆內(nèi)存只包含新生代和老年代。
-XX:+AggressiveOpts:作用如其名(aggressive),啟用這個參數(shù),則每當(dāng) JDK 版本升級時,你的 JVM 都會使用最新加入的優(yōu)化技術(shù)(如果有的話)。
-XX:+UseBiasedLocking:啟用一個優(yōu)化了的線程鎖,我們知道在我們的appserver,每個http請求就是一個線程,有的請求短有的請求長,就會有請求排隊的現(xiàn)象,甚至還會出現(xiàn)線程阻塞,這個優(yōu)化了的線程鎖使得你的appserver內(nèi)對線程處理自動進(jìn)行最優(yōu)調(diào)配。
-XX:+DisableExplicitGC:在 程序代碼中不允許有顯示的調(diào)用“System.gc()”。每次在到操作結(jié)束時手動調(diào)用 System.gc() 一下,付出的代價就是系統(tǒng)響應(yīng)時間嚴(yán)重降低,就和關(guān)于 Xms,Xmx 里的解釋的原理一樣,這樣去調(diào)用 GC 導(dǎo)致系統(tǒng)的 JVM 大起大落。
-XX:+UseConcMarkSweepGC:設(shè)置年老代為并發(fā)收集,即 CMS gc,這一特性只有 jdk1.5
后續(xù)版本才具有的功能,它使用的是 gc 估算觸發(fā)和 heap 占用觸發(fā)。我們知道頻頻繁的 GC 會造面 JVM
的大起大落從而影響到系統(tǒng)的效率,因此使用了 CMS GC 后可以在 GC 次數(shù)增多的情況下,每次 GC 的響應(yīng)時間卻很短,比如說使用了 CMS
GC 后經(jīng)過 jprofiler 的觀察,GC 被觸發(fā)次數(shù)非常多,而每次 GC 耗時僅為幾毫秒。
-XX:+UseParNewGC:對新生代采用多線程并行回收,這樣收得快,注意最新的 JVM 版本,當(dāng)使用 -XX:+UseConcMarkSweepGC 時,-XX:UseParNewGC 會自動開啟。因此,如果年輕代的并行 GC 不想開啟,可以通過設(shè)置 -XX:-UseParNewGC 來關(guān)掉。
-XX:MaxTenuringThreshold:設(shè)置垃圾最大年齡。如果設(shè)置為0的話,則新生代對象不經(jīng)過 Survivor 區(qū),直接進(jìn)入老年代。對于老年代比較多的應(yīng)用(需要大量常駐內(nèi)存的應(yīng)用),可以提高效率。如果將此值設(shè)置為一 個較大值,則新生代對象會在 Survivor 區(qū)進(jìn)行多次復(fù)制,這樣可以增加對象在新生代的存活時間,增加在新生代即被回收的概率,減少Full GC的頻率,這樣做可以在某種程度上提高服務(wù)穩(wěn)定性。該參數(shù)只有在串行 GC 時才有效,這個值的設(shè)置是根據(jù)本地的 jprofiler 監(jiān)控后得到的一個理想的值,不能一概而論原搬照抄。
-XX:+CMSParallelRemarkEnabled:在使用 UseParNewGC 的情況下,盡量減少 mark 的時間。
-XX:+UseCMSCompactAtFullCollection:在使用 concurrent gc 的情況下,防止 memoryfragmention,對 live object 進(jìn)行整理,使 memory 碎片減少。
-XX:LargePageSizeInBytes:指定 Java heap 的分頁頁面大小,內(nèi)存頁的大小不可設(shè)置過大, 會影響 Perm 的大小。
-XX:+UseFastAccessorMethods:使用 get,set 方法轉(zhuǎn)成本地代碼,原始類型的快速優(yōu)化。
-XX:+UseCMSInitiatingOccupancyOnly:只有在 oldgeneration 在使用了初始化的比例后 concurrent collector 啟動收集。
-Duser.timezone=Asia/Shanghai:設(shè)置用戶所在時區(qū)。
-Djava.awt.headless=true:這個參數(shù)一般我們都是放在最后使用的,這全參數(shù)的作用是這樣的,有時我們會在我們的 J2EE 工程中使用一些圖表工具如:jfreechart,用于在 web 網(wǎng)頁輸出 GIF/JPG 等流,在 winodws 環(huán)境下,一般我們的 app server 在輸出圖形時不會碰到什么問題,但是在linux/unix 環(huán)境下經(jīng)常會碰到一個 exception 導(dǎo)致你在 winodws 開發(fā)環(huán)境下圖片顯示的好好可是在 linux/unix 下卻顯示不出來,因此加上這個參數(shù)以免避這樣的情況出現(xiàn)。
-Xmn:新生代的內(nèi)存空間大小,注意:此處的大小是(eden+ 2 survivor space)。與 jmap -heap 中顯示的 New gen 是不同的。整個堆大小 = 新生代大小 + 老生代大小 + 永久代大小。在保證堆大小不變的情況下,增大新生代后,將會減小老生代大小。此值對系統(tǒng)性能影響較大,Sun官方推薦配置為整個堆的 3/8。
-XX:CMSInitiatingOccupancyFraction:當(dāng)堆滿之后,并行收集器便開始進(jìn)行垃圾收集,例如,當(dāng)沒有足夠的空間來容納新分配或提升的對象。對于 CMS 收集器,長時間等待是不可取的,因為在并發(fā)垃圾收集期間應(yīng)用持續(xù)在運(yùn)行(并且分配對象)。因此,為了在應(yīng)用程序使用完內(nèi)存之前完成垃圾收集周期,CMS 收集器要比并行收集器更先啟動。因為不同的應(yīng)用會有不同對象分配模式,JVM 會收集實際的對象分配(和釋放)的運(yùn)行時數(shù)據(jù),并且分析這些數(shù)據(jù),來決定什么時候啟動一次 CMS 垃圾收集周期。這個參數(shù)設(shè)置有很大技巧,基本上滿足(Xmx-Xmn)(100-CMSInitiatingOccupancyFraction)/100 >= Xmn 就不會出現(xiàn) promotion failed。例如在應(yīng)用中 Xmx 是6000,Xmn 是 512,那么 Xmx-Xmn 是 5488M,也就是老年代有 5488M,CMSInitiatingOccupancyFraction=90 說明老年代到 90% 滿的時候開始執(zhí)行對老年代的并發(fā)垃圾回收(CMS),這時還 剩 10% 的空間是 548810% = 548M,所以即使 Xmn(也就是新生代共512M)里所有對象都搬到老年代里,548M 的空間也足夠了,所以只要滿足上面的公式,就不會出現(xiàn)垃圾回收時的 promotion failed,因此這個參數(shù)的設(shè)置必須與 Xmn 關(guān)聯(lián)在一起。
-XX:+CMSIncrementalMode:該標(biāo)志將開啟 CMS 收集器的增量模式。增量模式經(jīng)常暫停 CMS 過程,以便對應(yīng)用程序線程作出完全的讓步。因此,收集器將花更長的時間完成整個收集周期。因此,只有通過測試后發(fā)現(xiàn)正常 CMS 周期對應(yīng)用程序線程干擾太大時,才應(yīng)該使用增量模式。由于現(xiàn)代服務(wù)器有足夠的處理器來適應(yīng)并發(fā)的垃圾收集,所以這種情況發(fā)生得很少,用于但 CPU情況。
-XX:NewRatio:年輕代(包括 Eden 和兩個 Survivor 區(qū))與年老代的比值(除去持久代),-XX:NewRatio=4 表示年輕代與年老代所占比值為 1:4,年輕代占整個堆棧的 1/5,Xms=Xmx 并且設(shè)置了 Xmn 的情況下,該參數(shù)不需要進(jìn)行設(shè)置。
-XX:SurvivorRatio:Eden 區(qū)與 Survivor 區(qū)的大小比值,設(shè)置為 8,表示 2 個 Survivor 區(qū)(JVM 堆內(nèi)存年輕代中默認(rèn)有 2 個大小相等的 Survivor 區(qū))與 1 個 Eden 區(qū)的比值為 2:8,即 1 個 Survivor 區(qū)占整個年輕代大小的 1/10。
-XX:+UseSerialGC:設(shè)置串行收集器。
-XX:+UseParallelGC:設(shè)置為并行收集器。此配置僅對年輕代有效。即年輕代使用并行收集,而年老代仍使用串行收集。
-XX:+UseParallelOldGC:配置年老代垃圾收集方式為并行收集,JDK6.0 開始支持對年老代并行收集。
-XX:ConcGCThreads:早期 JVM 版本也叫-XX:ParallelCMSThreads,定義并發(fā) CMS 過程運(yùn)行時的線程數(shù)。比如 value=4 意味著 CMS 周期的所有階段都以 4 個線程來執(zhí)行。盡管更多的線程會加快并發(fā) CMS 過程,但其也會帶來額外的同步開銷。因此,對于特定的應(yīng)用程序,應(yīng)該通過測試來判斷增加 CMS 線程數(shù)是否真的能夠帶來性能的提升。如果還標(biāo)志未設(shè)置,JVM 會根據(jù)并行收集器中的 -XX:ParallelGCThreads 參數(shù)的值來計算出默認(rèn)的并行 CMS 線程數(shù)。
-XX:ParallelGCThreads:配置并行收集器的線程數(shù),即:同時有多少個線程一起進(jìn)行垃圾回收,此值建議配置與 CPU 數(shù)目相等。
-XX:OldSize:設(shè)置 JVM 啟動分配的老年代內(nèi)存大小,類似于新生代內(nèi)存的初始大小 -XX:NewSize。
以上就是一些常用的配置參數(shù),有些參數(shù)是可以被替代的,配置思路需要考慮的是 Java 提供的垃圾回收機(jī)制。虛擬機(jī)的堆大小決定了虛擬機(jī)花費(fèi)在收集垃圾上的時間和頻度。收集垃圾能夠接受的速度和應(yīng)用有關(guān),應(yīng)該通過分析實際的垃圾收集的時間和頻率來調(diào)整。假如堆的大小很大,那么完全垃圾收集就會很慢,但是頻度會降低。假如您把堆的大小和內(nèi)存的需要一致,完全收集就很快,但是會更加頻繁。調(diào)整堆大小的的目的是最小化垃圾收集的時間,以在特定的時間內(nèi)最大化處理客戶的請求。在基準(zhǔn)測試的時候,為確保最好的性能,要把堆的大小設(shè)大,確保垃圾收集不在整個基準(zhǔn)測試的過程中出現(xiàn)。
假如系統(tǒng)花費(fèi)很多的時間收集垃圾,請減小堆大小。一次完全的垃圾收集應(yīng)該不超過 3-5 秒。假如垃圾收集成為瓶頸,那么需要指定代的大小,檢查垃圾收集的周詳輸出,研究垃圾收集參數(shù)對性能的影響。當(dāng)增加處理器時,記得增加內(nèi)存,因為分配能夠并行進(jìn)行,而垃圾收集不是并行的。