概述
在這篇文章中,我們將一起看一下,一些常見的JAVA虛擬機的參數配置。
堆內存 - Xms 和 Xmx配置
堆內存配置,可以說是應用程序中,最常見的提升性能的參數配置。
這就是為什么我們需要指定最大和最小堆內存配置:
-Xms<heap size>[unit]
-Xmx<heap size>[unit]
在這里,unit 表示要初始化內存(用堆大小表示)的單元。 單位可以標記為“ g”代表 GB,“ m”代表 MB,“ k”代表 KB。
例如,如果我們想給 JVM 分配最小的2gb 和最大的5Gb,我們需要寫:
-Xms2G -Xmx5G
從 java8開始,Metaspace 的大小沒有定義。 一旦它達到全局限制,JVM 會自動增加它,然而,為了克服任何不必要的不穩定性,我們可以設置 Metaspace 大小為:
-XX:MaxMetaspaceSize=<metaspace size>[unit]
在這里,metaspace size表示我們要分配給元空間的內存量。
根據 Oracle 的參考指南,除了總的可用內存之外,第二大影響因素是為年輕代保留的堆的比例。 默認情況下,YG(年輕代) 的最小大小為1310 MB,最大大小不受限制。
我們也可以顯示的設置年輕代的大小:
-XX:NewSize=<young size>[unit]
-XX:MaxNewSize=<young size>[unit]
垃圾收集
為了提高應用程序的穩定性,選擇正確的垃圾收集算法至關重要。有四種類型的 GC 實現:
- Serial Garbage Collector 串行垃圾收集器
- Parallel Garbage Collector 并行垃圾收集器
- CMS Garbage Collector CMS垃圾收集器
- G1 Garbage Collector G1垃圾收集器
這些實現可以使用以下參數聲明:
-XX:+UseSerialGC
-XX:+UseParallelGC
-XX:+USeParNewGC
-XX:+UseG1GC
GC 日志
為了嚴格監視應用程序的運行狀況,我們應該始終檢查 JVM 的垃圾收集性能。 最簡單的方法是以可讀的格式記錄 GC 日志。
使用以下參數,我們可以記錄 GC 活動:
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=< number of log files >
-XX:GCLogFileSize=< file size >[ unit ]
-Xloggc:/path/to/gc.log
在這里,UseGCLogFileRotation 指定日志文件滾動策略,很像 log4j、 sl4j 等。 NumberOfGCLogfFles 表示可以為單個應用程序生命周期編寫的日志文件的最大數量。 GCLogFileSize 指定文件的最大大小。 最后,loggc 表示它的位置。
這里需要注意的是,還有兩個可用的 JVM 參數(- XX: + PrintGCTimeStamps 和-XX: + PrintGCDateStamps)可用于在 GC 日志中打印日期時間戳。
例如,如果我們希望分配最多100個 GC 日志文件,每個文件的最大大小為50 MB,并希望將它們存儲在‘/home/user/log/ ’位置,我們可以使用以下語法:
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=10
-XX:GCLogFileSize=50M
-Xloggc:/home/user/log/gc.log
但是,問題是總是在后臺使用一個附加的守護進程來監視系統時間。 這種行為可能會造成一些性能瓶頸; 這就是為什么在生產中最好不要使用這個參數的原因。
OOM的處理
對于大型應用程序來說,遇到OOM是非常常見的,OOM會導致應用程序崩潰。 這是一個非常關鍵的場景,很難復制以解決問題。
這就是為什么 JVM 提供了一些參數,這些參數將堆內存轉儲到一個物理文件中,以后可以用來查找內存泄漏:
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=./java_pid<pid>.hprof
-XX:OnOutOfMemoryError="< cmd args >;< cmd args >"
-XX:+UseGCOverheadLimit
這里有幾點需要注意:
- HeapDumpOnOutOfMemoryError: 這個參數表示如果發生OOM,則指示 JVM 將 heap 轉儲到物理文件
- HeapDumpPath: 這個參數表示要寫入文件的路徑, 文件名任意; 但是,如果 JVM 在名稱中找到一個 pid 標記,導致內存不足錯誤的當前進程的進程 id 將會以Hprof 格式附加到文件名中
- OnOutOfMemoryError: 這個參數用于發出緊急命令,以便在內存不足的情況下執行; 在 cmd args 中應使用適當的命令。 例如,如果我們想在內存不足時重啟服務器,我們可以設置參數:
-XX:OnOutOfMemoryError="shutdown -r"
- UseGCOverheadLimit: 該參數是一種策略,它限制在拋出 OutOfMemory 錯誤之前,在 GC 中花費的 VM 時間的比例
32/64位
在同時安裝了32位和64位包的操作系統環境中,JVM 會自動選擇32位環境包。如果我們想手動設置環境為64位,我們可以使用下面的參數:
-d<OS bit>
Misc(其他一些參數)
- -server: 表示啟用 HotSpot 虛擬機, 該參數在64位系統中默認使用
- -XX:+UseStringDeduplication: java 8u20版本引入了這個 JVM 參數,用來減少通過創建太多相同 String 的實例帶來的不必要的內存使用; 這通過將重復的 String 值減少為單個全局 char []數組來優化堆內存
- -XX:+UseLwpsynchronization: 設置基于 LWP (輕量級進程)的同步策略,而不是基于線程的同步策略
- -XX:LargePageSizeInBytes: 設置用于 Java 堆的 Large Page大小; 它采用 gb / mb / kb 的參數; 使用較大的頁面大小,我們可以更好地利用虛擬內存硬件資源; 然而,這可能會導致 PermGen 的空間大小變大,這反過來會迫使減小 Java 堆空間的大小
- -XX:MaxHeapFreeRatio: 設置 GC 之后堆空閑的最大百分比,以避免收縮。
- -XX:MinHeapFreeRatio: 設置 GC 之后堆空閑的最小百分比,以避免擴展; 為了監視堆使用情況,可以使用 JDK 附帶的 VisualVM。
- -XX:SurvivorRatio: Eden區和幸存者空間大小的比率——例如,-XX:SurvivorRatio=6 將每個幸存者空間和Eden區的比率設置為1:6
- -XX:+UseLargePages: 如果系統支持, 則使用大的頁面內存,請注意,如果使用這個 JVM 參數,OpenJDK 7會崩潰
- -XX:+UseStringCache: 啟用 String 池中可用的常用分配字符串的緩存
- -XX:+UseCompressedStrings: 對 String 對象使用 byte []類型,該類型可以用純 ASCII 格式表示
- -XX:+OptimizeStringConcat: 它在可能的情況下優化字符串串聯操作
總結
在這篇簡短的文章中,我們了解了一些重要的 JVM 參數,這些參數可用于調優和提高應用程序性能,其中一些還可以用于調試。