搞定這24道JVM面試題,要價30k都有底氣~


1.什麼是JVM?

JVM 的全稱是 「Java Virtual Machine」,也就是咱們耳熟能詳的 Java 虛擬機。它能識別 .class後綴的文件,而且可以解析它的指令,最終調用操做系統上的函數,完成咱們想要的操做。java

C++開發出來的程序,編譯成二進制文件後,就能夠直接執行了,操做系統是可以識別的。算法

可是我們的Java程序就不同了,使用javac命令編譯出來的的.class文件以後,操做系統是不能識別的,須要對應JVM去作一個轉換後,操做系統才能識別。數據庫

2.說說JDKJREJVM的關係?

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數據結構

圖片

3.獲取class文件有哪些方式?

  1. 從本地文件系統中加載.class文件
  2. 從jar包中或者war包中加載.class文件
  3. 經過網絡或者從數據庫中加載.class文件
  4. 把一個Java源文件動態編譯,並加載,加載進來後就,系統爲這個.class文件生成一個對應的Class對象。

4.生成Class對象的有哪些方式?

1.對象獲取。調用person類的父類方法getClaass();多線程

2.類名獲取。每一個類型(包括基本類型和引用)都有一個靜態屬性,class;併發

3.Class類的靜態方法獲取。forName("字符串的類名")寫全名,要帶包名。(包名.類名)

5.類加載器有哪些?

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,如tomcatjboss都會根據j2ee規範自行實現ClassLoader

6.如何自定義類加載器?

用戶根據需求本身定義的。須要繼承自ClassLoader,重寫方法findClass()

若是想要編寫本身的類加載器,只須要兩步:

  • 繼承ClassLoader
  • 覆蓋findClass(String className)方法

**ClassLoader**超類的loadClass方法用於將類的加載操做委託給其父類加載器去進行,只有當該類還沒有加載而且父類加載器也沒法加載該類時,才調用findClass方法。若是要實現該方法,必須作到如下幾點:

1.爲來自本地文件系統或者其餘來源的類加載其字節碼。2.調用ClassLoader超類的defineClass方法,向虛擬機提供字節碼。

7.如何設置Java虛擬機棧的大小呢?

可使用虛擬機參數-Xss 選項來設置線程的最大棧空間,棧的大小直接決定了函數調用的最大可達深度;

-Xss size

8.方法區、堆、棧之間到底有什麼關係?

圖片

棧指向堆

若是在棧幀中有一個變量,類型爲引用類型,好比

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文件

方法區指向堆

方法區中會存放靜態變量,常量等數據。

若是是下面這種狀況,就是典型的方法區中元素指向堆中的對象。【「紅線」

圖片

堆指向方法區

方法區中會包含類的信息,對象保存再堆中,建立一個對象的前提是有對應的類信息,這個類信息就在方法區中。

圖片

9.Java對象內存是如何佈局的?

圖片

一個Java對象在內存中包括3個部分:對象頭、實例數據和對齊填充。

圖片

10.如何理解Minor/Major/Full GC?

還可能問你:請說一下Minor/Major/Full GC分別發送在哪一個區域。

Minor GC:發生在年輕代的 GC Major GC:發生在老年代的 GC。Full GC:新生代+老年代,好比 Metaspace 區引發年輕代和老年代的回收。

11.可以觸發條件 Full GC 有哪些?

1)調用System.gc時,系統建議執行Full GC,可是沒必要然執行;

2)老年代空間不足;

3)方法去空間不足;

4)經過Minor GC後進入老年代的平均大小 > 老年代的可用內存;

5)由Eden區、From Space區向To Space區複製時,對象大小大於To Space可用內存,則把該對象轉存到老年代,且老年代的可用內存小於該對象大小。即老年代沒法存放下新年代過分到老年代的對象的時候,會觸發Full GC。

12.爲何須要Survivor區?

若是沒有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還能在新生代中存活的對象,纔會被送到老年代。

13.爲何須要兩個大小同樣的Survivor區?

最大的好處就是解決了碎片化。

假設如今只有一個Survivor區,咱們來模擬一下流程:

剛剛新建的對象在Eden中,一旦Eden滿了,觸發一次Minor GC,Eden中的存活對象就會被移動到Survivor區。這樣繼續循 環下去,下一次Eden滿了的時候,問題來了,此時進行Minor GC,Eden和Survivor各有一些存活對象,若是此時把Eden區的 存活對象硬放到Survivor區,很明顯這兩部分對象所佔有的內存是不連續的,也就致使了內存碎片化。

永遠有一個Survivor space是空的,另外一個非空的Survivor space無碎片。

14.新生代中Eden:S1:S2爲何是8:1:1?

新生代中的可用內存:複製算法用來擔保的內存爲9:1,因此只會形成 10% 的空間浪費。可用內存中Eden:S1區爲8:1 即新生代中Eden:S1:S2 = 8:1:1

這個比例,是由參數 -XX:SurvivorRatio 進行配置的(默認爲 8)。

15.如何判斷對象已死?

引用計數法

給對象添加一個引用計數器,每當一個地方引用它object時技術加1,引用失去之後就減1,計數爲0說明再也不引用

  • 優勢:實現簡單,斷定效率高
  • 缺點:沒法解決對象相互循環引用的問題,對象A中引用了對象B,對象B中引用對象A。

圖片

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;
    }
}

16.對象的有幾種引用類型?

  • 強引用: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

17.finalize方法有了解嗎?

這個方法就有點相似:某我的被判了死刑,可是不必定會死。

即便在可達性分析算法中不可達的對象,也並不是必定是「非死不可」的,這時候他們暫時處於「緩刑」階段,真正宣告一個對象死亡至少要經歷兩個階段:

一、若是對象在可達性分析算法中不可達,那麼它會被第一次標記並進行一次刷選,刷選的條件是是否須要執行finalize()方法(當對象沒有覆蓋finalize()或者finalize()方法已經執行過了(對象的此方法只會執行一次)),虛擬機將這兩種狀況都會視爲沒有必要執行)。

二、若是這個對象有必要執行finalize()方法會將其放入F-Queue隊列中,稍後GC將對F-Queue隊列進行第二次標記,若是在重寫finalize()方法中將對象本身賦值給某個類變量或者對象的成員變量,那麼第二次標記時候就會將它移出「即將回收」的集合。

18.垃圾回收算法有哪些?

標記-清除算法

第一步:就是找出活躍的對象。咱們反覆強調 GC 過程是逆向的, 根據 GC Roots 遍歷全部的可達對象,這個過程,就叫做標記。

第二部:除了上面標記出來的對象之外,其他的都清楚掉。

  • 缺點:標記和清除效率不高,標記和清除以後會產生大量不連續的內存碎片

圖片

複製算法

新生代使用,新生代分中Eden:S0:S1= 8:1:1,其中後面的1:1就是用來複制的。

當其中一塊內存使用完了,就將還存活的對象複製到另一塊上面,而後把已經使用過的內存空間一次 清除掉。

通常對象分配都是進入新生代的eden區,若是Minor GC還存活則進入S0區,S0S1不斷對象進行復制。對象存活年齡最大默認是15,大對象進來可能由於新生代不存在連續空間,因此會直接接入老年代。任何使用都有新生代的10%是空着的。

  • 缺點:對象存活率高時,複製效率會較低,浪費內存。

標記整理算法

它的主要思路,就是移動全部存活的對象,且按照內存地址順序依次排列,而後將末端內存地址之後的內存所有回收。 可是須要注意,這只是一個理想狀態。對象的引用關係通常都是很是複雜的,咱們這裏不對具體的算法進行描述。咱們只須要了解,從效率上來講,通常整理算法是要低於複製算法的。這個算法是規避了內存碎片和內存浪費。

讓全部存活的對象都向一端移動,而後直接清理掉端邊界之外的內存。

從上面的三個算法來看,其實沒有絕對最好的回收算法,只有最適合的算法。

19.新生代有哪些垃圾收集器?

serial

Serial收集器是最基本、發展歷史最悠久的收集器,曾經(在JDK1.3.1以前)是虛擬機新生代收集的惟一選擇。

它是一種單線程收集器,不只僅意味着它只會使用一個CPU或者一條收集線程去完成垃圾收集工做,更重要的是其在進行垃圾收集的時候須要暫停其餘線程。

優勢:簡單高效,擁有很高的單線程收集效率 缺點:收集過程須要暫停全部線程 算法:複製算法 應用:Client模式下的默認新生代收集器

收集過程:

ParNew

能夠把這個收集器理解爲Serial收集器的多線程版本。

優勢:在多CPU時,比Serial效率高。缺點:收集過程暫停全部應用程序線程,單CPU時比Serial效率差。算法:複製算法 應用:運行在Server模式下的虛擬機中首選的新生代收集器

收集過程:

Parallel Scanvenge

Parallel Scavenge收集器是一個新生代收集器,它也是使用複製算法的收集器,又是並行的多線程收集 器,看上去和ParNew同樣,可是Parallel Scanvenge更關注 系統的吞吐量 ;

吞吐量 = 運行用戶代碼的時間 / (運行用戶代碼的時間 + 垃圾收集時間)

好比虛擬機總共運行了120秒,垃圾收集時間用了1秒,吞吐量=(120-1)/120=99.167%。

若吞吐量越大,意味着垃圾收集的時間越短,則用戶代碼能夠充分利用CPU資源,儘快完成程序的運算任務。

可設置參數:

-XX:MaxGCPauseMillis控制最大的垃圾收集停頓時間,
-XX:GC Time Ratio直接設置吞吐量的大小。

20.老年代有哪些垃圾收集器?

CMS=Concurrent Mark Sweep

「特色」:最短回收停頓時間,

「回收算法」:標記-清除

「回收步驟」

  1. 初始標記:標記GC Roots直接關聯的對象,速度快
  2. 併發標記:GC Roots Tracing過程,耗時長,與用戶進程併發工做
  3. 從新標記:修正併發標記期間用戶進程運行而產生變化的標記,好事比初始標記長,可是遠遠小於併發標記
  4. 表發清除:清除標記的對象

「缺點」:對CPU資源很是敏感,CPU少於4個時,CMS歲用戶程序的影響可能變得很大,有此虛擬機提供了「增量式併發收集器」;沒法回收浮動垃圾;採用標記清除算法會產生內存碎片,不過能夠經過參數開啓內存碎片的合併整理。

圖片

收集過程:

圖片

serial old

Serial Old收集器是Serial收集器的老年代版本,也是一個單線程收集器,不一樣的是採用"標記-整理算 法",運行過程和Serial收集器同樣。

「適用場景」JDK1.5前與Parallel Scanvenge配合使用,做爲CMS的後備預案;

圖片

收集過程:

Parallel old

Parallel Old收集器是Parallel Scavenge收集器的老年代版本,使用多線程和"標記-整理算法"進行垃圾 回收,吞吐量優先;

「回收算法」:標記-整理

「適用場景」:爲了替代serial oldParallel Scanvenge配合使用

收集過程:

G1=Garbage first

從 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 便可保證不對全堆掃面也不會遺漏。

「回收步驟」

  1. 初始標記:標記GC Roots直接關聯的對象
  2. 併發標記:對堆中對象進行可達性分析,找出存活對象,耗時長,與用戶進程併發工做
  3. 最終標記:修正併發標記期間用戶進程繼續運行而產生變化的標記
  4. 篩選回收:對各個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收集過程當中額外耗費的內存小

「缺點」:浮動垃圾

目前使用的很是少,真正普及仍是須要寫時間的。

21.垃圾收集器之間有什麼關係?

「新生代收集器」:Serial、ParNewParallel Scavenge

「老年代收集器」CMS、Serial Old、Parallel Old

「整堆收集器」G1ZGC(由於不涉年代不在圖中)

22.如何選擇垃圾收集器?

圖片

選擇建議:

  1. 若是你的堆大小不是很大(好比 100MB),選擇串行收集器通常是效率最高的。

    參數:-XX:+UseSerialGC

  2. 若是你的應用運行在單核的機器上,或者你的虛擬機核數只有 單核,選擇串行收集器依然是合適的,這時候啓用一些並行收集器沒有任何收益。

    參數:-XX:+UseSerialGC

  3. 若是你的應用是「吞吐量」優先的,而且對較長時間的停頓沒有什麼特別的要求。選擇並行收集器是比較好的。

    參數:-XX:+UseParallelGC

  4. 若是你的應用對響應時間要求較高,想要較少的停頓。甚至 1 秒的停頓都會引發大量的請求失敗,那麼選擇G1ZGCCMS都是合理的。雖然這些收集器的 GC 停頓一般都比較短,但它須要一些額外的資源去處理這些工做,一般吞吐量會低一些。

    參數:-XX:+UseConcMarkSweepGC-XX:+UseG1GC-XX:+UseZGC 等。

從上面這些出發點來看,咱們日常的 Web 服務器,都是對響應性要求很是高的。選擇性其實就集中在 CMSG1ZGC上。而對於某些定時任務,使用並行收集器,是一個比較好的選擇。

23.熟悉哪些JVM調優參數?

X或者XX開頭的都是非轉標準化參數

意思就是說準表化參數不會變,非標準化參數可能在每一個JDK版本中有所變化,可是就目前來看X開頭的非標準化的參數改變的也是很是少。

格式:-XX:[+-]<name> 表示啓用或者禁用name屬性。
例子:-XX:+UseG1GC(表示啓用G1垃圾收集器)

堆設置

-Xms 初始堆大小,ms是memory start的簡稱 ,等價於-XX:InitialHeapSize-Xmx 最大堆大小,mx是memory max的簡稱 ,等價於參數-XX:MaxHeapSize

注意:在一般狀況下,服務器項目在運行過程當中,堆空間會不斷的收縮與擴張,勢必會形成沒必要要的系統壓力。因此在生產環境中,JVMXmsXmx要設置成同樣的,可以避免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:filenameGC日誌輸出到文件裏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"

24.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區進行屢次複製,這樣能夠增長對象再年輕代的存活時間,增長在年輕代即被回收的概論。

相關文章
相關標籤/搜索