JVM調優由淺到深(四)——JVM內存分配參數詳解

我們在這一篇文章中已經大概瞭解到了jvm的參數有哪些,大概怎麼設置。
JVM調優由淺到深(一)——jvm參數配置

現在我們再來詳細得再更加詳細分析一次;

常用參數設置

設置最大堆內存

參數說明 例子
最大堆內存 -Xmx10m

在運行時,可以使用 Runtime.getRuntime().maxMemory() 取得系統可用的最大堆內存。

    public void test5(){
        System.out.println(Runtime.getRuntime().maxMemory()/1024/1024);
    }

運行結果:

設置最小堆內存

參數說明 例子
最小堆內存 -Xms10m

Java應用程序在運行時,首先被分配-Xms指定的內存大小,並儘可能嘗試在這個空間段內運行程序。
當-Xms指定的內存大小確實無法滿足應用程序時,JVM 纔會向操作系統申請更多的內存,直到內存大小達到-Xmx指定的最大內存爲止。
若超過-Xmx的值,則拋出 OutOfMemoryError 異常。

如果 -Xms 的數值較小,那麼JVM爲了保證系統儘可能地在指定內存範圍內運行,就會更加頻繁地進行GC操作,以釋放失效的內存空間。
從而,會增加 Minor GC 和 Full GC的次數,對系統性能產生一定的影響
因此把 -Xms 值設置爲 -Xmx 時,可以在系統運行初期減少 GC 的次數和耗時。

設置新生代

參數說明 例子
新生代 -Xmn2m

設置一個較大的新生代會減少老年代的大小,這個參數對系統性能以及 GC 行爲有很大的影響。
新生代的大小一般設置爲整個堆空間的1/4到1/3左右。

在 Hot Spot 虛擬機中,-XX:NewSize 用於設置新生代的初始大小,
-XX:MaxNewSize用於設置新生代的最大值。
但通常情況下,只設置 -Xmn 以及可以滿足絕大部分應用的需要。
設置 -Xmn 的效果等同於設置了相同的-XX:NewSize 和 -XX:MaxNewSize。

若設置不同的-XX:NewSize 和 -XX:MaxNewSize可能會導致內存震盪,從而產生不必要的系統開銷。

設置持久代

持久代(方法區)不屬於Java堆的一部分。在Hot Spot虛擬機中,使用-XX:MaxPermSize可以設置持久代的最大值,使用-XX:PermSize可以設置持久代的初始大小。

JDK1.8取消了PermGen,取而代之的是Metaspace(元空間),
所以PermSize和MaxPermSize參數失效,取而代之的是 -XX:MetaspaceSize
和 -XX:MaxMetaspaceSize。

參數說明 例子
持久代的初始大小 -XX:MetaspaceSize=64M
持久代的最大值 -XX:MaxMetaspaceSize=128M

持久代的大小直接決定了系統可以支持多少個類定義和多少常量。
對於使用 CGLIB 或者 Javassist 等動態字節碼生成工具的應用程序而言,
設置合理的持久代大小有助於維持系統穩定。

一般來說,設置MaxMetaspaceSize爲64MB已經可以滿足絕大部分應用程序正常工作。
如果依然出現永久區溢出,可以將MaxMetaspaceSize設置爲128MB。
這是兩個很常用的永久區取值。

設置線程棧

線程棧是線程的一塊私有空間。有關描述可以參考前文的“Java虛擬機棧”。

參數說明 例子
線程棧大小 -Xss1M

在線程中進行局部變量分配,函數調用時,都需要在棧中開闢空間。

如果棧的空間分配太小,那麼線程在運行時,可能沒有足夠的空間分配局部變量或者達不到足夠的函數調用深度,導致程序異常退出;

如果棧空間過大,那麼開設線程所需的內存成本就會上升,系統所能支持的線程總數就會下降。

由於Java堆也是向操作系統申請內存空間的,
因此,如果堆空間過大,就會導致操作系統可用於線程棧的內存減少,
從而間接減少程序所能支持的線程數量。

當系統由於內存不夠無法創建新的線程時,會拋出 OOM 異常如下:

java.lang.OutOfMemoryError: unable to create new native thread

根據以上內容可知,這並不是由於堆內存不夠而導致的 OOM,而是因爲操作系統內存減去堆內存後,剩餘的系統內存不足而無法創建新的線程。

在這種情況下,可以嘗試減少堆內存,以換取更多的系統空間,來解決這個問題。

如果系統確實需要大量的線程併發執行,那麼設置一個較小的堆和較小的棧,
有助於提供系統所能承受的最大線程數。

堆的內存分配

參數說明 例子
eden區/survivor區 -XX:SurvivorRatio=8
老年代/新生代 -XX:NewRatio=2

參數 -XX:SurvivorRatio 是用來設置新生代中,eden空間和s0空間的比例關係。
s0 和 s1 空間又被稱爲 from 空間和 to 空間。
它們的大小是相同的,職能也是一樣的,並在 Minor GC後,會互換角色。

公式:-XX:SurvivorRatio = eden/s0 = eden/s1

舉例:當設置JVM參數 -Xmn10M -XX:SurvivorRatio=8 就等於設置 eden=8M,s0=1M,s1=1M。

參數 -XX:NewRatio 是用來設置新生代與老年代的比例:

公式:-XX:NewRatio = 老年代 / 新生代

舉例:當設置JVM參數 -Xms18M -Xmx18M -XX:NewRatio=2運行程序時,新生代約佔6MB,老年代約佔12MB。

堆分配參數總結

參數說明 例子
-Xmx 設置Java應用程序能獲得的最大堆
-Xms 設置Java應用程序啓動時的初始堆
-Xss 設置新生代的初始大小與最大值
-Xmn 設置新生代的初始大小與最大值
-XX:NewSize 設置新生代的大小。
-XX:NewRatio 設置老年代與新生代的比例,它等於老年代大小除以新生代大小。
-XX:SurvivorRatio 設置新生代中eden區和survivor區的比例
-XX:MetaspaceSize XX
-XX:MetaspaceSize (Java8)設置永久區的初始值。。
-XX:MaxMetaspaceSize (Java8)最大的持久區大小。
-XX:MinHeapFreeRatio 設置堆空間的最大空閒比例,當堆空間的空閒內存小於這個數值時,JVM便會擴展堆空間
-XX:MaxHeapFreeRatio 設置堆空間的最大空閒比例。當堆空間的空閒內存大於這個數值時,便會壓縮堆空間,得到一個較小的堆。
-XX:TargetSurvivorRatio 設置survivor區的可使用率。當survivor區的空間使用率達到這個值時,會將對象送入老年代。

非常感謝以下博主的優秀博客

https://www.cnblogs.com/yueshutong/p/9768298.html

發佈了32 篇原創文章 · 獲贊 14 · 訪問量 4487
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章