一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Tomcat中JVM內(nèi)存溢出及合理配置及maxThreads如何配置

 WindySky 2016-04-18

Tomcat本身不能直接在計算機上運行,需要依賴于硬件基礎(chǔ)之上的操作系統(tǒng)和一個Java虛擬機。Tomcat的內(nèi)存溢出本質(zhì)就是JVM內(nèi)存溢出,所以在本文開始時,應(yīng)該先對Java JVM有關(guān)內(nèi)存方面的知識進行詳細介紹。

一、Java JVM內(nèi)存介紹

JVM管理兩種類型的內(nèi)存,堆和非堆。按照官方的說法:“Java 虛擬機具有一個堆,堆是運行時數(shù)據(jù)區(qū)域,所有類實例和數(shù)組的內(nèi)存均從此處分配。堆是在 Java 虛擬機啟動時創(chuàng)建的?!薄霸贘VM中堆之外的內(nèi)存稱為非堆內(nèi)存(Non-heap memory)”。簡單來說堆就是Java代碼可及的內(nèi)存,是留給開發(fā)人員使用的;非堆就是JVM留給自己用的,所以方法區(qū)、JVM內(nèi)部處理或優(yōu)化所需的內(nèi)存(如JIT編譯后的代碼緩存)、每個類結(jié)構(gòu)(如運行時常數(shù)池、字段和方法數(shù)據(jù))以及方法和構(gòu)造方法的代碼都在非堆內(nèi)存中,它和堆不同,運行期內(nèi)GC不會釋放其空間。

(1). 堆內(nèi)存分配 
JVM初始分配的內(nèi)存由-Xms指定,默認是物理內(nèi)存的1/64;JVM最大分配的內(nèi)存由-Xmx指 定,默認是物理內(nèi)存的1/4。默認空余堆內(nèi)存小于 40%時,JVM就會增大堆直到-Xmx的最大限制;空余堆內(nèi)存大于70%時,JVM會減少堆直到-Xms的最小限制。因此服務(wù)器一般設(shè)置-Xms、 -Xmx相等以避免在每次GC 后調(diào)整堆的大小??梢岳肑VM提供的-Xmn -Xms -Xmx等選項可進行堆內(nèi)存設(shè)置,一般的要將-Xms和-Xmx選項設(shè)置為相同,而-Xmn為1/4的-Xmx值,建議堆的最大值設(shè)置為可用內(nèi)存的最大值的80%。

初始化堆的大小是JVM在啟動時向系統(tǒng)申請的內(nèi)存的大小。一般而言,這個參數(shù)不重要。但是有的應(yīng)用程序在大負載的情況下會急劇地占用更多的內(nèi)存,此時這個參數(shù)就是顯得非常重要,如果JVM啟動時設(shè)置使用的內(nèi)存比較小而在這種情況下有許多對象進行初始化,JVM就必須重復(fù)地增加內(nèi)存來滿足使用。由于這種原因,我們一般把-Xms和-Xmx設(shè)為一樣大,而堆的最大值受限于系統(tǒng)使用的物理內(nèi)存。一般使用數(shù)據(jù)量較大的應(yīng)用程序會使用持久對象,內(nèi)存使用有可能迅速地增長。當(dāng)應(yīng)用程序需要的內(nèi)存超出堆的最大值時JVM就會提示內(nèi)存溢出,并且導(dǎo)致應(yīng)用服務(wù)崩潰。所以,如果Xms超過了Xmx值,或者堆最大值和非堆最大值的總和超過了物理內(nèi)存或者操作系統(tǒng)的最大限制都會引起服務(wù)器啟動不起來。

(2). 非堆內(nèi)存分配 
也叫永久保存的區(qū)域,用于存放Class和Meta信息,Class在被Load的時候被放入該區(qū)域。它和存放類實例(Instance)的Heap區(qū)域不同,GC(Garbage Collection)不會在主程序運行期對PermGen space進行清理。JVM使用-XX:PermSize設(shè)置非堆內(nèi)存初始值,默認是物理內(nèi)存的1/64;由XX:MaxPermSize設(shè)置最大非堆內(nèi)存的大小,默認是物理內(nèi)存的1/4。 GC不會對PermGen space進行清理,所以如果你的APP會LOAD很多CLASS的話,就很可能出現(xiàn)PermGen space錯誤。

(3). JVM內(nèi)存限制(最大值) 
首先JVM內(nèi)存限制于實際的最大物理內(nèi)存(廢話!,呵呵),假設(shè)物理內(nèi)存無限大的話,JVM內(nèi)存的最大值跟操作系統(tǒng)有很大的關(guān)系。簡單的說就32位處理器雖然可控內(nèi)存空間有4GB,但是具體的操作系統(tǒng)會給一個限制,這個限制一般是2GB-3GB(一般來說Windows系統(tǒng)下為1.5G-2G,Linux系統(tǒng) 下為2G-3G),而64bit以上的處理器就不會有限制了。

二、三種內(nèi)存溢出異常介紹

1. OutOfMemoryError: Java heap space  堆溢出

內(nèi)存溢出主要存在問題就是出現(xiàn)在這個情況中。當(dāng)在JVM中如果98%的時間是用于GC且可用的 Heap size 不足2%的時候?qū)伋龃水惓P畔ⅰ?

 2. OutOfMemoryError: PermGen space   非堆溢出(永久保存區(qū)域溢出)

這種錯誤常見在web服務(wù)器對JSP進行pre compile的時候。如果你的WEB APP下都用了大量的第三方j(luò)ar, 其大小超過了jvm默認的大小(4M)那么就會產(chǎn)生此錯誤信息了。如果web app用了大量的第三方j(luò)ar或者應(yīng)用有太多的class文件而恰好MaxPermSize設(shè)置較小,超出了也會導(dǎo)致這塊內(nèi)存的占用過多造成溢出,或者tomcat熱部署時侯不會清理前面加載的環(huán)境,只會將context更改為新部署的,非堆存的內(nèi)容就會越來越多。

3. OutOfMemoryError: unable to create new native thread.   無法創(chuàng)建新的線程

這種現(xiàn)象比較少見,也比較奇怪,主要是和jvm與系統(tǒng)內(nèi)存的比例有關(guān)。這種怪事是因為JVM已經(jīng)被系統(tǒng)分配了大量的內(nèi)存(比如1.5G),并且它至少要占用可用內(nèi)存的一半。

三、Java JVM內(nèi)存配置

1. JVM內(nèi)存分配設(shè)置的參數(shù)有四個

-Xmx    Java Heap最大值,默認值為物理內(nèi)存的1/4;

-Xms    Java Heap初始值,Server端JVM最好將-Xms和-Xmx設(shè)為相同值,開發(fā)測試機JVM可以保留默認值;

-Xmn    Java Heap Young區(qū)大小,不熟悉最好保留默認值;

-Xss      每個線程的Stack大小,不熟悉最好保留默認值;

-XX:PermSize:設(shè)定內(nèi)存的永久保存區(qū)域; 

-XX:MaxPermSize:設(shè)定最大內(nèi)存的永久保存區(qū)域;

-XX:PermSize:設(shè)定內(nèi)存的永久保存區(qū)域;

-XX:NewSize:設(shè)置JVM堆的‘新生代’的默認大??;

-XX:MaxNewSize:設(shè)置JVM堆的‘新生代’的最大大?。?nbsp;

2. 如何設(shè)置JVM的內(nèi)存分配

(1)當(dāng)在命令提示符下啟動并使用JVM時(只對當(dāng)前運行的類Test生效):

java -Xmx128m -Xms64m -Xmn32m -Xss16m Test

(2)當(dāng)在集成開發(fā)環(huán)境下(如eclipse)啟動并使用JVM時:

a. 在eclipse根目錄下打開eclipse.ini,默認內(nèi)容為(這里設(shè)置的是運行當(dāng)前開發(fā)工具的JVM內(nèi)存分配):  -vmargs -Xms40m -Xmx256m -vmargs表示以下為虛擬機設(shè)置參數(shù),可修改其中的參數(shù)值,也可添加-Xmn,-Xss,另外,eclipse.ini內(nèi)還可以設(shè)置非   堆內(nèi)存,如:-XX:PermSize=56m,-XX:MaxPermSize=128m。

b. 打開eclipse-窗口-首選項-Java-已安裝的JRE(對在當(dāng)前開發(fā)環(huán)境中運行的java程序皆生效)  編輯當(dāng)前使用的JRE,在缺省VM參數(shù)中輸入:-Xmx128m -Xms64m -Xmn32m –Xss16m。

c. 打開eclipse-運行-運行-Java應(yīng)用程序(只對所設(shè)置的java類生效)  選定需設(shè)置內(nèi)存分配的類-自變量,在VM自變量中輸入:-Xmx128m -Xms64m -Xmn32m -Xss16m  注:如果在同一開發(fā)環(huán)境中同時進行了b和c設(shè)置,則b設(shè)置生效,c設(shè)置無效,如:  開發(fā)環(huán)境的設(shè)置為:-Xmx256m,而類Test的設(shè)置為:-Xmx128m -Xms64m,則運行Test時生效的設(shè)置為:  -Xmx256m -Xms64m。

(3)當(dāng)在服務(wù)器環(huán)境下(如Tomcat)啟動并使用JVM時(對當(dāng)前服務(wù)器環(huán)境下所以Java程序生效):

a. 設(shè)置環(huán)境變量:  變量名:CATALINA_OPTS  變量值:-Xmx128m -Xms64m -Xmn32m -Xss16m。

b. 打開Tomcat根目錄下的bin文件夾,編輯catalina.bat,將其中的%CATALINA_OPTS%(共有四處)替換為:-Xmx128m -Xms64m -Xmn32m -Xss16m。

c. 若沒有catalina.bat,只有tomcat.exe,tomcat6w.exe;則可以在啟動tomcat6w.exe 后 右鍵配置--Java--java option 下面輸入:

-Xmx256m –Xms64m

也可以找到注冊表HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\TomcatService Manager\Tomcat6\Parameters\JavaOptions原值為 -Dcatalina.home="C:\ApacheGroup\Tomcat 6.0" -Djava.endorsed.dirs="C:\ApacheGroup\Tomcat 6.0\common\endorsed" -Xrs 加入  -Xms300m  -Xmx350m  重起tomcat服務(wù),設(shè)置生效。

3. 查看JVM內(nèi)存信息

Runtime.getRuntime().maxMemory(); //最大可用內(nèi)存,對應(yīng)-Xmx 

Runtime.getRuntime().freeMemory(); //當(dāng)前JVM空閑內(nèi)存 

Runtime.getRuntime().totalMemory(); //當(dāng)前JVM占用的內(nèi)存總數(shù),其值相當(dāng)于當(dāng)前JVM已使用的內(nèi)存及freeMemory()的總和 

關(guān)于maxMemory(),freeMemory()和totalMemory():maxMemory()為JVM的最大可用內(nèi)存,可通過-Xmx設(shè)置,默認值為物理內(nèi)存的1/4,設(shè)置不能高于計算機物理內(nèi)存;  totalMemory()為當(dāng)前JVM占用的內(nèi)存總數(shù),其值相當(dāng)于當(dāng)前JVM已使用的內(nèi)存及freeMemory()的總和,會隨著JVM使用內(nèi)存的增加而增加;  freeMemory()為當(dāng)前JVM空閑內(nèi)存,因為JVM只有在需要內(nèi)存時才占用物理內(nèi)存使用,所以freeMemory()的值一般情況下都很小,而JVM實際可用內(nèi)存并不等于freeMemory(),而應(yīng)該等于maxMemory()-totalMemory()+freeMemory()。

4. 實例,以下給出1G內(nèi)存環(huán)境下java jvm 的參數(shù)設(shè)置參考

JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=128m -Djava.awt.headless=true "

大型的web工程,用tomcat默認分配的內(nèi)存空間無法啟動,如果不是在myeclipse中啟動tomcat可以對tomcat這樣設(shè)置:

TOMCAT_HOME\bin\catalina.bat 中添加這樣一句話:

set JAVA_OPTS= -Xmx1024M -Xms512M -XX:MaxPermSize=256m

如果要在myeclipse中啟動,上述的修改就不起作用了,可如下設(shè)置:

Myeclipse->preferences->myeclipse->servers->tomcat->tomcat×.×->JDK面板中的

Optional Java VM arguments中添加:-Xmx1024M -Xms512M -XX:MaxPermSize=256m

對于單獨的.class,可以用下面的方法對Test運行時的jvm內(nèi)存進行設(shè)置。 java -Xms64m -Xmx256m Test -Xms是設(shè)置內(nèi)存初始化的大小 -Xmx是設(shè)置最大能夠使用內(nèi)存的大小。

四、JVM內(nèi)存配置與GC

需要考慮的是Java提供的垃圾回收機制。JVM的堆大小決定了JVM花費在收集垃圾上的時間和頻度。收集垃圾可以接受的速度與應(yīng)用有關(guān),應(yīng)該通過分析實際的垃圾收集的時間和頻率來調(diào)整。如果堆的大小很大,那么完全垃圾收集就會很慢,但是頻度會降低。如果你把堆的大小和內(nèi)存的需要一致,完全收集就很快,但是會更加頻繁。調(diào)整堆大小的的目的是最小化垃圾收集的時間,以在特定的時間內(nèi)最大化處理客戶的請求。在基準(zhǔn)測試的時候,為保證最好的性能,要把堆的大小設(shè)大,保證垃圾收集不在整個基準(zhǔn)測試的過程中出現(xiàn)。如果系統(tǒng)花費很多的時間收集垃圾,請減小堆大小。一次完全的垃圾收集應(yīng)該不超過 3-5 秒。如果垃圾收集成為瓶頸,那么需要指定堆的大小,檢查垃圾收集的詳細輸出,研究垃圾收集參數(shù)對性能的影響。一般說來,你應(yīng)該使用物理內(nèi)存的 80% 作為堆大小。當(dāng)增加處理器時,記得增加內(nèi)存,因為分配可以并行進行,而垃圾收集不是并行的。

Java Heap分為3個區(qū):

1.Young 2.Old 3.Permanent。Young保存剛實例化的對象。當(dāng)該區(qū)被填滿時,GC會將對象移到Old區(qū)。Permanent區(qū)則負責(zé)保存反射對象,本文不討論該區(qū)。

JVM有2個GC線程: 
第一個線程負責(zé)回收Heap的Young區(qū); 
第二個線程在Heap不足時,遍歷Heap,將Young 區(qū)升級為Older區(qū),Older區(qū)的大小等于-Xmx減去-Xmn,不能將-Xms的值設(shè)的過大,因為第二個線程被迫運行會降低JVM的性能。

為什么一些程序頻繁發(fā)生GC?有如下原因: 
1. 程序內(nèi)調(diào)用了System.gc()或Runtime.gc()。 
2. 一些中間件軟件調(diào)用自己的GC方法,此時需要設(shè)置參數(shù)禁止這些GC。 
3. Java的Heap太小,一般默認的Heap值都很小。 
4. 頻繁實例化對象,Release對象 此時盡量保存并重用對象,例如使用StringBuffer()和String()。

如果你發(fā)現(xiàn)每次GC后,Heap的剩余空間會是總空間的50%,這表示你的Heap處于健康狀態(tài)許多Server端的Java程序每次GC后最好能有65%的剩余空間。

經(jīng)驗之談: 
1.Server端JVM最好將-Xms和-Xmx設(shè)為相同值。為了優(yōu)化GC,最好讓-Xmn值約等于-Xmx的1/3。 
2.一個GUI程序最好是每10到20秒間運行一次GC,每次在半秒之內(nèi)完成。

注意: 
1.增加Heap的大小雖然會降低GC的頻率,但也增加了每次GC的時間。并且GC運行時,所有的用戶線程將暫停,也就是GC期間,Java應(yīng)用程序不做任何工作。 
2.Heap大小并不決定進程的內(nèi)存使用量。進程的內(nèi)存使用量要大于-Xmx定義的值,因為Java為其他任務(wù)分配內(nèi)存,例如每個線程的Stack等。

 

tomcat 的Connector配置如下

<</span>Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" maxThreads="800" acceptCount="1000"/>
 其中最后兩個參數(shù)意義如下:

maxThreads:tomcat起動的最大線程數(shù),即同時處理的任務(wù)個數(shù),默認值為200

acceptCount:當(dāng)tomcat起動的線程數(shù)達到最大時,接受排隊的請求個數(shù),默認值為100

 

這兩個值如何起作用,請看下面三種情況

情況1:接受一個請求,此時tomcat起動的線程數(shù)沒有到達maxThreads,tomcat會起動一個線程來處理此請求。

情況2:接受一個請求,此時tomcat起動的線程數(shù)已經(jīng)到達maxThreads,tomcat會把此請求放入等待隊列,等待空閑線程。

情況3:接受一個請求,此時tomcat起動的線程數(shù)已經(jīng)到達maxThreads,等待隊列中的請求個數(shù)也達到了acceptCount,此時tomcat會直接拒絕此次請求,返回connection refused

maxThreads如何配置

一般的服務(wù)器操作都包括量方面:1計算(主要消耗cpu),2等待(io、數(shù)據(jù)庫等)

第一種極端情況,如果我們的操作是純粹的計算,那么系統(tǒng)響應(yīng)時間的主要限制就是cpu的運算能力,此時maxThreads應(yīng)該盡量設(shè)的小,降低同一時間內(nèi)爭搶cpu的線程個數(shù),可以提高計算效率,提高系統(tǒng)的整體處理能力。

第二種極端情況,如果我們的操作純粹是IO或者數(shù)據(jù)庫,那么響應(yīng)時間的主要限制就變?yōu)榈却獠抠Y源,此時maxThreads應(yīng)該盡量設(shè)的大,這樣 才能提高同時處理請求的個數(shù),從而提高系統(tǒng)整體的處理能力。此情況下因為tomcat同時處理的請求量會比較大,所以需要關(guān)注一下tomcat的虛擬機內(nèi) 存設(shè)置和linux的open file限制。

我在測試時遇到一個問題,maxThreads我設(shè)置的比較大比如3000,當(dāng)服務(wù)的線程數(shù)大到一定程度時,一般是2000出頭,單次請求的響應(yīng)時間就會急劇的增加,

百思不得其解這是為什么,四處尋求答案無果,最后我總結(jié)的原因可能是cpu在線程切換時消耗的時間隨著線程數(shù)量的增加越來越大,

cpu把大多數(shù)時間都用來在這2000多個線程直接切換上了,當(dāng)然cpu就沒有時間來處理我們的程序了。

以前一直簡單的認為多線程=高效率。。其實多線程本身并不能提高cpu效率,線程過多反而會降低cpu效率。

當(dāng)cpu核心數(shù)<線程數(shù)時,cpu就需要在多個線程直接來回切換,以保證每個線程都會獲得cpu時間,即通常我們說的并發(fā)執(zhí)行。

所以maxThreads的配置絕對不是越大越好。

現(xiàn)實應(yīng)用中,我們的操作都會包含以上兩種類型(計算、等待),所以maxThreads的配置并沒有一個最優(yōu)值,一定要根據(jù)具體情況來配置。

最好的做法是:在不斷測試的基礎(chǔ)上,不斷調(diào)整、優(yōu)化,才能得到最合理的配置。

acceptCount的配置,我一般是設(shè)置的跟maxThreads一樣大,這個值應(yīng)該是主要根據(jù)應(yīng)用的訪問峰值與平均值來權(quán)衡配置的。

如果設(shè)的較小,可以保證接受的請求較快相應(yīng),但是超出的請求可能就直接被拒絕

如果設(shè)的較大,可能就會出現(xiàn)大量的請求超時的情況,因為我們系統(tǒng)的處理能力是一定的。

    

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国产一级不卡视频在线观看| 夜色福利久久精品福利| 亚洲乱码av中文一区二区三区| 亚洲欧洲一区二区综合精品| 日韩精品视频香蕉视频| 中文字幕在线五月婷婷| 亚洲欧美日韩精品永久| 亚洲一区二区精品国产av| 污污黄黄的成年亚洲毛片| 老熟妇2久久国内精品| 99国产高清不卡视频| 欧美欧美欧美欧美一区| 国产又色又爽又黄又大| 亚洲欧美日本成人在线| 91亚洲精品综合久久| 偷自拍亚洲欧美一区二页| 久久国产成人精品国产成人亚洲| 成人免费高清在线一区二区| 国产自拍欧美日韩在线观看 | 亚洲一区二区三区四区性色av| 中文字幕五月婷婷免费| 欧美日韩久久精品一区二区| 欧美日韩一区二区午夜| 老富婆找帅哥按摩抠逼视频| 亚洲欧美天堂精品在线| 国产日韩欧美专区一区| 高清亚洲精品中文字幕乱码| 国产一区二区不卡在线播放| 美女激情免费在线观看| 亚洲欧美日本视频一区二区| 果冻传媒在线观看免费高清| 欧美成人高清在线播放| 一区二区三区国产日韩| 国产av熟女一区二区三区蜜桃| 在线免费不卡亚洲国产| 亚洲国产av在线视频| 色丁香一区二区黑人巨大| 人妻内射在线二区一区| 国产亚洲精品俞拍视频福利区| 成人免费高清在线一区二区| 欧美尤物在线视频91|