精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

大白話帶你認識JVM

開發 前端
JVM 是 Java Virtual Machine 的縮寫,它是一個虛構出來的計算機,一種規范。通過在實際的計算機上仿真模擬各類計算機功能實現···

 如果在文中用詞或者理解方面出現問題,歡迎指出。此文旨在提及和而不深究,但會盡量效率地把知識點都拋出來

一、JVM的基本介紹

JVM 是 Java Virtual Machine 的縮寫,它是一個虛構出來的計算機,一種規范。通過在實際的計算機上仿真模擬各類計算機功能實現···

好,其實拋開這么專業的句子不說,就知道JVM其實就類似于一臺小電腦運行在windows或者linux這些操作系統環境下即可。它直接和操作系統進行交互,與硬件不直接交互,可操作系統可以幫我們完成和硬件進行交互的工作。 

 

 1.1 Java文件是如何被運行的

比如我們現在寫了一個 HelloWorld.java 好了,那這個 HelloWorld.java 拋開所有東西不談,那是不是就類似于一個文本文件,只是這個文本文件它寫的都是英文,而且有一定的縮進而已。

那我們的 JVM 是不認識文本文件的,所以它需要一個 編譯 ,讓其成為一個它會讀二進制文件的HelloWorld.class

① 類加載器

如果 JVM 想要執行這個 .class 文件,我們需要將其裝進一個 類加載器 中,它就像一個搬運工一樣,會把所有的 .class 文件全部搬進JVM里面來。

  

 ② 方法區

方法區 是用于存放類似于元數據信息方面的數據的,比如類信息,常量,靜態變量,編譯后代碼···等

類加載器將 .class 文件搬過來就是先丟到這一塊上

③ 堆

堆 主要放了一些存儲的數據,比如對象實例,數組···等,它和方法區都同屬于 線程共享區域 。也就是說它們都是 線程不安全 的

④ 棧

棧 這是我們的代碼運行空間。我們編寫的每一個方法都會放到 棧 里面運行。

我們會聽說過 本地方法棧 或者 本地方法接口 這兩個名詞,不過我們基本不會涉及這兩塊的內容,它倆底層是使用C來進行工作的,和Java沒有太大的關系。

⑤ 程序計數器

主要就是完成一個加載工作,類似于一個指針一樣的,指向下一行我們需要執行的代碼。和棧一樣,都是 線程獨享 的,就是說每一個線程都會有自己對應的一塊區域而不會存在并發和多線程的問題。

   

 小總結

Java文件經過編譯后變成 .class 字節碼文件

字節碼文件通過類加載器被搬運到 JVM 虛擬機中

虛擬機主要的5大塊:方法區,堆都為線程共享區域,有線程安全問題,棧和本地方法棧和計數器都是獨享區域,不存在線程安全問題,而 JVM 的調優主要就是圍繞堆,棧兩大塊進行

1.2 簡單的代碼例子

一個簡單的學生類

 一個main方法

 

 

執行main方法的步驟如下:

編譯好 App.java 后得到 App.class 后,執行 App.class,系統會啟動一個 JVM 進程,從 classpath 路徑中找到一個名為 App.class 的二進制文件,將 App 的類信息加載到運行時數據區的方法區內,這個過程叫做 App 類的加載

JVM 找到 App 的主程序入口,執行main方法

這個main中的第一條語句為 Student student = new Student("tellUrDream") ,就是讓 JVM 創建一個Student對象,但是這個時候方法區中是沒有 Student 類的信息的,所以 JVM 馬上加載 Student 類,把 Student 類的信息放到方法區中

加載完 Student 類后,JVM 在堆中為一個新的 Student 實例分配內存,然后調用構造函數初始化 Student 實例,這個 Student 實例持有 指向方法區中的 Student 類的類型信息 的引用

執行student.sayName();時,JVM 根據 student 的引用找到 student 對象,然后根據 student 對象持有的引用定位到方法區中 student 類的類型信息的方法表,獲得 sayName() 的字節碼地址。

執行sayName()

其實也不用管太多,只需要知道對象實例初始化時會去方法區中找類信息,完成后再到棧那里去運行方法。找方法就在方法表中找。

二、類加載器的介紹

之前也提到了它是負責加載.class文件的,它們在文件開頭會有特定的文件標示,將class文件字節碼內容加載到內存中,并將這些內容轉換成方法區中的運行時數據結構,并且ClassLoader只負責class文件的加載,而是否能夠運行則由 Execution Engine 來決定

2.1 類加載器的流程

從類被加載到虛擬機內存中開始,到釋放內存總共有7個步驟:加載,驗證,準備,解析,初始化,使用,卸載。其中驗證,準備,解析三個部分統稱為連接

2.1.1 加載

將class文件加載到內存

將靜態數據結構轉化成方法區中運行時的數據結構

在堆中生成一個代表這個類的 java.lang.Class對象作為數據訪問的入口

2.1.2 鏈接

  • 驗證:確保加載的類符合 JVM 規范和安全,保證被校驗類的方法在運行時不會做出危害虛擬機的事件,其實就是一個安全檢查
  • 準備:為static變量在方法區中分配內存空間,設置變量的初始值,例如 static int a = 3 (注意:準備階段只設置類中的靜態變量(方法區中),不包括實例變量(堆內存中),實例變量是對象初始化時賦值的)
  • 解析:虛擬機將常量池內的符號引用替換為直接引用的過程(符號引用比如我現在import java.util.ArrayList這就算符號引用,直接引用就是指針或者對象地址,注意引用對象一定是在內存進行)

2.1.3 初始化

初始化其實就是一個賦值的操作,它會執行一個類構造器的()方法。由編譯器自動收集類中所有變量的賦值動作,此時準備階段時的那個 static int a = 3 的例子,在這個時候就正式賦值為3

2.1.4 卸載

GC將無用對象從內存中卸載

2.2 類加載器的加載順序

加載一個Class類的順序也是有優先級的,類加載器從最底層開始往上的順序是這樣的

  1. BootStrap ClassLoader:rt.jar
  2. Extention ClassLoader: 加載擴展的jar包
  3. App ClassLoader:指定的classpath下面的jar包
  4. Custom ClassLoader:自定義的類加載器

2.3 雙親委派機制

當一個類收到了加載請求時,它是不會先自己去嘗試加載的,而是委派給父類去完成,比如我現在要new一個Person,這個Person是我們自定義的類,如果我們要加載它,就會先委派App ClassLoader,只有當父類加載器都反饋自己無法完成這個請求(也就是父類加載器都沒有找到加載所需的Class)時,子類加載器才會自行嘗試加載

這樣做的好處是,加載位于rt.jar包中的類時不管是哪個加載器加載,最終都會委托到BootStrap ClassLoader進行加載,這樣保證了使用不同的類加載器得到的都是同一個結果。

其實這個也是一個隔離的作用,避免了我們的代碼影響了JDK的代碼,比如我現在要來一個 

  1. public class String(){ 
  2.     public static void main(){sout;} 

這種時候,我們的代碼肯定會報錯,因為在加載的時候其實是找到了rt.jar中的String.class,然后發現這也沒有main方法

三、運行時數據區

3.1 本地方法棧和程序計數器

比如說我們現在點開Thread類的源碼,會看到它的start0方法帶有一個native關鍵字修飾,而且不存在方法體,這種用native修飾的方法就是本地方法,這是使用C來實現的,然后一般這些方法都會放到一個叫做本地方法棧的區域。

程序計數器其實就是一個指針,它指向了我們程序中下一句需要執行的指令,它也是內存區域中唯一一個不會出現OutOfMemoryError的區域,而且占用內存空間小到基本可以忽略不計。這個內存僅代表當前線程所執行的字節碼的行號指示器,字節碼解析器通過改變這個計數器的值選取下一條需要執行的字節碼指令。

如果執行的是native方法,那這個指針就不工作了。

3.2 方法區

方法區主要的作用技術存放類的元數據信息,常量和靜態變量···等。當它存儲的信息過大時,會在無法滿足內存分配時報錯。

3.3 虛擬機棧和虛擬機堆

一句話便是:棧管運行,堆管存儲。則虛擬機棧負責運行代碼,而虛擬機堆負責存儲數據。

3.3.1 虛擬機棧的概念

它是Java方法執行的內存模型。里面會對局部變量,動態鏈表,方法出口,棧的操作(入棧和出棧)進行存儲,且線程獨享。同時如果我們聽到局部變量表,那也是在說虛擬機棧

 public class Person{ 

  1.     int a = 1; 
  2.  
  3.     public void doSomething(){ 
  4.         int b = 2; 
  5.     } 

 

3.3.2 虛擬機棧存在的異常

如果線程請求的棧的深度大于虛擬機棧的最大深度,就會報 StackOverflowError (這種錯誤經常出現在遞歸中)。Java虛擬機也可以動態擴展,但隨著擴展會不斷地申請內存,當無法申請足夠內存時就會報錯 OutOfMemoryError。

3.3.3 虛擬機棧的生命周期

對于棧來說,不存在垃圾回收。只要程序運行結束,棧的空間自然就會釋放了。棧的生命周期和所處的線程是一致的。

這里補充一句:8種基本類型的變量+對象的引用變量+實例方法都是在棧里面分配內存。

3.3.4 虛擬機棧的執行

我們經常說的棧幀數據,說白了在JVM中叫棧幀,放到Java中其實就是方法,它也是存放在棧中的。

棧中的數據都是以棧幀的格式存在,它是一個關于方法和運行期數據的數據集。比如我們執行一個方法a,就會對應產生一個棧幀A1,然后A1會被壓入棧中。同理方法b會有一個B1,方法c會有一個C1,等到這個線程執行完畢后,棧會先彈出C1,后B1,A1。它是一個先進后出,后進先出原則。

3.3.5 局部變量的復用

局部變量表用于存放方法參數和方法內部所定義的局部變量。它的容量是以Slot為最小單位,一個slot可以存放32位以內的數據類型。

虛擬機通過索引定位的方式使用局部變量表,范圍為[0,局部變量表的slot的數量]。方法中的參數就會按一定順序排列在這個局部變量表中,至于怎么排的我們可以先不關心。而為了節省棧幀空間,這些slot是可以復用的,當方法執行位置超過了某個變量,那么這個變量的slot可以被其它變量復用。當然如果需要復用,那我們的垃圾回收自然就不會去動這些內存。

3.3.6 虛擬機堆的概念

JVM內存會劃分為堆內存和非堆內存,堆內存中也會劃分為年輕代和老年代,而非堆內存則為永久代。年輕代又會分為Eden和Survivor區。Survivor也會分為FromPlace和ToPlace,toPlace的survivor區域是空的。Eden,FromPlace和ToPlace的默認占比為 8:1:1。當然這個東西其實也可以通過一個 -XX:+UsePSAdaptiveSurvivorSizePolicy 參數來根據生成對象的速率動態調整

堆內存中存放的是對象,垃圾收集就是收集這些對象然后交給GC算法進行回收。非堆內存其實我們已經說過了,就是方法區。在1.8中已經移除永久代,替代品是一個元空間(MetaSpace),最大區別是metaSpace是不存在于JVM中的,它使用的是本地內存。并有兩個參數

  1. MetaspaceSize:初始化元空間大小,控制發生GC 
  2. MaxMetaspaceSize:限制元空間大小上限,防止占用過多物理內存。 

 移除的原因可以大致了解一下:融合HotSpot JVM和JRockit VM而做出的改變,因為JRockit是沒有永久代的,不過這也間接性地解決了永久代的OOM問題。

3.3.7 Eden年輕代的介紹

當我們new一個對象后,會先放到Eden劃分出來的一塊作為存儲空間的內存,但是我們知道對堆內存是線程共享的,所以有可能會出現兩個對象共用一個內存的情況。這里JVM的處理是每個線程都會預先申請好一塊連續的內存空間并規定了對象存放的位置,而如果空間不足會再申請多塊內存空間。這個操作我們會稱作TLAB,有興趣可以了解一下。

當Eden空間滿了之后,會觸發一個叫做Minor GC(就是一個發生在年輕代的GC)的操作,存活下來的對象移動到Survivor0區。Survivor0區滿后觸發 Minor GC,就會將存活對象移動到Survivor1區,此時還會把from和to兩個指針交換,這樣保證了一段時間內總有一個survivor區為空且to所指向的survivor區為空。經過多次的 Minor GC后仍然存活的對象(這里的存活判斷是15次,對應到虛擬機參數為 -XX:TargetSurvivorRatio 。為什么是15,因為HotSpot會在對象投中的標記字段里記錄年齡,分配到的空間僅有4位,所以最多只能記錄到15)會移動到老年代。老年代是存儲長期存活的對象的,占滿時就會觸發我們最常聽說的Full GC,期間會停止所有線程等待GC的完成。所以對于響應要求高的應用應該盡量去減少發生Full GC從而避免響應超時的問題。

而且當老年區執行了full gc之后仍然無法進行對象保存的操作,就會產生OOM,這時候就是虛擬機中的堆內存不足,原因可能會是堆內存設置的大小過小,這個可以通過參數-Xms、-Xms來調整。也可能是代碼中創建的對象大且多,而且它們一直在被引用從而長時間垃圾收集無法收集它們。

 

 3.3.8 如何判斷一個對象需要被干掉

 

 圖中程序計數器、虛擬機棧、本地方法棧,3個區域隨著線程的生存而生存的。內存分配和回收都是確定的。隨著線程的結束內存自然就被回收了,因此不需要考慮垃圾回收的問題。而Java堆和方法區則不一樣,各線程共享,內存的分配和回收都是動態的。因此垃圾收集器所關注的都是堆和方法這部分內存。

在進行回收前就要判斷哪些對象還存活,哪些已經死去。下面介紹兩個基礎的計算方法

1.引用計數器計算:給對象添加一個引用計數器,每次引用這個對象時計數器加一,引用失效時減一,計數器等于0時就是不會再次使用的。不過這個方法有一種情況就是出現對象的循環引用時GC沒法回收。

2.可達性分析計算:這是一種類似于二叉樹的實現,將一系列的GC ROOTS作為起始的存活對象集,從這個節點往下搜索,搜索所走過的路徑成為引用鏈,把能被該集合引用到的對象加入到集合中。搜索當一個對象到GC Roots沒有使用任何引用鏈時,則說明該對象是不可用的。主流的商用程序語言,例如Java,C#等都是靠這招去判定對象是否存活的。

(了解一下即可)在Java語言匯總能作為GC Roots的對象分為以下幾種:

  1. 虛擬機棧(棧幀中的本地方法表)中引用的對象(局部變量)
  2. 方法區中靜態變量所引用的對象(靜態變量)
  3. 方法區中常量引用的對象
  4. 本地方法棧(即native修飾的方法)中JNI引用的對象(JNI是Java虛擬機調用對應的C函數的方式,通過JNI函數也可以創建新的Java對象。且JNI對于對象的局部引用或者全局引用都會把它們指向的對象都標記為不可回收)
  5. 已啟動的且未終止的Java線程

這種方法的優點是能夠解決循環引用的問題,可它的實現需要耗費大量資源和時間,也需要GC(它的分析過程引用關系不能發生變化,所以需要停止所有進程)

3.3.9 如何宣告一個對象的真正死亡

首先必須要提到的是一個名叫 finalize() 的方法

finalize()是Object類的一個方法、一個對象的finalize()方法只會被系統自動調用一次,經過finalize()方法逃脫死亡的對象,第二次不會再調用。

補充一句:并不提倡在程序中調用finalize()來進行自救。建議忘掉Java程序中該方法的存在。因為它執行的時間不確定,甚至是否被執行也不確定(Java程序的不正常退出),而且運行代價高昂,無法保證各個對象的調用順序(甚至有不同線程中調用)。在Java9中已經被標記為deprecated ,且java.lang.ref.Cleaner(也就是強、軟、弱、幻象引用的那一套)中已經逐步替換掉它,會比finalize來的更加的輕量及可靠。

 判斷一個對象的死亡至少需要兩次標記

如果對象進行可達性分析之后沒發現與GC Roots相連的引用鏈,那它將會第一次標記并且進行一次篩選。判斷的條件是決定這個對象是否有必要執行finalize()方法。如果對象有必要執行finalize()方法,則被放入F-Queue隊列中。

GC對F-Queue隊列中的對象進行二次標記。如果對象在finalize()方法中重新與引用鏈上的任何一個對象建立了關聯,那么二次標記時則會將它移出“即將回收”集合。如果此時對象還沒成功逃脫,那么只能被回收了。

如果確定對象已經死亡,我們又該如何回收這些垃圾呢

3.4 垃圾回收算法

不會非常詳細的展開,常用的有標記清除,復制,標記整理和分代收集算法

3.4.1 標記清除算法

標記清除算法就是分為“標記”和“清除”兩個階段。標記出所有需要回收的對象,標記結束后統一回收。這個套路很簡單,也存在不足,后續的算法都是根據這個基礎來加以改進的。

其實它就是把已死亡的對象標記為空閑內存,然后記錄在一個空閑列表中,當我們需要new一個對象時,內存管理模塊會從空閑列表中尋找空閑的內存來分給新的對象。

不足的方面就是標記和清除的效率比較低下。且這種做法會讓內存中的碎片非常多。這個導致了如果我們需要使用到較大的內存塊時,無法分配到足夠的連續內存。比如下圖

 

 此時可使用的內存塊都是零零散散的,導致了剛剛提到的大內存對象問題

3.4.2 復制算法

為了解決效率問題,復制算法就出現了。它將可用內存按容量劃分成兩等分,每次只使用其中的一塊。和survivor一樣也是用from和to兩個指針這樣的玩法。fromPlace存滿了,就把存活的對象copy到另一塊toPlace上,然后交換指針的內容。這樣就解決了碎片的問題。

這個算法的代價就是把內存縮水了,這樣堆內存的使用效率就會變得十分低下了

 

 不過它們分配的時候也不是按照1:1這樣進行分配的,就類似于Eden和Survivor也不是等價分配是一個道理。

3.4.3 標記整理算法

復制算法在對象存活率高的時候會有一定的效率問題,標記過程仍然與“標記-清除”算法一樣,但后續步驟不是直接對可回收對象進行清理,而是讓所有存活的對象都向一端移動,然后直接清理掉邊界以外的內存

 3.4.4 分代收集算法

這種算法并沒有什么新的思想,只是根據對象存活周期的不同將內存劃分為幾塊。一般是把Java堆分為新生代和老年代,這樣就可以根據各個年代的特點采用最適當的收集算法。在新生代中,每次垃圾收集時都發現有大批對象死去,只有少量存活,那就選用復制算法,只需要付出少量存活對象的復制成本就可以完成收集。而老年代中因為對象存活率高、沒有額外空間對它進行分配擔保,就必須使用“標記-清理”或者“標記-整理”算法來進行回收。

說白了就是八仙過海各顯神通,具體問題具體分析了而已。

3.5 (了解)各種各樣的垃圾回收器

HotSpot VM中的垃圾回收器,以及適用場景

 

 到jdk8為止,默認的垃圾收集器是Parallel Scavenge 和 Parallel Old

從jdk9開始,G1收集器成為默認的垃圾收集器

目前來看,G1回收器停頓時間最短而且沒有明顯缺點,非常適合Web應用。在jdk8中測試Web應用,堆內存6G,新生代4.5G的情況下,Parallel Scavenge 回收新生代停頓長達1.5秒。G1回收器回收同樣大小的新生代只停頓0.2秒。

3.6 (了解)JVM的常用參數

JVM的參數非常之多,這里只列舉比較重要的幾個,通過各種各樣的搜索引擎也可以得知這些信息。

JVM參數的含義 

 

其實還有一些打印及CMS方面的參數,這里就不以一一列舉了

四、關于JVM調優的一些方面

根據剛剛涉及的jvm的知識點,我們可以嘗試對JVM進行調優,主要就是堆內存那塊

所有線程共享數據區大小=新生代大小 + 年老代大小 + 持久代大小。持久代一般固定大小為64m。所以java堆中增大年輕代后,將會減小年老代大小(因為老年代的清理是使用fullgc,所以老年代過小的話反而是會增多fullgc的)。此值對系統性能影響較大,Sun官方推薦配置為java堆的3/8。

4.1 調整最大堆內存和最小堆內存

-Xmx –Xms:指定java堆最大值(默認值是物理內存的1/4(<1GB))和初始java堆最小值(默認值是物理內存的1/64(<1GB))

默認(MinHeapFreeRatio參數可以調整)空余堆內存小于40%時,JVM就會增大堆直到-Xmx的最大限制.,默認(MaxHeapFreeRatio參數可以調整)空余堆內存大于70%時,JVM會減少堆直到 -Xms的最小限制。簡單點來說,你不停地往堆內存里面丟數據,等它剩余大小小于40%了,JVM就會動態申請內存空間不過會小于-Xmx,如果剩余大小大于70%,又會動態縮小不過不會小于–Xms。就這么簡單

開發過程中,通常會將 -Xms 與 -Xmx兩個參數的配置相同的值,其目的是為了能夠在java垃圾回收機制清理完堆區后不需要重新分隔計算堆區的大小而浪費資源。

我們執行下面的代碼

  1. System.out.println("Xmx=" + Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M");    //系統的最大空間 
  2. System.out.println("free mem=" + Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M");  //系統的空閑空間 
  3. System.out.println("total mem=" + Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M");  //當前可用的總空間 

 注意:此處設置的是Java堆大小,也就是新生代大小 + 老年代大小

 

 設置一個VM options的參數

-Xmx20m -Xms5m -XX:+PrintGCDetails 

 再次啟動main方法 

 這里GC彈出了一個Allocation Failure分配失敗,這個事情發生在PSYoungGen,也就是年輕代中

這時候申請到的內存為18M,空閑內存為4.214195251464844M

我們此時創建一個字節數組看看,執行下面的代碼

  1. byte[] b = new byte[1 * 1024 * 1024]; 
  2. System.out.println("分配了1M空間給數組"); 
  3. System.out.println("Xmx=" + Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M");  //系統的最大空間 
  4. System.out.println("free mem=" + Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M");  //系統的空閑空間 
  5. System.out.println("total mem=" + Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M"); 

 此時free memory就又縮水了,不過total memory是沒有變化的。Java會盡可能將total mem的值維持在最小堆內存大小 

  1. byte[] b = new byte[10 * 1024 * 1024]; 
  2. System.out.println("分配了10M空間給數組"); 
  3. System.out.println("Xmx=" + Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M");  //系統的最大空間 
  4. System.out.println("free mem=" + Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M");  //系統的空閑空間 
  5. System.out.println("total mem=" + Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M");  //當前可用的總空間 

 

  

 這時候我們創建了一個10M的字節數據,這時候最小堆內存是頂不住的。我們會發現現在的total memory已經變成了15M,這就是已經申請了一次內存的結果。

此時我們再跑一下這個代碼

  1. System.gc(); 
  2. System.out.println("Xmx=" + Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M");    //系統的最大空間 
  3. System.out.println("free mem=" + Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M");  //系統的空閑空間 
  4. System.out.println("total mem=" + Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M");  //當前可用的總空間 

 

 此時我們手動執行了一次fullgc,此時total memory的內存空間又變回5.5M了,此時又是把申請的內存釋放掉的結果。

4.2 調整新生代和老年代的比值

-XX:NewRatio --- 新生代(eden+2*Survivor)和老年代(不包含永久區)的比值

例如:-XX:NewRatio=4,表示新生代:老年代=1:4,即新生代占整個堆的1/5。在Xms=Xmx并且設置了Xmn的情況下,該參數不需要進行設置。

4.3 調整Survivor區和Eden區的比值

-XX:SurvivorRatio(幸存代)--- 設置兩個Survivor區和eden的比值

例如:8,表示兩個Survivor:eden=2:8,即一個Survivor占年輕代的1/10

4.4 設置年輕代和老年代的大小

-XX:NewSize --- 設置年輕代大小

-XX:MaxNewSize --- 設置年輕代最大值

可以通過設置不同參數來測試不同的情況,反正最優解當然就是官方的Eden和Survivor的占比為8:1:1,然后在剛剛介紹這些參數的時候都已經附帶了一些說明,感興趣的也可以看看。反正最大堆內存和最小堆內存如果數值不同會導致多次的gc,需要注意。

4.5 小總結

根據實際事情調整新生代和幸存代的大小,官方推薦新生代占java堆的3/8,幸存代占新生代的1/10

在OOM時,記得Dump出堆,確??梢耘挪楝F場問題,通過下面命令你可以輸出一個.dump文件,這個文件可以使用VisualVM或者Java自帶的Java VisualVM工具。

-Xmx20m -Xms5m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=你要輸出的日志路徑

一般我們也可以通過編寫腳本的方式來讓OOM出現時給我們報個信,可以通過發送郵件或者重啟程序等來解決。

4.6 永久區的設置

-XX:PermSize -XX:MaxPermSize

初始空間(默認為物理內存的1/64)和最大空間(默認為物理內存的1/4)。也就是說,jvm啟動時,永久區一開始就占用了PermSize大小的空間,如果空間還不夠,可以繼續擴展,但是不能超過MaxPermSize,否則會OOM。

tips:如果堆空間沒有用完也拋出了OOM,有可能是永久區導致的。堆空間實際占用非常少,但是永久區溢出 一樣拋出OOM。

4.7 JVM的棧參數調優

4.7.1 調整每個線程??臻g的大小

可以通過-Xss:調整每個線程??臻g的大小

JDK5.0以后每個線程堆棧大小為1M,以前每個線程堆棧大小為256K。在相同物理內存下,減小這個值能生成更多的線程。但是操作系統對一個進程內的線程數還是有限制的,不能無限生成,經驗值在3000~5000左右

4.7.2 設置線程棧的大小

-XXThreadStackSize: 設置線程棧的大小(0 means use default stack size)

這些參數都是可以通過自己編寫程序去簡單測試的,這里礙于篇幅問題就不再提供demo了

4.8 (可以直接跳過了)JVM其他參數介紹

形形色色的參數很多,就不會說把所有都扯個遍了,因為大家其實也不會說一定要去深究到底。

4.8.1 設置內存頁的大小

-XXThreadStackSize: 設置內存頁的大小,不可設置過大,會影響Perm的大小

4.8.2 設置原始類型的快速優化

-XX:+UseFastAccessorMethods: 設置原始類型的快速優化

4.8.3 設置關閉手動GC

-XX:+DisableExplicitGC: 設置關閉System.gc()(這個參數需要嚴格的測試)

4.8.4 設置垃圾最大年齡

-XX:MaxTenuringThreshold 設置垃圾最大年齡。如果設置為0的話,則年輕代對象不經過Survivor區,直接進入年老代. 對于年老代比較多的應用,可以提高效率。如果將此值設置為一個較大值, 則年輕代對象會在Survivor區進行多次復制,這樣可以增加對象再年輕代的存活時間, 增加在年輕代即被回收的概率。該參數只有在串行GC時才有效.

4.8.5 加快編譯速度

-XX:+AggressiveOpts

加快編譯速度

4.8.6 改善鎖機制性能

-XX:+UseBiasedLocking

4.8.7 禁用垃圾回收

-Xnoclassgc

4.8.8 設置堆空間存活時間

-XX:SoftRefLRUPolicyMSPerMB 設置每兆堆空閑空間中SoftReference的存活時間,默認值是1s。

4.8.9 設置對象直接分配在老年代

-XX:PretenureSizeThreshold 設置對象超過多大時直接在老年代分配,默認值是0。

4.8.10 設置TLAB占eden區的比例

-XX:TLABWasteTargetPercent 設置TLAB占eden區的百分比,默認值是1% 。

4.8.11設置是否優先YGC

-XX:+CollectGen0First 設置FullGC時是否先YGC,默認值是false。

 

責任編輯:武曉燕 來源: 說出你的愿望吧
相關推薦

2020-02-20 11:32:09

Kafka概念問題

2023-12-26 18:22:05

RocketMQ延遲消息

2020-12-04 06:40:46

Zookeeper選舉機制

2019-05-17 08:27:23

SQL注入漏洞攻擊

2024-12-09 08:18:33

2021-03-01 18:38:32

Mock測試軟件

2025-10-27 01:55:00

2021-02-18 09:06:39

數據訪問者模式

2019-08-14 09:13:38

中臺互聯網業務

2025-02-05 08:00:00

2024-04-24 12:41:10

Rust安全性內存

2023-09-18 14:34:07

Kubernetes云原生

2025-03-25 09:00:00

2021-01-27 13:50:17

AI 數據機器學習

2018-11-19 08:34:22

Hadoop架構HDFS

2020-09-08 06:30:59

微服務代碼模塊

2021-10-08 08:58:35

物聯網通信發布者

2023-05-06 07:29:49

Spring事務傳播

2023-09-13 09:02:22

PVPVC存儲

2025-05-14 08:25:00

深度學習AI人工智能
點贊
收藏

51CTO技術棧公眾號

国产成人精品综合| 日韩欧美综合在线| 一区二区三区四区视频在线 | 午夜不卡av免费| 欧美黑人3p| 91麻豆一区二区| 99热免费精品| 日韩中文字幕免费| 人妻少妇精品视频一区二区三区| 日韩毛片免费看| 婷婷久久综合九色综合伊人色| 亚洲精品中文字幕乱码三区不卡| 狠狠躁日日躁夜夜躁av| 日本视频中文字幕一区二区三区| 免费99精品国产自在在线| 女尊高h男高潮呻吟| 日本精品一区二区三区在线观看视频| 欧美三级免费观看| 欧美极品少妇无套实战| 北岛玲日韩精品一区二区三区| 国产精品456露脸| 国产精品电影网站| 日韩三级视频在线播放| 亚洲做受高潮无遮挡| 国产www视频在线观看| 国产精品视频一二三| 国产福利久久| 国产理论视频在线观看| 日韩制服丝袜av| 久久久人成影片一区二区三区| frxxee中国xxx麻豆hd| 精品国产乱码久久久| 日韩av影院在线观看| 丰满少妇中文字幕| 视频欧美精品| 欧美日韩在线观看一区二区| 99精品视频在线看| 乱人伦视频在线| 亚洲午夜电影网| www.在线观看av| 综合久久2019| 亚洲黄色av一区| 制服诱惑一区| 黄色的网站在线观看| 国产精品久久久爽爽爽麻豆色哟哟| 看高清中日韩色视频| 农村少妇久久久久久久| 国产 欧美在线| av一区二区三区四区电影| 国产免费黄色片| 精品一区二区三区久久久| 国产精品久久久久秋霞鲁丝| 99re这里只有精品在线| 日日夜夜精品视频天天综合网| 欧美一区在线直播| 天天干天天干天天操| 99视频一区| 欧美一区亚洲一区| 黄色av网站免费| 蜜桃精品在线观看| 成人精品一区二区三区电影免费 | 污视频网站在线免费| 国产精品福利一区| 国产免费色视频| 天天干在线视频论坛| 亚洲一区二区三区激情| 精品少妇人妻av免费久久洗澡| av今日在线| 一本色道久久综合亚洲精品按摩 | 国产精一品亚洲二区在线视频| 国产日韩在线免费| 国产按摩一区二区三区| 丁香婷婷综合色啪| 久久精精品视频| 国产精品一级伦理| 亚洲欧洲日产国码二区| 国产精品一二三在线观看| 午夜在线激情影院| 精品国产福利在线| 欧美日韩亚洲自拍| 日本精品在线观看| 精品视频在线播放免| 国产精品久久久久久久av| 99精品在线| 海角国产乱辈乱精品视频| 日本高清不卡码| 久久国产精品99久久久久久老狼| 亚洲最大福利视频网站| 无码精品黑人一区二区三区| 国产精品久久久久一区| 野外做受又硬又粗又大视频√| 久久uomeier| 7777精品伊人久久久大香线蕉 | 黄色网一区二区| 在线观看亚洲视频| 精品视频久久久久| 日本成人在线视频网站| 国产精品yjizz| 国产69久久| 精品伊人久久久| 欧美一区二区三区在线| 五月婷婷综合在线观看| 在线精品视频在线观看高清| 91福利视频在线观看| 91在线观看喷潮| 91色在线porny| 色一情一乱一乱一区91| 成人美女大片| 欧美r级在线观看| 日韩精品电影一区二区三区| aa国产精品| 亚洲va欧美va国产综合久久| 区一区二在线观看| 成人av免费在线观看| 一区二区在线不卡| 三级中文字幕在线观看| 日韩一级黄色大片| 黄色免费一级视频| 老鸭窝毛片一区二区三区| 亚洲自拍欧美另类| 网友自拍视频在线| 欧美性xxxx极品hd满灌| 91人人澡人人爽| 婷婷亚洲最大| 国产精品美女主播| 国产三级在线| 色综合激情久久| 影音先锋人妻啪啪av资源网站| 亚洲女同另类| 91精品久久久久久久久久| 国产区视频在线播放| 日韩欧美精品中文字幕| 性囗交免费视频观看| 欧美午夜不卡| 99视频国产精品免费观看| 久做在线视频免费观看| 88在线观看91蜜桃国自产| 亚洲天堂精品一区| 蜜桃视频一区二区三区在线观看| 水蜜桃亚洲一二三四在线| 欧美伦理91| 亚洲跨种族黑人xxx| 毛片视频网站在线观看| 白白在线精品| 亚洲欧美综合在线精品| 亚洲五月天综合| 欧美日韩国产高清电影| 国产成人在线一区| 九色视频在线播放| 91黄视频在线| 黑人と日本人の交わりビデオ| 日韩成人一级片| 亚洲国产一区二区在线| jizz亚洲女人高潮大叫| 日韩在线免费视频| 国产乱码久久久| 亚洲伊人色欲综合网| 免费在线观看日韩av| 最新日韩欧美| 久久综合九色综合网站| 日韩精品一区二区三区| 亚洲视频777| 中文字幕永久在线观看| 亚洲天堂2016| 波多野结衣一二三区| 久久av一区| 亚洲欧美日韩精品在线| 亚洲欧美专区| 久久久久久香蕉网| 美州a亚洲一视本频v色道| 欧美亚洲禁片免费| 国产乱国产乱老熟300| 99久久综合狠狠综合久久| 成人观看免费完整观看| 精品视频久久| 99久久自偷自偷国产精品不卡| japanese色国产在线看视频| 亚洲美女动态图120秒| 做爰视频毛片视频| 一区二区三区av电影| 国产精品无码一区二区三区免费| 奇米影视一区二区三区小说| 亚洲国产精品女人| 精品嫩草影院| 国产欧美日韩最新| gogo高清在线播放免费| 中文综合在线观看| 丰满人妻一区二区三区四区53| 欧美性猛交xxx| 五月天婷婷色综合| www.久久精品| 亚洲精品电影网站| 精品肉丝脚一区二区三区| 久久久精品中文字幕麻豆发布| 天天色天天综合网| 亚洲免费影院| 男人日女人的bb| 精品久久电影| 国产精品日韩一区二区免费视频| www.国产精品| 26uuu日韩精品一区二区| 九七久久人人| 一本一本久久a久久精品牛牛影视 一本色道久久综合亚洲精品小说 一本色道久久综合狠狠躁篇怎么玩 | 久久中文字幕一区二区三区| 黄色免费高清视频| 色棕色天天综合网| 国产私拍一区| 超碰国产精品一区二页| 日本sm极度另类视频| 牛牛电影国产一区二区| 精品国产一区二区三区在线观看 | 久久免费精品| 国产精品九九久久久久久久| 国产极品人妖在线观看| 日韩有码在线观看| 国产三级电影在线观看| 亚洲国产欧美一区二区三区同亚洲| 国产精品无码一区二区桃花视频| 色婷婷av一区二区三区软件| 久久精品视频9| 亚洲男同性恋视频| 免费成人深夜蜜桃视频| 国产性做久久久久久| 免费的av网站| 成人黄色在线看| 亚洲精品一区二区18漫画| 精品一区二区日韩| 国产高清视频网站| 日韩高清不卡一区二区三区| 久久久久人妻精品一区三寸| 国产亚洲在线观看| 极品美女扒开粉嫩小泬| 91久久亚洲| 无码中文字幕色专区| 亚洲国产综合在线看不卡| 亚洲第一精品在线| 爱爱的免费视频| 91在线视频在线| 先锋资源av在线| 99v久久综合狠狠综合久久| 国产视频精品视频| 成人高清在线视频| 99免费观看视频| 成人性生交大合| 日韩av无码一区二区三区不卡 | 羞羞的视频在线看| 萌白酱国产一区二区| 91麻豆免费在线视频| 美女黄色丝袜一区| 国产在线拍揄自揄拍视频| 欧美精品18videos性欧| 草草在线视频| 欧美在线视频一二三| 中文日产幕无线码一区二区| 欧洲日韩成人av| 最新日韩一区| 成人国产精品久久久久久亚洲| 爱情电影网av一区二区| 亚洲free性xxxx护士hd| 亚洲国产欧美在线观看| 国产精品区一区二区三含羞草| 欧美高清视频看片在线观看 | 91精品福利| 男人c女人视频| 东京干手机福利视频| 最近中文字幕一区二区三区| avtt天堂在线| 婷婷久久综合九色综合绿巨人 | 久久精品99久久| 欧美极品在线观看| 亚洲一区二区三区免费看| 综合久久综合| 欧美日韩一道本| 老妇喷水一区二区三区| 色www免费视频| 国产凹凸在线观看一区二区| 少妇饥渴放荡91麻豆| 国产精品美女一区二区在线观看| 乱h高h女3p含苞待放| 午夜电影一区二区三区| 男人的天堂av网站| 欧美一区二区三区免费观看视频| 欧美一区二区公司| 中文字幕国产亚洲| 欧美性video| 国产精品99久| 182午夜视频| 91蜜桃网址入口| 日韩一区二区不卡视频| 姬川优奈aav一区二区| 真实新婚偷拍xxxxx| 日韩欧美一二区| 国产小视频免费在线网址| 美日韩精品免费视频| 欧洲亚洲两性| 国产精品播放| 日韩www.| 免费看又黄又无码的网站| 黄色小说综合网站| 女人又爽又黄免费女仆| 亚洲一区二区美女| 在线免费观看高清视频| 日韩av在线免费看| 国产三区视频在线观看| 日产精品99久久久久久| 这里视频有精品| 综合视频免费看| 丝袜a∨在线一区二区三区不卡| 精品国产免费久久久久久婷婷| 中文字幕第一区第二区| 天天操天天摸天天干| 91精品福利在线一区二区三区| 黄网在线观看| 91av国产在线| 大桥未久女教师av一区二区| 在线丝袜欧美日韩制服| 日韩专区在线视频| 7788色淫网站小说| 亚洲激情图片一区| 国产精品视频在线观看免费| 亚洲日本aⅴ片在线观看香蕉| 97人澡人人添人人爽欧美| 91免费精品国偷自产在线| blacked蜜桃精品一区| 国产成人a亚洲精v品无码| 成人涩涩免费视频| 欧美日韩在线视频免费播放| 欧美日韩极品在线观看一区| 国产中文字幕在线| 国产成人精品在线播放| 日韩欧美ww| 人妻少妇被粗大爽9797pw| av中文字幕不卡| 亚洲精品1区2区3区| 精品国产乱码91久久久久久网站| 日本天码aⅴ片在线电影网站| 成人免费淫片aa视频免费| 久久国产精品成人免费观看的软件| 亚洲精品中文字幕无码蜜桃| 久久色成人在线| 欧美一区二区三区四区夜夜大片 | 亚洲人成亚洲人成在线观看| 欧亚av在线| 美女精品国产| 久久五月激情| 蜜臀久久99精品久久久久久| 日本韩国欧美三级| 超碰97在线免费观看| 国产精品视频区| 四虎国产精品免费观看| 国产乱女淫av麻豆国产| 中文字幕制服丝袜成人av| 国产精品色综合| 欧美国产极速在线| 加勒比久久高清| 国产熟女高潮视频| 亚洲国产成人自拍| 国产日本精品视频| 欧美剧在线观看| 精品三级av| www黄色在线| 中文字幕中文乱码欧美一区二区| 99久久久久久久| 久久久久成人网| 九九精品久久| 国产精品久久a| 樱花草国产18久久久久| 午夜18视频在线观看| 国产精品久久久久久久av电影 | www欧美日韩| 日本一区二区三区播放| 日本中文字幕网址| 国产欧美日本一区视频| 国产青青草视频| 午夜免费在线观看精品视频| 深夜福利久久| 久久久福利影院| 精品毛片网大全| 888av在线| 成人资源av| 石原莉奈一区二区三区在线观看| 国产一二三av| 精品国产三级电影在线观看| 欧美影视资讯| 小泽玛利亚av在线| 26uuu久久天堂性欧美| 国产又粗又猛又黄又爽无遮挡| 久久久久免费视频| 成人影院天天5g天天爽无毒影院 | 91成人福利| 黄色片在线免费| 亚洲制服丝袜av| 最近高清中文在线字幕在线观看| 成人资源av| 麻豆精品国产91久久久久久| 精品少妇久久久| 精品国产一区二区三区四区在线观看 | 黄色国产精品一区二区三区| 久久天堂影院| 欧美在线一区二区三区四|