Java虛擬機(JVM)中的內存設置詳解

    在一些規模稍大的應用中,Java虛擬機(JVM)的內存設置尤爲重要,想在項目中取得好的效率,GC(垃圾回收)的設置是第一步。

    PermGen space:全稱是Permanent Generation space.就是說是永久保存的區域,用於存放Class和Meta信息,Class在被Load的時候被放入該區域Heap space:存放Instance。

    GC(Garbage Collection)應該不會對PermGen space進行清理,所以如果你的APP會LOAD很多CLASS的話,就很可能出現PermGen space錯誤

Java Heap分爲3個區
    1.Young
    2.Old
    3.Permanent

    Young保存剛實例化的對象。當該區被填滿時,GC會將對象移到Old區。Permanent區則負責保存反射對象,本文不討論該區。

    JVM的Heap分配可以使用-X參數設定,

    -Xms 
    初始Heap大小
    -Xmx 
    java heap最大值 

    -Xmn 
    young generation的heap大小

JVM有2個GC線程
    第一個線程負責回收Heap的Young區
    第二個線程在Heap不足時,遍歷Heap,將Young 區升級爲Older區

    Older區的大小等於-Xmx減去-Xmn,不能將-Xms的值設的過大,因爲第二個線程被迫運行會降低JVM的性能。
 爲什麼一些程序頻繁發生GC?

   有如下原因:
   1.程序內調用了System.gc()或Runtime.gc()。
   2.一些中間件軟件調用自己的GC方法,此時需要設置參數禁止這些GC。
   3.Java的Heap太小,一般默認的Heap值都很小。
   4.頻繁實例化對象,Release對象 此時儘量保存並重用對象,例如使用StringBuffer()和String()。

   如果你發現每次GC後,Heap的剩餘空間會是總空間的50%,這表示你的Heap處於健康狀態,許多Server端的Java程序每次GC後最好能有65%的剩餘空間

經驗之談:

    1.Server端JVM最好將-Xms和-Xmx設爲相同值。爲了優化GC,最好讓-Xmn值約等於-Xmx的1/3。
    2.一個GUI程序最好是每10到20秒間運行一次GC,每次在半秒之內完成。

注意:

  1. 增加Heap的大小雖然會降低GC的頻率,但也增加了每次GC的時間。並且GC運行時,所有的用戶線程將暫停,也就是GC期間,Java應用程序不做任何工作。
  2. Heap大小並不決定進程的內存使用量。進程的內存使用量要大於-Xmx定義的值,因爲Java爲其他任務分配內存,例如每個線程的Stack等。

    Stack的設定
    每個線程都有他自己的Stack。

    -Xss 
    每個線程的Stack大小

    Stack的大小限制着線程的數量。如果Stack過大就好導致內存溢漏。-Xss參數決定Stack大小,例如-Xss1024K。如果Stack太小,也會導致Stack溢漏。

硬件環境

    硬件環境也影響GC的效率,例如機器的種類,內存,swap空間,和CPU的數量。
    如果你的程序需要頻繁創建很多transient對象,會導致JVM頻繁GC。這種情況你可以增加機器的內存,來減少Swap空間的使用。

4種GC

    1、第一種爲單線程GC,也是默認的GC,該GC適用於單CPU機器。
    2、第二種爲Throughput GC,是多線程的GC,適用於多CPU,使用大量線程的程序。第二種GC與第一種GC相似,不同在於GC在收集Young區是多線程的,但在Old區和第一種一樣,仍然採用單線程。-XX:+UseParallelGC參數啓動該GC。
    3、第三種爲Concurrent Low Pause GC,類似於第一種,適用於多CPU,並要求縮短因GC造成程序停滯的時間。這種GC可以在Old區的回收同時,運行應用程序。-XX:+UseConcMarkSweepGC參數啓動該GC。
    4、第四種爲Incremental Low Pause GC,適用於要求縮短因GC造成程序停滯的時間。這種GC可以在Young區回收的同時,回收一部分Old區對象。-Xincgc參數啓動該GC。

單文件的JVM內存進行設置

    默認的java虛擬機的大小比較小,在對大數據進行處理時java就會報錯:java.lang.OutOfMemoryError。
    設置jvm內存的方法,對於單獨的.class,可以用下面的方法對Test運行時的jvm內存進行設置。
    java -Xms64m -Xmx256m Test
    -Xms是設置內存初始化的大小
    -Xmx是設置最大能夠使用內存的大小(最好不要超過物理內存大小)

    tomcat啓動jvm內存設置

Linux:

在/usr/local/apache-tomcat-5.5.23/bin目錄下的catalina.sh添加:JAVA_OPTS='-Xms512m -Xmx1024m'要加“m”說明是MB,否則就是KB了,在啓動tomcat時會報內存不足。
-Xms:初始值
-Xmx:最大值
-Xmn:最小值Windows
在catalina.bat最前面加入
set JAVA_OPTS=-Xms128m -Xmx350m 如果用startup.bat啓動tomcat,OK設置生效.夠成功的分配200M內存.但是如果不是執行startup.bat啓動tomcat而是利用windows的系統服務啓動tomcat服務,上面的設置就不生效了,就是說set JAVA_OPTS=-Xms128m -Xmx350m 沒起作用.上面分配200M內存就OOM了..windows服務執行的是bin/tomcat.exe.他讀取註冊表中的值,而不是catalina.bat的設置.解決辦法:

修改註冊表HKEY_LOCAL_MACHINE/SOFTWARE/Apache Software Foundation/Tomcat Service Manager/Tomcat5/Parameters/JavaOptions

原值爲

-Dcatalina.home="C:/ApacheGroup/Tomcat 5.0"
-Djava.endorsed.dirs="C:/ApacheGroup/Tomcat 5.0/common/endorsed"
-Xrs加入 -Xms300m -Xmx350m

重起tomcat服務,設置生效

weblogic啓動jvm內存設置

在weblogic中,可以在startweblogic.cmd中對每個domain虛擬內存的大小進行設置,默認的設置是在commEnv.cmd裏面。

JBoss

默認可以使用的內存爲64MB 
$JBOSSDIR$/bin/run.config 
JAVA_OPTS = "-server -Xms128 -Xmx512"

Eclipse

在所在目錄下,鍵入 
eclipse.exe -vmargs -Xms256m -Xmx512m 
256m表示JVM堆內存最小值 
512m表示JVM堆內存最大

Websphere

進入控制檯去設置:應用程序服務器 > server1 > 進程定義 > Java 虛擬機

-----------------------------------------------------------------------------------------------------------------------------------------------------
JVM內存分配
如果採取默認配置的話,JVM默認只能分配到最大64M內存(默認大小和JVM版本有關係),這在生產環境裏肯定是不夠,將會導致用戶通過WEB方式無法訪問應用服務,但是系統進程中,JBOSS服務卻沒有宕掉的奇怪現象。
修改$jboss/bin/run.conf文件,找到“#JAVA_OPTS=”,如果沒有該字符串,請添加,並去掉最前面的“#”,修改該字符串(含雙引號)爲JAVA_OPTS="-server -Xms512m -Xmx512m”,這是分配JVM的最小和最大內存,取決於硬件物理內存的大小,建議均設爲物理內存的一半。

JAVA_OPTS爲:-Xms 520m -Xmx 1500m -Xss 128k
jboss性能優化:內存緊張的問題

JAVA_OPTS: -Xms 520m -Xmx 1220m -Xss 15120k +XX:AggressiveHeap

這個JAVA_OPTS犯了2個致命的錯誤:

1. +XX:AggressiveHeap會使得 Xms 1220m沒有意義。這個參數讓jvm忽略Xmx參數,瘋狂地吃完一個G物理內存,再吃盡一個G的swap。

另外Xmx作爲允許jvm使用的最大內存數量,不應該超過物理內存的90%。

而之所以使用了這個參數,是因爲不加的話,JBoss會在運行一天左右的時間後迅速崩潰,上機課是,甚至出現過半個小時就崩潰的情況。

之所以要用這個參數,用swap支持服務器運行,是因爲犯了下面的錯誤:

2. -Xss 15120k

這使得JBoss每增加一個線程(thread)就會立即消耗15M內存,而最佳值應該是128K,默認值好像是512k.

3. -Xms指定初始化內存大小



所作的修改:

1.修改JAVA_OPTS,去掉+XX:AggressiveHeap,修改Xss。現在的JAVA_OPTS爲:

-Xms 520m -Xmx 1500m -Xss 128k

2.修改deploy/jbossweb-tomcat55.sar/service.xml

將maxThreads根據目前的訪問量由默認的250降爲75,並使用jboss 4默認未寫在標準service.xml裏面而jboss 3寫入了的2個參數:

maxSparseThreads=200,minSparseThreads=100

3.修改oracle-ds.xml將最大連接數有150降爲50.
-----------------------------------------------------------------------------------------------------------------------------------------------------

JVM的垃圾回收機制詳解和調優

1.JVM的gc概述

    gc即垃圾收集機制是指jvm用於釋放那些不再使用的對象所佔用的內存。java語言並不要求jvm有gc,也沒有規定gc如何工作。不過常用的jvm都有gc,而且大多數gc都使用類似的算法管理內存和執行收集操作。

    在充分理解了垃圾收集算法和執行過程後,纔能有效的優化它的性能。有些垃圾收集專用於特殊的應用程序。比如,實時應用程序主要是爲了避免垃圾收集中斷,而大多數OLTP應用程序則注重整體效率。理解了應用程序的工作負荷和jvm支持的垃圾收集算法,便可以進行優化配置垃圾收集器。

    垃圾收集的目的在於清除不再使用的對象。gc通過確定對象是否被活動對象引用來確定是否收集該對象。gc首先要判斷該對象是否是時候可以收集。兩種常用的方法是引用計數和對象引用遍歷。

    1.1.引用計數

    引用計數存儲對特定對象的所有引用數,也就是說,當應用程序創建引用以及引用超出範圍時,jvm必須適當增減引用數。當某對象的引用數爲0時,便可以進行垃圾收集。

    1.2.對象引用遍歷

    早期的jvm使用引用計數,現在大多數jvm採用對象引用遍歷。對象引用遍歷從一組對象開始,沿着整個對象圖上的每條鏈接,遞歸確定可到達(reachable)的對象。如果某對象不能從這些根對象的一個(至少一個)到達,則將它作爲垃圾收集。在對象遍歷階段,gc必須記住哪些對象可以到達,以便刪除不可到達的對象,這稱爲標記(marking)對象。

    下一步,gc要刪除不可到達的對象。刪除時,有些gc只是簡單的掃描堆棧,刪除未標記的未標記的對象,並釋放它們的內存以生成新的對象,這叫做清除(sweeping)。這種方法的問題在於內存會分成好多小段,而它們不足以用於新的對象,但是組合起來卻很大。因此,許多gc可以重新組織內存中的對象,並進行壓縮(compact),形成可利用的空間。

    爲此,gc需要停止其他的活動活動。這種方法意味着所有與應用程序相關的工作停止,只有gc運行。結果,在響應期間增減了許多混雜請求。另外,更復雜的 gc不斷增加或同時運行以減少或者清除應用程序的中斷。有的gc使用單線程完成這項工作,有的則採用多線程以增加效率。

    2.幾種垃圾回收機制

    2.1.標記-清除收集器

    這種收集器首先遍歷對象圖並標記可到達的對象,然後掃描堆棧以尋找未標記對象並釋放它們的內存。這種收集器一般使用單線程工作並停止其他操作。

    2.2.標記-壓縮收集器

    有時也叫標記-清除-壓縮收集器,與標記-清除收集器有相同的標記階段。在第二階段,則把標記對象複製到堆棧的新域中以便壓縮堆棧。這種收集器也停止其他操作。

    2.3.複製收集器

    這種收集器將堆棧分爲兩個域,常稱爲半空間。每次僅使用一半的空間,jvm生成的新對象則放在另一半空間中。gc運行時,它把可到達對象複製到另一半空間,從而壓縮了堆棧。這種方法適用於短生存期的對象,持續複製長生存期的對象則導致效率降低。

    2.4.增量收集器

    增量收集器把堆棧分爲多個域,每次僅從一個域收集垃圾。這會造成較小的應用程序中斷。

    2.5.分代收集器

    這種收集器把堆棧分爲兩個或多個域,用以存放不同壽命的對象。jvm生成的新對象一般放在其中的某個域中。過一段時間,繼續存在的對象將獲得使用期並轉入更長壽命的域中。分代收集器對不同的域使用不同的算法以優化性能。

    2.6.併發收集器

    併發收集器與應用程序同時運行。這些收集器在某點上(比如壓縮時)一般都不得不停止其他操作以完成特定的任務,但是因爲其他應用程序可進行其他的後臺操作,所以中斷其他處理的實際時間大大降低。

    2.7.並行收集器

    並行收集器使用某種傳統的算法並使用多線程並行的執行它們的工作。在多cpu機器上使用多線程技術可以顯著的提高java應用程序的可擴展性。

    3.Sun HotSpot 1.4.1 JVM堆大小的調整

    Sun HotSpot 1.4.1使用分代收集器,它把堆分爲三個主要的域:新域、舊域以及永久域。Jvm生成的所有新對象放在新域中。一旦對象經歷了一定數量的垃圾收集循環後,便獲得使用期並進入舊域。在永久域中jvm則存儲class和method對象。就配置而言,永久域是一個獨立域並且不認爲是堆的一部分。

    下面介紹如何控制這些域的大小。可使用-Xms和-Xmx 控制整個堆的原始大小或最大值。

    下面的命令是把初始大小設置爲128M:

    java –Xms128m

    –Xmx256m爲控制新域的大小,可使用-XX:NewRatio設置新域在堆中所佔的比例。

    下面的命令把整個堆設置成128m,新域比率設置成3,即新域與舊域比例爲1:3,新域爲堆的1/4或32M:

    java –Xms128m –Xmx128m–XX:NewRatio =3可使用-XX:NewSize和-XX:MaxNewsize設置新域的初始值和最大值。

    下面的命令把新域的初始值和最大值設置成64m:

    java –Xms256m –Xmx256m –Xmn64m

    永久域默認大小爲4m.運行程序時,jvm會調整永久域的大小以滿足需要。每次調整時,jvm會對堆進行一次完全的垃圾收集。

    使用-XX:MaxPerSize標誌來增加永久域搭大小。在WebLogic Server應用程序加載較多類時,經常需要增加永久域的最大值。當jvm加載類時,永久域中的對象急劇增加,從而使jvm不斷調整永久域大小。爲了避免調整,可使用-XX:PerSize標誌設置初始值。

    下面把永久域初始值設置成32m,最大值設置成64m.

    java -Xms512m -Xmx512m -Xmn128m -XX:PermSize=32m -XX:MaxPermSize=64m

    默認狀態下,HotSpot在新域中使用複製收集器。該域一般分爲三個部分。第一部分爲Eden,用於生成新的對象。另兩部分稱爲救助空間,當Eden充滿時,收集器停止應用程序,把所有可到達對象複製到當前的from救助空間,一旦當前的from救助空間充滿,收集器則把可到達對象複製到當前的to救助空間。From和to救助空間互換角色。維持活動的對象將在救助空間不斷複製,直到它們獲得使用期並轉入舊域。使用-XX:SurvivorRatio可控制新域子空間的大小。

    同NewRation一樣,SurvivorRation規定某救助域與Eden空間的比值。比如,以下命令把新域設置成64m,Eden佔32m,每個救助域各佔16m:

    java -Xms256m -Xmx256m -Xmn64m -XX:SurvivorRation =2

    如前所述,默認狀態下HotSpot對新域使用複製收集器,對舊域使用標記-清除-壓縮收集器。在新域中使用複製收集器有很多意義,因爲應用程序生成的大部分對象是短壽命的。理想狀態下,所有過渡對象在移出Eden空間時將被收集。如果能夠這樣的話,並且移出Eden空間的對象是長壽命的,那麼理論上可以立即把它們移進舊域,避免在救助空間反覆複製。但是,應用程序不能適合這種理想狀態,因爲它們有一小部分中長壽命的對象。最好是保持這些中長壽命的對象並放在新域中,因爲複製小部分的對象總比壓縮舊域廉價。爲控制新域中對象的複製,可用-XX:TargetSurvivorRatio控制救助空間的比例(該值是設置救助空間的使用比例。如救助空間位1M,該值50表示可用500K)。該值是一個百分比,默認值是50.當較大的堆棧使用較低的 sruvivorratio時,應增加該值到80至90,以更好利用救助空間。用-XX:maxtenuring threshold可控制上限。

爲放置所有的複製全部發生以及希望對象從eden擴展到舊域,可以把MaxTenuring Threshold設置成0.設置完成後,實際上就不再使用救助空間了,因此應把SurvivorRatio設成最大值以最大化Eden空間,設置如下:

    java … -XX:MaxTenuringThreshold=0 –XX:SurvivorRatio=50000 …

    4.BEA JRockit JVM的使用

    Bea WebLogic 8.1使用的新的JVM用於Intel平臺。在Bea安裝完畢的目錄下可以看到有一個類似於jrockit81sp1_141_03的文件夾。這就是 Bea新JVM所在目錄。不同於HotSpot把Java字節碼編譯成本地碼,它預先編譯成類。JRockit還提供了更細緻的功能用以觀察JVM的運行狀態,主要是獨立的GUI控制檯(只能適用於使用Jrockit才能使用jrockit81sp1_141_03自帶的console監控一些cpu及 memory參數)或者WebLogic Server控制檯。

    Bea JRockit JVM支持4種垃圾收集器:

    4.1.1.分代複製收集器

    它與默認的分代收集器工作策略類似。對象在新域中分配,即JRockit文檔中的nursery.這種收集器最適合單cpu機上小型堆操作。

    4.1.2.單空間併發收集器

    該收集器使用完整堆,並與背景線程共同工作。儘管這種收集器可以消除中斷,但是收集器需花費較長的時間尋找死對象,而且處理應用程序時收集器經常運行。如果處理器不能應付應用程序產生的垃圾,它會中斷應用程序並關閉收集。

    分代併發收集器這種收集器在護理域使用排它複製收集器,在舊域中則使用併發收集器。由於它比單空間共同發生收集器中斷頻繁,因此它需要較少的內存,應用程序的運行效率也較高,注意,過小的護理域可以導致大量的臨時對象被擴展到舊域中。這會造成收集器超負荷運作,甚至採用排它性工作方式完成收集。

    4.1.3.並行收集器

    該收集器也停止其他進程的工作,但使用多線程以加速收集進程。儘管它比其他的收集器易於引起長時間的中斷,但一般能更好的利用內存,程序效率也較高。

    默認狀態下,JRockit使用分代併發收集器。要改變收集器,可使用-Xgc:<gc_name>,對應四個收集器分別爲 gencopy,singlecon,gencon以及parallel.可使用-Xms和-Xmx設置堆的初始大小和最大值。要設置護理域,則使用 -Xns:java –jrockit –Xms512m –Xmx512m –Xgc:gencon –Xns128m…儘管JRockit支持-verbose:gc開關,但它輸出的信息會因收集器的不同而異。JRockit還支持memory、 load和codegen的輸出。

    注意 :如果 使用JRockit JVM的話還可以使用WLS自帶的console(C:beajrockit81sp1_141_03bin下)來監控一些數據,如cpu,memery 等。要想能構監控必須在啓動服務時startWeblogic.cmd中加入-Xmanagement參數。

    5.如何從JVM中獲取信息來進行調整

    -verbose.gc開關可顯示gc的操作內容。打開它,可以顯示最忙和最空閒收集行爲發生的時間、收集前後的內存大小、收集需要的時間等。打開 -xx:+ printgcdetails開關,可以詳細瞭解gc中的變化。打開-XX: + PrintGCTimeStamps開關,可以瞭解這些垃圾收集發生的時間,自jvm啓動以後以秒計量。最後,通過-xx: + PrintHeapAtGC開關了解堆的更詳細的信息。爲了瞭解新域的情況,可以通過-XX:=PrintTenuringDistribution開關了解獲得使用期的對象權。

    6.Pdm系統JVM調整

    6.1.服務器:前提內存1G 單CPU

    可通過如下參數進行調整:-server 啓用服務器模式(如果CPU多,服務器機建議使用此項)

    -Xms,-Xmx一般設爲同樣大小。 800m

    -Xmn 是將NewSize與MaxNewSize設爲一致。320m

    -XX:PerSize 64m

    -XX:NewSize 320m 此值設大可調大新對象區,減少Full GC次數

    -XX:MaxNewSize 320m

    -XX:NewRato NewSize設了可不設。4

    -XX: SurvivorRatio 4

    -XX:userParNewGC 可用來設置並行收集

    -XX:ParallelGCThreads 可用來增加並行度 4

    -XXUseParallelGC 設置後可以使用並行清除收集器

    -XX:UseAdaptiveSizePolicy 與上面一個聯合使用效果更好,利用它可以自動優化新域大小以及救助空間比值

    6.2.客戶機:通過在JNLP文件中設置參數來調整客戶端JVM

    JNLP中參數:initial-heap-size和max-heap-size

    這可以在framework的RequestManager中生成JNLP文件時加入上述參數,但是這些值是要求根據客戶機的硬件狀態變化的(如客戶機的內存大小等)。建議這兩個參數值設爲客戶機可用內存的60%(有待測試)。爲了在動態生成JNLP時以上兩個參數值能夠隨客戶機不同而不同,可靠慮獲得客戶機系統信息並將這些嵌到首頁index.jsp中作爲連接請求的參數。

    在設置了上述參數後可以通過Visualgc 來觀察垃圾回收的一些參數狀態,再做相應的調整來改善性能。一般的標準是減少fullgc的次數,最好硬件支持使用並行垃圾回收(要求多CPU)。

 

 

 

 

一、設置JVM內存設置

1. 設置JVM內存的參數有四個:

-Xmx    Java Heap最大值,默認值爲物理內存的1/4,最佳設值應該視物理內存大小及計算機內其他內存開銷而定;

-Xms    Java Heap初始值,Server端JVM最好將-Xms和-Xmx設爲相同值,開發測試機JVM可以保留默認值;

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

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

2. 如何設置JVM內存分配:

(1)當在命令提示符下啓動並使用JVM時(只對當前運行的類Test生效):

java -Xmx128m -Xms64m -Xmn32m -Xss16m Test

(2)當在集成開發環境下(如eclipse)啓動並使用JVM時:

a. 在eclipse根目錄下打開eclipse.ini,默認內容爲(這裏設置的是運行當前開發工具的JVM內存分配):

-vmargs  -Xms40m  -Xmx256m -vmargs表示以下爲虛擬機設置參數,可修改其中的參數值,也可添加-Xmn,-Xss,另外,eclipse.ini內還可以設置非堆內存,如:-XX:PermSize=56m,-XX:MaxPermSize=128m。

此處設置的參數值可以通過以下配置在開發工具的狀態欄顯示:

在eclipse根目錄下創建文件options,文件內容爲:org.eclipse.ui/perf/showHeapStatus=true

修改eclipse根目錄下的eclipse.ini文件,在開頭處添加如下內容:

-debug  options  -vm  javaw.exe 重新啓動eclipse,就可以看到下方狀態條多了JVM信息。

b. 打開eclipse-窗口-首選項-Java-已安裝的JRE(對在當前開發環境中運行的java程序皆生效)

編輯當前使用的JRE,在缺省VM參數中輸入:-Xmx128m -Xms64m -Xmn32m -Xss16m

c. 打開eclipse-運行-運行-Java應用程序(只對所設置的java類生效)

選定需設置內存分配的類-自變量,在VM自變量中輸入:-Xmx128m -Xms64m -Xmn32m -Xss16m

注:如果在同一開發環境中同時進行了b和c設置,則b設置生效,c設置無效,如:

開發環境的設置爲:-Xmx256m,而類Test的設置爲:-Xmx128m -Xms64m,則運行Test時生效的設置爲:

-Xmx256m -Xms64m

(3)當在服務器環境下(如Tomcat)啓動並使用JVM時(對當前服務器環境下所以Java程序生效):

a. 設置環境變量:

變量名:CATALINA_OPTS

變量值:-Xmx128m -Xms64m -Xmn32m -Xss16m

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

二、查看設置JVM內存信息

Runtime.getRuntime().maxMemory();  //最大可用內存,對應-Xmx

Runtime.getRuntime().freeMemory();  //當前JVM空閒內存

Runtime.getRuntime().totalMemory();  //當前JVM佔用的內存總數,其值相當於當前JVM已使用的內存及freeMemory()的總和

關於maxMemory(),freeMemory()和totalMemory():

maxMemory()爲JVM的最大可用內存,可通過-Xmx設置,默認值爲物理內存的1/4,設值不能高於計算機物理內存;

totalMemory()爲當前JVM佔用的內存總數,其值相當於當前JVM已使用的內存及freeMemory()的總和,會隨着JVM使用內存的增加而增加;

freeMemory()爲當前JVM空閒內存,因爲JVM只有在需要內存時才佔用物理內存使用,所以freeMemory()的值一般情況下都很小,而JVM實際可用內存並不等於freeMemory(),而應該等於maxMemory()-totalMemory()+freeMemory()。及其設置JVM內存分配。

在一些規模稍大的應用中,Java虛擬機(JVM)的內存設置尤爲重要,想在項目中取得好的效率,GC(垃圾回收)的設置是第一步。

PermGen space:全稱是Permanent Generation space.就是說是永久保存的區域,用於存放Class和Meta信息,Class在被Load的時候被放入該區域Heap space:存放Instance。

GC(Garbage Collection)應該不會對PermGen space進行清理,所以如果你的APP會LOAD很多CLASS的話,就很可能出現PermGen space錯誤

Java Heap分爲3個區
1.Young
2.Old
3.Permanent

Young保存剛實例化的對象。當該區被填滿時,GC會將對象移到Old區。Permanent區則負責保存反射對象,本文不討論該區。

JVM的Heap分配可以使用-X參數設定,

-Xms
初始Heap大小

-Xmx
java heap最大值 

-Xmn
young generation的heap大小

JVM有2個GC線程
第一個線程負責回收Heap的Young區
第二個線程在Heap不足時,遍歷Heap,將Young 區升級爲Older區

Older區的大小等於-Xmx減去-Xmn,不能將-Xms的值設的過大,因爲第二個線程被迫運行會降低JVM的性能。
爲什麼一些程序頻繁發生GC?

有如下原因:
1.程序內調用了System.gc()或Runtime.gc()。
2.一些中間件軟件調用自己的GC方法,此時需要設置參數禁止這些GC。
3.Java的Heap太小,一般默認的Heap值都很小。
4.頻繁實例化對象,Release對象 此時儘量保存並重用對象,例如使用StringBuffer()和String()。

如果你發現每次GC後,Heap的剩餘空間會是總空間的50%,這表示你的Heap處於健康狀態,許多Server端的Java程序每次GC後最好能有65%的剩餘空間

經驗之談:

1.Server端JVM最好將-Xms和-Xmx設爲相同值。爲了優化GC,最好讓-Xmn值約等於-Xmx的1/3。
2.一個GUI程序最好是每10到20秒間運行一次GC,每次在半秒之內完成。

注意:

1.增加Heap的大小雖然會降低GC的頻率,但也增加了每次GC的時間。並且GC運行時,所有的用戶線程將暫停,也就是GC期間,Java應用程序不做任何工作。
2.Heap大小並不決定進程的內存使用量。進程的內存使用量要大於-Xmx定義的值,因爲Java爲其他任務分配內存,例如每個線程的Stack等。

Stack的設定
每個線程都有他自己的Stack。

-Xss
每個線程的Stack大小

Stack的大小限制着線程的數量。如果Stack過大就好導致內存溢漏。-Xss參數決定Stack大小,例如-Xss1024K。如果Stack太小,也會導致Stack溢漏。

硬件環境

硬件環境也影響GC的效率,例如機器的種類,內存,swap空間,和CPU的數量。
如果你的程序需要頻繁創建很多transient對象,會導致JVM頻繁GC。這種情況你可以增加機器的內存,來減少Swap空間的使用。

4種GC

1、第一種爲單線程GC,也是默認的GC,該GC適用於單CPU機器。
2、第二種爲Throughput GC,是多線程的GC,適用於多CPU,使用大量線程的程序。第二種GC與第一種GC相似,不同在於GC在收集Young區是多線程的,但在Old區和第一種一樣,仍然採用單線程。-XX:+UseParallelGC參數啓動該GC。
3、第三種爲Concurrent Low Pause GC,類似於第一種,適用於多CPU,並要求縮短因GC造成程序停滯的時間。這種GC可以在Old區的回收同時,運行應用程序。-XX:+UseConcMarkSweepGC參數啓動該GC。
4、第四種爲Incremental Low Pause GC,適用於要求縮短因GC造成程序停滯的時間。這種GC可以在Young區回收的同時,回收一部分Old區對象。-Xincgc參數啓動該GC。

單文件的JVM內存進行設置

默認的java虛擬機的大小比較小,在對大數據進行處理時java就會報錯:java.lang.OutOfMemoryError。
設置jvm內存的方法,對於單獨的.class,可以用下面的方法對Test運行時的jvm內存進行設置。
java -Xms64m -Xmx256m Test
-Xms是設置內存初始化的大小
-Xmx是設置最大能夠使用內存的大小(最好不要超過物理內存大小)

tomcat啓動jvm內存設置

Linux:

在/usr/local/apache-tomcat-5.5.23/bin目錄下的catalina.sh添加:JAVA_OPTS='-Xms512m -Xmx1024m'要加“m”說明是MB,否則就是KB了,在啓動tomcat時會報內存不足。
-Xms:初始值
-Xmx:最大值
-Xmn:最小值Windows
在catalina.bat最前面加入
set JAVA_OPTS=-Xms128m -Xmx350m 如果用startup.bat啓動tomcat,OK設置生效.夠成功的分配200M內存.但是如果不是執行startup.bat啓動tomcat而是利用windows的系統服務啓動tomcat服務,上面的設置就不生效了,就是說set JAVA_OPTS=-Xms128m -Xmx350m 沒起作用.上面分配200M內存就OOM了..windows服務執行的是bintomcat.exe.他讀取註冊表中的值,而不是catalina.bat的設置.解決辦法:

修改註冊表HKEY_LOCAL_MACHINESOFTWAREApache Software FoundationTomcat Service ManagerTomcat5ParametersJavaOptions

原值爲

-Dcatalina.home="C:ApacheGroupTomcat 5.0"
-Djava.endorsed.dirs="C:ApacheGroupTomcat 5.0commonendorsed"
-Xrs加入 -Xms300m -Xmx350m

重起tomcat服務,設置生效

weblogic啓動jvm內存設置

在weblogic中,可以在startweblogic.cmd中對每個domain虛擬內存的大小進行設置,默認的設置是在commEnv.cmd裏面。

JBoss

默認可以使用的內存爲64MB
$JBOSSDIR$/bin/run.config
JAVA_OPTS = "-server -Xms128 -Xmx512"

Eclipse

在所在目錄下,鍵入
eclipse.exe -vmargs -Xms256m -Xmx512m
256m表示JVM堆內存最小值
512m表示JVM堆內存最大

Websphere

進入控制檯去設置:應用程序服務器 > server1 > 進程定義 > Java 虛擬機

 

 

 

 

Linux上:
在/usr/tomcat/bin/catalina.sh中加入
export JAVA_OPTS='-Xms[初始化內存大小] -Xmx[可以使用最大內存]'
例如:export JAVA_OPTS='-Xms256m -Xmx512m'
Windows上:
在catalina.bat裏設置初始內存和最大內存:
set CATALINA_OPTS="-Xms30m -Xmx512m"
檢查一下Catalina.bat文件,在每個“%_RUNJAVA%”後面都應該有“�TALINA_OPTS%”
有的Catalina.bat文件在“%_RUNJAVA%”後面跟着“%JAVA_OPTS%”,
如果是這樣,應該設置:
set JAVA_OPTS=-Xms30m -Xmx512m
或者在每個“%_RUNJAVA%”後面加上“�TALINA_OPTS%”

------------------------------------

如何設置Tomcat的JVM虛擬機內存大小

可以給Java虛擬機設置使用的內存,但是如果你的選擇不對的話,虛擬機不會補償。可通過命令行的方式改變虛擬機使用內存的大小。如下表所示有兩個參數用來設置虛擬機使用內存的大小。
參數
描述
-Xms
JVM初始化堆的大小
-Xmx
JVM堆的最大值
這 兩個值的大小一般根據需要進行設置。初始化堆的大小執行了虛擬機在啓動時向系統申請的內存的大小。一般而言,這個參數不重要。但是有的應用程序在大負載的 情況下會急劇地佔用更多的內存,此時這個參數就是顯得非常重要,如果虛擬機啓動時設置使用的內存比較小而在這種情況下有許多對象進行初始化,虛擬機就必須 重複地增加內存來滿足使用。由於這種原因,我們一般把-Xms和-Xmx設爲一樣大,而堆的最大值受限於系統使用的物理內存。一般使用數據量較大的應用程 序會使用持久對象,內存使用有可能迅速地增長。當應用程序需要的內存超出堆的最大值時虛擬機就會提示內存溢出,並且導致應用服務崩潰。因此一般建議堆的最 大值設置爲可用內存的最大值的80%。
Tomcat默認可以使用的內存爲128MB,在較大型的應用項目中,這點內存是不夠的,需要調大。
Windows下,在文件/bin/catalina.bat,Unix下,在文件/bin/catalina.sh的前面,增加如下設置:
JAVA_OPTS='-Xms【初始化內存大小】 -Xmx【可以使用的最大內存】'
需要把這個兩個參數值調大。例如:
JAVA_OPTS='-Xms256m -Xmx512m'
表示初始化內存爲256MB,可以使用的最大內存爲512MB。
另 外需要考慮的是Java提供的垃圾回收機制。虛擬機的堆大小決定了虛擬機花費在收集垃圾上的時間和頻度。收集垃圾可以接受的速度與應用有關,應該通過分析 實際的垃圾收集的時間和頻率來調整。如果堆的大小很大,那麼完全垃圾收集就會很慢,但是頻度會降低。如果你把堆的大小和內存的需要一致,完全收集就很快, 但是會更加頻繁。調整堆大小的的目的是最小化垃圾收集的時間,以在特定的時間內最大化處理客戶的請求。在基準測試的時候,爲保證最好的性能,要把堆的大小 設大,保證垃圾收集不在整個基準測試的過程中出現。
如果系統花費很多的時間收集垃圾,請減小堆大小。一次完全的垃圾收集應該不超過 3-5 秒。如果垃圾收集成爲瓶頸,那麼需要指定代的大小,檢查垃圾收集的詳細輸出,研究 垃圾收集參數對性能的影響。一般說來,你應該使用物理內存的 80% 作爲堆大小。當增加處理器時,記得增加內存,因爲分配可以並行進行,而垃圾收集不是並行的。
Tomcat 5常用優化和配置
1、JDK內存優化:
Tomcat默認可以使用的內存爲128MB,Windows下,在文件{tomcat_home}/bin/catalina.bat,Unix下,在文件{tomcat_home}/bin/catalina.sh的前面,增加如下設置:
JAVA_OPTS='-Xms[初始化內存大小] -Xmx[可以使用的最大內存]
一般說來,你應該使用物理內存的 80% 作爲堆大小。
2、連接器優化:
在tomcat配置文件server.xml中的配置中,和連接數相關的參數有:
maxThreads:
Tomcat使用線程來處理接收的每個請求。這個值表示Tomcat可創建的最大的線程數。默認值150。
acceptCount:
指定當所有可以使用的處理請求的線程數都被使用時,可以放到處理隊列中的請求數,超過這個數的請求將不予處理。默認值10。
minSpareThreads:
Tomcat初始化時創建的線程數。默認值25。
maxSpareThreads:
一旦創建的線程超過這個值,Tomcat就會關閉不再需要的socket線程。默認值75。
enableLookups:
是否反查域名,默認值爲true。爲了提高處理能力,應設置爲false
connnectionTimeout:
網絡連接超時,默認值60000,單位:毫秒。設置爲0表示永不超時,這樣設置有隱患的。通常可設置爲30000毫秒。
maxKeepAliveRequests:
保持請求數量,默認值100。
bufferSize:
輸入流緩衝大小,默認值2048 bytes。
compression:
壓縮傳輸,取值on/off/force,默認值off。
其中和最大連接數相關的參數爲maxThreads和acceptCount。如果要加大併發連接數,應同時加大這兩個參數。web server允許的最大連接數還受制於*作系統的內核參數設置,通常Windows是2000個左右,Linux是1000個左右。
3、tomcat中如何禁止和允許列目錄下的文件
在{tomcat_home}/conf/web.xml中,把listings參數設置成false即可,如下:
<servlet>
...
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
...
</servlet>
4、tomcat中如何禁止和允許主機或IP地址訪問
<Host name="localhost" ...>
...
<Valve className="org.apache.catalina.valves.RemoteHostValve"
allow="*.mycompany.com,www.yourcompany.com"/>
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
deny="192.168.1.*"/>
...
</Host>
服務器的配置
JAVA_OPTS='-server -Xms512m -Xmx768m -XX:NewSize=128m -XX:MaxNewSize=192m -XX:SurvivorRatio=8'

tomcat 的jvm 內存溢出問題的解決


                最近在熟悉一個開發了有幾年的項目,需要把數據庫從mysql移植到oracle,首先把jdbc的連接指向mysql,打包放到tomcat裏面,可以跑起來,沒有問題,可是當把jdbc連接指向oracle的時候,tomcat就連續拋java.lang.OutOfMemoryError的錯誤,上網google了一下,瞭解了一下tomcat的運行機制,也解決了問題,share出來,以備查。
1、首先是:java.lang.OutOfMemoryError: Java heap space
解釋:
Heap size 設置
JVM堆的設置是指java程序運行過程中JVM可以調配使用的內存空間的設置.JVM在啓動的時候會自動設置Heap
size的值,其初始空間(即-Xms)是物理內存的1/64,最大空間(-Xmx)是物理內存的1/4。可以利用JVM提供的-Xmn -Xms
-Xmx等選項可進行設置。Heap size 的大小是Young Generation 和Tenured Generaion 之和。
提示:在JVM中如果98%的時間是用於GC且可用的Heap size 不足2%的時候將拋出此異常信息。
提示:Heap Size 最大不要超過可用物理內存的80%,一般的要將-Xms和-Xmx選項設置爲相同,而-Xmn爲1/4的-Xmx值。
解決方法:
手動設置Heap size
修改TOMCAT_HOME/bin/catalina.bat,在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:
Java代碼
  • set JAVA_OPTS=%JAVA_OPTS% -server -Xms800m -Xmx800m -XX:MaxNewSize=256m   set JAVA_OPTS=%JAVA_OPTS% -server -Xms800m -Xmx800m -XX:MaxNewSize=256m或修改catalina.sh
    在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:
    JAVA_OPTS="$JAVA_OPTS -server -Xms800m -Xmx800m -XX:MaxNewSize=256m"
    2、其次是:java.lang.OutOfMemoryError: PermGen space
    原因:
    PermGen space的全稱是Permanent Generation
    space,是指內存的永久保存區域,這塊內存主要是被JVM存放Class和Meta信息的,Class在被Loader時就會被放到PermGen
    space中,它和存放類實例(Instance)的Heap區域不同,GC(Garbage
    Collection)不會在主程序運行期對PermGen space進行清理,所以如果你的應用中有很CLASS的話,就很可能出現PermGen
    space錯誤,這種錯誤常見在web服務器對JSP進行pre compile的時候。如果你的WEB APP下都用了大量的第三方jar,
    其大小超過了jvm默認的大小(4M)那麼就會產生此錯誤信息了。
    解決方法:
    1. 手動設置MaxPermSize大小
    修改TOMCAT_HOME/bin/catalina.bat(Linux下爲catalina.sh),在Java代碼
  • “echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:   [*]set JAVA_OPTS=%JAVA_OPTS% -server -XX:PermSize=128M -XX:MaxPermSize=512m   “echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:set JAVA_OPTS=%JAVA_OPTS% -server -XX:PermSize=128M -XX:MaxPermSize=512m
    catalina.sh下爲:
    Java代碼
  • JAVA_OPTS="$JAVA_OPTS -server -XX:PermSize=128M -XX:MaxPermSize=512m" JAVA_OPTS="$JAVA_OPTS -server -XX:PermSize=128M -XX:MaxPermSize=512m"另外看到了另外一個帖子,覺得挺好,摘抄如下:
    分析java.lang.OutOfMemoryError: PermGen space
    發現很多人把問題歸因於: spring,hibernate,tomcat,因爲他們動態產生類,導致JVM中的permanent heap溢出 。然後解決方法衆說紛紜,有人說升級 tomcat版本到最新甚至乾脆不用tomcat。還有人懷疑spring的問題,在spring論壇上討論很激烈,因爲spring在AOP時使用CBLIB會動態產生很多類。
    但問題是爲什麼這些王牌的開源會出現同一個問題呢,那麼是不是更基礎的原因呢?tomcat在Q&A很隱晦的回答了這一點,我們知道這個問題,但這個問題是由一個更基礎的問題產生。
    於是有人對更基礎的JVM做了檢查,發現了問題的關鍵。原來SUN
    的JVM把內存分了不同的區,其中一個就是permenter區用來存放用得非常多的類和類描述。本來SUN設計的時候認爲這個區域在JVM啓動的時候就
    固定了,但他沒有想到現在動態會用得這麼廣泛。而且這個區域有特殊的垃圾收回機制,現在的問題是動態加載類到這個區域後,gc根本沒辦法回收!
    對於以上兩個問題,我的處理是:
    在catalina.bat的第一行增加:
    Java代碼
  • set JAVA_OPTS=-Xms64m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m  set JAVA_OPTS=-Xms64m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m在catalina.sh的第一行增加:
    Java代碼
  • JAVA_OPTS=-Xms64m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m 
發佈了20 篇原創文章 · 獲贊 9 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章