JVM
?JVM
的全稱是 「Java Virtual Machine」,也就是咱們耳熟能詳的 Java 虛擬機。它能識別 .class後綴的文件,而且可以解析它的指令,最終調用操做系統上的函數,完成咱們想要的操做。java
C++開發出來的程序,編譯成二進制文件後,就能夠直接執行了,操做系統是可以識別的。算法
可是我們的Java程序就不同了,使用javac
命令編譯出來的的.class文件以後,操做系統是不能識別的,須要對應JVM
去作一個轉換後,操做系統才能識別。數據庫
JDK
、JRE
、JVM
的關係?JDK
是Sun公司(已被Oracle收購)針對Java開發員的軟件開發工具包。自從Java推出以來,JDK
已經成爲使用最普遍的Java SDK
(Software development kit)。緩存
JRE
全稱Java Runtime Environment,是運行基於Java語言編寫的程序所不可缺乏的運行環境。也是經過它,Java的開發者才得以將本身開發的程序發佈到用戶手中,讓用戶使用。tomcat
JVM
就是 Java 虛擬機,它能識別 .class後綴的文件,而且可以解析它的指令,最終調用操做系統上的函數,完成咱們想要的操做。服務器
JDK
中包含JRE
,也包括JDK
,而JRE
也包括JDK
。網絡
範圍關係:JDK
>JRE
>JVM
。數據結構
1.對象獲取。調用person類的父類方法getClaass()
;多線程
2.類名獲取。每一個類型(包括基本類型和引用)都有一個靜態屬性,class;併發
3.Class類的靜態方法獲取。forName("字符串的類名")寫全名,要帶包名。(包名.類名)
Bootstrap ClassLoader
負責加載$JAVA_HOME中 jre/lib/rt.jar
裏全部的class或Xbootclassoath
選項指定的jar包。由C++實現,不是ClassLoader
子類。
Extension ClassLoader
負責加載Java
平臺中擴展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar
或 -Djava.ext.dirs
指定目錄下的jar包。
App ClassLoader
負責加載classpath
中指定的jar包及 Djava.class.path
所指定目錄下的類和jar包。
Custom ClassLoader
經過java.lang.ClassLoader
的子類自定義加載class,屬於應用程序根據自身須要自定義的ClassLoader
,如tomcat
、jboss
都會根據j2ee
規範自行實現ClassLoader
。
用戶根據需求本身定義的。須要繼承自ClassLoader
,重寫方法findClass()
。
若是想要編寫本身的類加載器,只須要兩步:
ClassLoader
類findClass(String className)
方法**ClassLoader**
超類的loadClass
方法用於將類的加載操做委託給其父類加載器去進行,只有當該類還沒有加載而且父類加載器也沒法加載該類時,才調用findClass
方法。若是要實現該方法,必須作到如下幾點:
1.爲來自本地文件系統或者其餘來源的類加載其字節碼。2.調用ClassLoader
超類的defineClass
方法,向虛擬機提供字節碼。
可使用虛擬機參數-Xss 選項來設置線程的最大棧空間,棧的大小直接決定了函數調用的最大可達深度;
-Xss size
若是在棧幀中有一個變量,類型爲引用類型,好比
package com.tian.my_code.test;
public class JvmCodeDemo {
public Object testGC(){
int op1 = 10;
int op2 = 3;
Object obj = new Object();
Object result=obj;
return result;
}
}
這時候就是典型的棧中元素obj指向堆中的Object對象,result的指向和obj的指向爲同一個對象。
使用命令
javac -g:vars JvmCodeDemo.java
進行編譯,而後再使用
javap -v JvmCodeDemo.class >log.txt
而後打開log.txt
文件
方法區中會存放靜態變量,常量等數據。
若是是下面這種狀況,就是典型的方法區中元素指向堆中的對象。【「紅線」】
方法區中會包含類的信息,對象保存再堆中,建立一個對象的前提是有對應的類信息,這個類信息就在方法區中。
一個Java對象在內存中包括3個部分:對象頭、實例數據和對齊填充。
還可能問你:請說一下Minor/Major/Full GC分別發送在哪一個區域。
❝Minor GC:發生在年輕代的 GC Major GC:發生在老年代的 GC。Full GC:新生代+老年代,好比 Metaspace 區引發年輕代和老年代的回收。
❞
1)調用System.gc時,系統建議執行Full GC,可是沒必要然執行;
2)老年代空間不足;
3)方法去空間不足;
4)經過Minor GC後進入老年代的平均大小 > 老年代的可用內存;
5)由Eden區、From Space區向To Space區複製時,對象大小大於To Space可用內存,則把該對象轉存到老年代,且老年代的可用內存小於該對象大小。即老年代沒法存放下新年代過分到老年代的對象的時候,會觸發Full GC。
若是沒有Survivor,Eden區每進行一次Minor GC ,而且沒有年齡限制的話, 存活的對象就會被送到老年代。這樣一來,老年代很快被填滿,觸發Major GC(由於Major GC通常伴隨着Minor GC,也能夠看作觸發了Full GC)。老年代的內存空間遠大於新生代,進行一次Full GC消耗的時間比Minor GC長得多。
執行時間長有什麼壞處?頻發的Full GC消耗的時間很長,會影響大型程序的執行和響應速度。
可能你會說,那就對老年代的空間進行增長或者較少咯。
假如增長老年代空間,更多存活對象才能填滿老年代。雖然下降Full GC頻率,可是隨着老年代空間加大,一旦發生Full GC,執行所須要的時間更長。
假如減小老年代空間,雖然Full GC所需時間減小,可是老年代很快被存活對象填滿,Full GC頻率增長。
因此Survivor的存在乎義,就是減小被送到老年代的對象,進而減小Full GC的發生,Survivor的預篩選保證,只有經歷16 次Minor GC還能在新生代中存活的對象,纔會被送到老年代。
最大的好處就是解決了碎片化。
假設如今只有一個Survivor區,咱們來模擬一下流程:
剛剛新建的對象在Eden中,一旦Eden滿了,觸發一次Minor GC,Eden中的存活對象就會被移動到Survivor區。這樣繼續循 環下去,下一次Eden滿了的時候,問題來了,此時進行Minor GC,Eden和Survivor各有一些存活對象,若是此時把Eden區的 存活對象硬放到Survivor區,很明顯這兩部分對象所佔有的內存是不連續的,也就致使了內存碎片化。
永遠有一個Survivor space是空的,另外一個非空的Survivor space無碎片。
新生代中的可用內存:複製算法用來擔保的內存爲9:1,因此只會形成 10% 的空間浪費。可用內存中Eden:S1
區爲8:1 即新生代中Eden:S1:S2
= 8:1:1
這個比例,是由參數 -XX:SurvivorRatio
進行配置的(默認爲 8)。
給對象添加一個引用計數器,每當一個地方引用它object時技術加1,引用失去之後就減1,計數爲0說明再也不引用
public class A {
public B b;
}
public class B {
public C c;
}
public class C {
public A a;
}
public class Test{
private void test(){
A a = new A();
B b = new B();
C c = new C();
a.b=b;
b.c=c;
c.a=a;
}
}
當一個對象到GC Roots
沒有引用鏈相連,即就是GC Roots
到這個對象不可達時,證實對象不可用。
GC Roots
種類:
❝Java 線程中,當前全部正在被調用的方法的引用類型參數、局部變量、臨時值等。也就是與咱們棧幀相關的各類引用。全部當前被加載的 Java 類。Java 類的引用類型靜態變量。運行時常量池裏的引用類型常量(String 或 Class 類型)。JVM 內部數據結構的一些引用,好比 sun.jvm.hotspot.memory.Universe 類。用於同步的監控對象,好比調用了對象的 wait() 方法。
❞
public class Test{
private void test(C c){
A a = new A();
B b = new B();
a.b=b;
//這裏的a/b/c都是GC Root;
}
}
強引用:User user=new User()
;咱們開發中使用最多的對象引用方式。
特色:咱們日常典型編碼Object obj = new Object()
中的obj就是強引用。
經過關鍵字new建立的對象所關聯的引用就是強引用。
當JVM
內存空間不足,JVM
寧願拋出OutOfMemoryError
運行時錯誤(OOM
),使程序異常終止,也不會靠隨意回收具備強引用的「存活」對象來解決內存不足的問題。
對於一個普通的對象,若是沒有其餘的引用關係,只要超過了引用的做用域或者顯式地將相應(強)引用賦值爲 null,就是能夠被垃圾收集的了,具體回收時機仍是要看垃圾收集策略。
軟引用:SoftReference<Object> object=new SoftReference<Object>(new Object())
;
特色:軟引用經過SoftReference
類實現。軟引用的生命週期比強引用短一些。只有當 JVM 認爲內存不足時,纔會去試圖回收軟引用指向的對象:即JVM 會確保在拋出 OutOfMemoryError 以前,清理軟引用指向的對象。軟引用能夠和一個引用隊列(ReferenceQueue)聯合使用,若是軟引用所引用的對象被垃圾回收器回收,Java虛擬機就會把這個軟引用加入到與之關聯的引用隊列中。後續,咱們能夠調用ReferenceQueue的poll()方法來檢查是否有它所關心的對象被回收。若是隊列爲空,將返回一個null,不然該方法返回隊列中前面的一個Reference對象。
應用場景:軟引用一般用來實現內存敏感的緩存。若是還有空閒內存,就能夠暫時保留緩存,當內存不足時清理掉,這樣就保證了使用緩存的同時,不會耗盡內存
弱引用:WeakReference<Object> object=new WeakReference<Object> (new Object()
;ThreadLocal
中有使用.
弱引用經過WeakReference
類實現。弱引用的生命週期比軟引用短。在垃圾回收器線程掃描它所管轄的內存區域的過程當中,一旦發現了具備弱引用的對象,無論當前內存空間足夠與否,都會回收它的內存。因爲垃圾回收器是一個優先級很低的線程,所以不必定會很快回收弱引用的對象。
弱引用能夠和一個引用隊列(ReferenceQueue
)聯合使用,若是弱引用所引用的對象被垃圾回收,Java虛擬機就會把這個弱引用加入到與之關聯的引用隊列中。應用場景:弱應用一樣可用於內存敏感的緩存。
虛引用:幾乎沒見過使用, ReferenceQueue 、PhantomReference
這個方法就有點相似:某我的被判了死刑,可是不必定會死。
即便在可達性分析算法中不可達的對象,也並不是必定是「非死不可」的,這時候他們暫時處於「緩刑」階段,真正宣告一個對象死亡至少要經歷兩個階段:
一、若是對象在可達性分析算法中不可達,那麼它會被第一次標記並進行一次刷選,刷選的條件是是否須要執行finalize()方法(當對象沒有覆蓋finalize()或者finalize()方法已經執行過了(對象的此方法只會執行一次)),虛擬機將這兩種狀況都會視爲沒有必要執行)。
二、若是這個對象有必要執行finalize()方法會將其放入F-Queue隊列中,稍後GC將對F-Queue隊列進行第二次標記,若是在重寫finalize()方法中將對象本身賦值給某個類變量或者對象的成員變量,那麼第二次標記時候就會將它移出「即將回收」的集合。
第一步:就是找出活躍的對象。咱們反覆強調 GC 過程是逆向的, 根據 GC Roots 遍歷全部的可達對象,這個過程,就叫做標記。
第二部:除了上面標記出來的對象之外,其他的都清楚掉。
新生代使用,新生代分中Eden:S0:S1
= 8:1:1,其中後面的1:1就是用來複制的。
當其中一塊內存使用完了,就將還存活的對象複製到另一塊上面,而後把已經使用過的內存空間一次 清除掉。
通常對象分配都是進入新生代的eden區,若是Minor GC
還存活則進入S0
區,S0
和S1
不斷對象進行復制。對象存活年齡最大默認是15,大對象進來可能由於新生代不存在連續空間,因此會直接接入老年代。任何使用都有新生代的10%是空着的。
它的主要思路,就是移動全部存活的對象,且按照內存地址順序依次排列,而後將末端內存地址之後的內存所有回收。 可是須要注意,這只是一個理想狀態。對象的引用關係通常都是很是複雜的,咱們這裏不對具體的算法進行描述。咱們只須要了解,從效率上來講,通常整理算法是要低於複製算法的。這個算法是規避了內存碎片和內存浪費。
讓全部存活的對象都向一端移動,而後直接清理掉端邊界之外的內存。
從上面的三個算法來看,其實沒有絕對最好的回收算法,只有最適合的算法。
Serial收集器是最基本、發展歷史最悠久的收集器,曾經(在JDK1.3.1以前)是虛擬機新生代收集的惟一選擇。
它是一種單線程收集器,不只僅意味着它只會使用一個CPU或者一條收集線程去完成垃圾收集工做,更重要的是其在進行垃圾收集的時候須要暫停其餘線程。
❝優勢:簡單高效,擁有很高的單線程收集效率 缺點:收集過程須要暫停全部線程 算法:複製算法 應用:Client模式下的默認新生代收集器
❞
收集過程:
能夠把這個收集器理解爲Serial收集器的多線程版本。
❝優勢:在多CPU時,比Serial效率高。缺點:收集過程暫停全部應用程序線程,單CPU時比Serial效率差。算法:複製算法 應用:運行在Server模式下的虛擬機中首選的新生代收集器
❞
收集過程:
Parallel Scavenge收集器是一個新生代收集器,它也是使用複製算法的收集器,又是並行的多線程收集 器,看上去和ParNew
同樣,可是Parallel Scanvenge
更關注 系統的吞吐量 ;
❝吞吐量 = 運行用戶代碼的時間 / (運行用戶代碼的時間 + 垃圾收集時間)
好比虛擬機總共運行了120秒,垃圾收集時間用了1秒,吞吐量=(120-1)/120=99.167%。
若吞吐量越大,意味着垃圾收集的時間越短,則用戶代碼能夠充分利用CPU資源,儘快完成程序的運算任務。
❞
可設置參數:
-XX:MaxGCPauseMillis控制最大的垃圾收集停頓時間,
-XX:GC Time Ratio直接設置吞吐量的大小。
「特色」:最短回收停頓時間,
「回收算法」:標記-清除
「回收步驟」:
GC Roots
直接關聯的對象,速度快GC Roots Tracing
過程,耗時長,與用戶進程併發工做「缺點」:對CPU資源很是敏感,CPU少於4個時,CMS歲用戶程序的影響可能變得很大,有此虛擬機提供了「增量式併發收集器」;沒法回收浮動垃圾;採用標記清除算法會產生內存碎片,不過能夠經過參數開啓內存碎片的合併整理。
收集過程:
Serial Old收集器是Serial收集器的老年代版本,也是一個單線程收集器,不一樣的是採用"標記-整理算 法",運行過程和Serial收集器同樣。
「適用場景」:JDK1.5
前與Parallel Scanvenge
配合使用,做爲CMS
的後備預案;
收集過程:
Parallel Old收集器是Parallel Scavenge收集器的老年代版本,使用多線程和"標記-整理算法"進行垃圾 回收,吞吐量優先;
「回收算法」:標記-整理
「適用場景」:爲了替代serial old
與Parallel Scanvenge
配合使用
收集過程:
從 JDK
9 開始,JVM
的默認垃圾回收器就從 Parallel GC
調整爲 G1
,而且開始全面廢除 CMS
。
限制或者減小 GC 停頓時間相比系統吞吐量而言更加劇要,從 PGC 切換至低延遲的 G1 可以爲大部分用戶帶來更好的體驗。G1 的性能在 JDK 8 以及後續的 release 版本都獲得了極大的優化,G1 是一個具有全部 GC 特性的垃圾回收器,所以將 G1 設置爲 JVM 默認的 GC。
根據 JEP-291 中的說明,爲了減輕 GC 代碼的維護負擔以及加速新功能開發,決定在 JDK 9 中廢棄 CMS GC。
從 Java 9 開始,若是您使用 -XX:+UseConcMarkSweepGC
(激活 CMS GC 算法的參數)參數啓動應用程序,則會在下面顯示警告消息:
Java HotSpot(TM) 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release.
若是你想知道當前應用對應的 JVM 版本,你可使用如下命令進行查詢:
G1將整個JVM
堆劃分紅多個大小相等的獨立區域regin
,跟蹤各個regin
裏面的垃圾堆積的價值大小,在後臺維護一個優先列表,每次根據容許的收集時間,有線回收最大的regin
,芮然還保留有新生代和老年代的概念,但新生代和老年代不在是物理隔離了,他們都是一部分regin
集合。
內存「化整爲零」的思路:在GC
根節點的枚舉範圍彙總加入remembered set 便可保證不對全堆掃面也不會遺漏。
「回收步驟」:
GC Roots
直接關聯的對象regin
的回收價值進行排序,而後根據指望的GC
停頓時間制定回收計劃G1
收集器優點
「並行與併發」:G1
能充分利用多CPU、多核環境下的硬件優點,使用多個CPU來縮短Stop-The-World停頓時間。部分收集器本來須要停頓Java線程來執行GC
動做,G1
收集器仍然能夠經過併發的方式讓Java程序繼續運行。
「分代收集」:G1
可以獨自管理整個Java堆,而且採用不一樣的方式去處理新建立的對象和已經存活了一段時間、熬過屢次GC
的舊對象以獲取更好的收集效果。
「空間整合」:G1
運做期間不會產生空間碎片,收集後能提供規整的可用內存。
「可預測的停頓」:G1
除了追求低停頓外,還能創建可預測的停頓時間模型。能讓使用者明確指定在一個長度爲M毫秒的時間段內,消耗在垃圾收集上的時間不得超過N毫秒。
收集過程:
G1
的回收過程主要分爲 3 類:
(1)G1
「年輕代」的垃圾回收,一樣叫 Minor G1
,這個過程和咱們前面描述的相似,發生時機就是 Eden 區滿的時候。
(2)老年代的垃圾收集,嚴格上來講其實不算是收集,它是一個「併發標記」的過程,順便清理了一點點對象。
(3)真正的清理,發生在「混合模式」,它不止清理年輕代,還會將老年代的一部分區域進行清理。
ZGC
ZGC
(Z Garbage Collector)是一款由Oracle公司研發的,以低延遲爲首要目標的一款垃圾收集器。它是基於「動態Region」內存佈局,(暫時)「不設年齡分代」,使用了「讀屏障」、「染色指針」和「內存多重映射」等技術來實現「可併發的標記-整理算法」的收集器。
在JDK 11
新加入,還在實驗階段,主要特色是:「回收TB級內存(最大4T),停頓時間不超過10ms
」。
「優勢」:低停頓,高吞吐量,ZGC
收集過程當中額外耗費的內存小
「缺點」:浮動垃圾
目前使用的很是少,真正普及仍是須要寫時間的。
「新生代收集器」:Serial、ParNew
、Parallel Scavenge
「老年代收集器」:CMS
、Serial Old、Parallel Old
「整堆收集器」:G1
,ZGC
(由於不涉年代不在圖中)
選擇建議:
若是你的堆大小不是很大(好比 100MB
),選擇串行收集器通常是效率最高的。
參數:-XX:+UseSerialGC
。
若是你的應用運行在單核的機器上,或者你的虛擬機核數只有 單核,選擇串行收集器依然是合適的,這時候啓用一些並行收集器沒有任何收益。
參數:-XX:+UseSerialGC
。
若是你的應用是「吞吐量」優先的,而且對較長時間的停頓沒有什麼特別的要求。選擇並行收集器是比較好的。
參數:-XX:+UseParallelGC
。
若是你的應用對響應時間要求較高,想要較少的停頓。甚至 1 秒的停頓都會引發大量的請求失敗,那麼選擇G1
、ZGC
、CMS
都是合理的。雖然這些收集器的 GC 停頓一般都比較短,但它須要一些額外的資源去處理這些工做,一般吞吐量會低一些。
參數:-XX:+UseConcMarkSweepGC
、-XX:+UseG1GC
、-XX:+UseZGC
等。
從上面這些出發點來看,咱們日常的 Web 服務器,都是對響應性要求很是高的。選擇性其實就集中在 CMS
、G1
、ZGC
上。而對於某些定時任務,使用並行收集器,是一個比較好的選擇。
X或者XX開頭的都是非轉標準化參數
意思就是說準表化參數不會變,非標準化參數可能在每一個JDK
版本中有所變化,可是就目前來看X開頭的非標準化的參數改變的也是很是少。
格式:-XX:[+-]<name> 表示啓用或者禁用name屬性。
例子:-XX:+UseG1GC(表示啓用G1垃圾收集器)
-Xms
初始堆大小,ms是memory start的簡稱 ,等價於-XX:InitialHeapSize
-Xmx
最大堆大小,mx是memory max的簡稱 ,等價於參數-XX:MaxHeapSize
❝注意:在一般狀況下,服務器項目在運行過程當中,堆空間會不斷的收縮與擴張,勢必會形成沒必要要的系統壓力。因此在生產環境中,
❞JVM
的Xms
和Xmx
要設置成同樣的,可以避免GC
在調整堆大小帶來的沒必要要的壓力。
-XX:NewSize=n
設置年輕代大小-XX:NewRatio=n
設置年輕代和年老代的比值。如:-XX:NewRatio=3
,表示年輕代與年老代比值爲1:3,年輕代佔整個年輕代年老代和的1/4,默認新生代和老年代的比例=1:2。-XX:SurvivorRatio=n
年輕代中Eden區與兩個Survivor區的比值。注意Survivor區有兩個,默認是8,表示
Eden:S0:S1=8:1:1
如:-XX:SurvivorRatio=3
,表示Eden:Survivor
=3:2,一個Survivor區佔整個年輕代的1/5。
-XX:MaxPermSize=n
設置持久代大小
-XX:MetaspaceSize
設置元空間大小
-XX:+UseSerialGC
設置串行收集器-XX:+UseParallelGC
設置並行收集器-XX:+UseParalledlOldGC
設置並行年老代收集器-XX:+UseConcMarkSweepGC
設置併發收集器
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-Xloggc:filename
GC日誌輸出到文件裏filename
,好比:-Xloggc:/gc.log
-XX:ParallelGCThreads=n
設置並行收集器收集時使用的CPU數。並行收集線程數。
-XX:MaxGCPauseMillis=n
設置並行收集最大暫停時間
-XX:GCTimeRatio=n
設置垃圾回收時間佔程序運行時間的百分比。公式爲1/(1+n)
-XX:MaxGCPauseMillis=n
設置並行收集最大暫停時間
-XX:+CMSIncrementalMode
設置爲增量模式。適用於單CPU狀況。-XX:ParallelGCThreads=n
設置併發收集器年輕代收集方式爲並行收集時,使用的CPU數。並行收集線程數。
-XX:+PrintCommandLineFlags
查看當前JVM
設置過的相關參數
Dump
異常快照-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath
堆內存出現OOM
的機率是全部內存耗盡異常中最高的,出錯時的堆內信息對解決問題很是有幫助,因此給JVM
設置這個參數(-XX:+HeapDumpOnOutOfMemoryError
),讓JVM
遇到OOM
異常時能輸出堆內信息,並經過(-XX:+HeapDumpPath
)參數設置堆內存溢出快照輸出的文件地址,這對於特別是對相隔數月纔出現的OOM
異常尤其重要。
-Xms10M -Xmx10M -Xmn2M -XX:SurvivorRatio=8 -XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=D:\study\log_hprof\gc.hprof
-XX:OnOutOfMemoryError
表示發生OOM後
,運行jconsole.exe
程序。這裏能夠不用加「」,由於jconsole.exe
路徑Program Files含有空格。利用這個參數,咱們能夠在系統OOM
後,自定義一個腳本,能夠用來發送郵件告警信息,能夠用來重啓系統等等。
-XX:OnOutOfMemoryError="C:\Program Files\Java\jdk1.8.0_151\bin\jconsole.exe"
8G
內存的服務器該如何設置?java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4 -XX:MaxPermSize=16m -XX:MaxTenuringThreshold=0
-Xmx3500m
設置JVM
最大可用內存爲3550M。
-Xms3500m
設置JVM
促使內存爲3550m
。此值能夠設置與-Xmx
相同,以免每次垃圾回收完成後JVM從新分配內存。-Xmn2g
設置年輕代大小爲2G
。
❝整個堆大小=年輕代大小 + 年老代大小 + 方法區大小
❞
-Xss128k
設置每一個線程的堆棧大小。JDK1.5
之後每一個線程堆棧大小爲1M,之前每一個線程堆棧大小爲256K。更具應用的線程所需內存大小進行調整。在相同物理內存下,減少這個值能生成更多的線程。可是操做系統對一個進程內的線程數仍是有限制的,不能無限生成,經驗值在3000~5000左右。
-XX:NewRatio=4
設置年輕代(包括Eden和兩個Survivor區)與年老代的比值(除去持久代)。設置爲4,則年輕代與年老代所佔比值爲1:4,年輕代佔整個堆棧的1/5 。
-XX:SurvivorRatio=4
設置年輕代中Eden區與Survivor區的大小比值。設置爲4,則兩個Survivor區與一個Eden區的比值爲2:4,一個Survivor區佔整個年輕代的1/6 -XX:MaxPermSize=16m
設置持久代大小爲16m。
-XX:MaxTenuringThreshold=0
設置垃圾最大年齡。若是設置爲0的話,則年輕代對象不通過Survivor區,直接進入年老代。對於年老代比較多的應用,能夠提升效率。若是將此值設置爲一個較大值,則年輕代對象會在Survivor區進行屢次複製,這樣能夠增長對象再年輕代的存活時間,增長在年輕代即被回收的概論。