JVM中-D、-X、-XX參數(shù)的區(qū)別
JVM 參數(shù)眾多,我們常在啟動一個 Java 程序時通過命令行(例如:java -jar app.jar
)指定各種參數(shù)選項(xiàng)。很多同學(xué)就會對此感到疑惑,為什么有時候要用 -D
,有時候卻要用 -X
,還有些時候用的卻是 -XX
呢?
今天,我就在這篇文章中講一講這些選項(xiàng)之間的差異??赐赀@篇文章之后,你將學(xué)到 JVM 選項(xiàng)的主要分類、不同分類的選項(xiàng)的主要用途,以及如何找出 JVM 支持的各種配置項(xiàng)。
想直接知道答案的同學(xué)可以直接跳到文章結(jié)尾。
JVM 選項(xiàng)分類
JVM 其實(shí)支持三種類型的選項(xiàng):標(biāo)準(zhǔn)選項(xiàng)(standard options)、非標(biāo)準(zhǔn)選項(xiàng)(non-standard options,又叫 extra-options)和高級選項(xiàng)(advanced options)。之所以有這么多選項(xiàng),是因?yàn)?JVM 只是一個規(guī)范,它有不同的實(shí)現(xiàn),例如 HotSpot、OpenJ9、GraalVM、Azul Zing 等。不同的 JVM 實(shí)現(xiàn)支持的選項(xiàng)會有所不同,但是有些選項(xiàng)是所有的 JVM 實(shí)現(xiàn)都會支持的,這類選項(xiàng)就是標(biāo)準(zhǔn)選項(xiàng)。
標(biāo)準(zhǔn)選項(xiàng)
標(biāo)準(zhǔn)選項(xiàng)是所有 JVM 實(shí)現(xiàn)都會支持的。打開控制臺,輸入 java
,你不僅能看到 java
命令的使用手冊,還能看到你機(jī)器上默認(rèn)的 JVM 所支持的所有標(biāo)準(zhǔn)選項(xiàng):
~$ java Usage: java [options] <mainclass> [args...] (to execute a class) or java [options] -jar <jarfile> [args...] (to execute a jar file) or java [options] -m <module>[/<mainclass>] [args...] java [options] --module <module>[/<mainclass>] [args...] (to execute the main class in a module) or java [options] <sourcefile> [args] (to execute a single source-file program) Arguments following the main class, source file, -jar <jarfile>, -m or --module <module>/<mainclass> are passed as the arguments to main class. where options include: -zero to select the "zero" VM -dcevm to select the "dcevm" VM -cp <class search path of directories and zip/jar files> -classpath <class search path of directories and zip/jar files> --class-path <class search path of directories and zip/jar files> A : separated list of directories, JAR archives, and ZIP archives to search for class files. -p <module path> --module-path <module path>... A : separated list of directories, each directory is a directory of modules. --upgrade-module-path <module path>... A : separated list of directories, each directory is a directory of modules that replace upgradeable modules in the runtime image --add-modules <module name>[,<module name>...] root modules to resolve in addition to the initial module. <module name> can also be ALL-DEFAULT, ALL-SYSTEM, ALL-MODULE-PATH. --enable-native-access <module name>[,<module name>...] modules that are permitted to perform restricted native operations. <module name> can also be ALL-UNNAMED. --list-modules list observable modules and exit -d <module name> --describe-module <module name> describe a module and exit --dry-run create VM and load main class but do not execute main method. The --dry-run option may be useful for validating the command-line options such as the module system configuration. --validate-modules validate all modules and exit The --validate-modules option may be useful for finding conflicts and other errors with modules on the module path. -D<name>=<value> set a system property -verbose:[class|module|gc|jni] enable verbose output for the given subsystem -version print product version to the error stream and exit --version print product version to the output stream and exit -showversion print product version to the error stream and continue --show-version print product version to the output stream and continue --show-module-resolution show module resolution output during startup -? -h -help print this help message to the error stream --help print this help message to the output stream -X print help on extra options to the error stream --help-extra print help on extra options to the output stream -ea[:<packagename>...|:<classname>] -enableassertions[:<packagename>...|:<classname>] enable assertions with specified granularity -da[:<packagename>...|:<classname>] -disableassertions[:<packagename>...|:<classname>] disable assertions with specified granularity -esa | -enablesystemassertions enable system assertions -dsa | -disablesystemassertions disable system assertions -agentlib:<libname>[=<options>] load native agent library <libname>, e.g. -agentlib:jdwp see also -agentlib:jdwp=help -agentpath:<pathname>[=<options>] load native agent library by full pathname -javaagent:<jarpath>[=<options>] load Java programming language agent, see java.lang.instrument -splash:<imagepath> show splash screen with specified image HiDPI scaled images are automatically supported and used if available. The unscaled image filename, e.g. image.ext, should always be passed as the argument to the -splash option. The most appropriate scaled image provided will be picked up automatically. See the SplashScreen API documentation for more information @argument files one or more argument files containing options -disable-@files prevent further argument file expansion --enable-preview allow classes to depend on preview features of this release To specify an argument for a long option, you can use --<name>=<value> or --<name> <value>.
上面的命令輸出的內(nèi)容還是有點(diǎn)多,不過你可以看到:
- 選項(xiàng)
-cp
是用來指定 Class Path 的 - 選項(xiàng)
-version
是用來輸出 Java 的版本信息的 - 通過
-D
可以設(shè)置系統(tǒng)屬性 -X
可以輸出有關(guān)非標(biāo)準(zhǔn)選項(xiàng)(額外選項(xiàng))的幫助信息- ……
看到?jīng)]有,我們前面提到的 -D
和 -X
都出現(xiàn)了。并且 Java 告訴我們, -D
是 JVM 的標(biāo)準(zhǔn)選項(xiàng)。
Java 允許我們以 -D<name>=<value>
這種鍵值對的形式設(shè)置系統(tǒng)屬性,例如:-Duser=Alice
就設(shè)置了簡單的系統(tǒng)屬性,它的鍵為 user
,值為 Alice
。隨后,我們就可以在程序中檢索出 user
的值:
System.getProperty("user"); //Alice
此外,我們也可以通過代碼覆蓋這個屬性的值:
System.setProperty("user", "Bob");
現(xiàn)在大家應(yīng)該明白 -D
的用途了吧:-D
是 JVM 的標(biāo)準(zhǔn)選項(xiàng),我們可以通過它設(shè)置系統(tǒng)屬性。
非標(biāo)準(zhǔn)選項(xiàng)
和標(biāo)準(zhǔn)選項(xiàng)類似,我們也可以直接通過 java
命令獲取 JVM 支持的所有非標(biāo)準(zhǔn)選項(xiàng)。
$ java -X -Xbatch disable background compilation -Xbootclasspath/a:<directories and zip/jar files separated by :> append to end of bootstrap class path -Xcheck:jni perform additional checks for JNI functions -Xcomp forces compilation of methods on first invocation -Xdebug does nothing. Provided for backward compatibility. -Xdiag show additional diagnostic messages -Xfuture enable strictest checks, anticipating future default. This option is deprecated and may be removed in a future release. -Xint interpreted mode execution only -Xinternalversion displays more detailed JVM version information than the -version option -Xlog:<opts> Configure or enable logging with the Java Virtual Machine (JVM) unified logging framework. Use -Xlog:help for details. -Xloggc:<file> log GC status to a file with time stamps. This option is deprecated and may be removed in a future release. It is replaced by -Xlog:gc:<file>. -Xmixed mixed mode execution (default) -Xmn<size> sets the initial and maximum size (in bytes) of the heap for the young generation (nursery) -Xms<size> set initial Java heap size -Xmx<size> set maximum Java heap size -Xnoclassgc disable class garbage collection -Xrs reduce use of OS signals by Java/VM (see documentation) -Xshare:auto use shared class data if possible (default) -Xshare:off do not attempt to use shared class data -Xshare:on require using shared class data, otherwise fail. This is a testing option and may lead to intermittent failures. It should not be used in production environments. -XshowSettings show all settings and continue -XshowSettings:all show all settings and continue -XshowSettings:locale show all locale related settings and continue -XshowSettings:properties show all property settings and continue -XshowSettings:vm show all vm related settings and continue -XshowSettings:system (Linux Only) show host system or container configuration and continue -Xss<size> set java thread stack size -Xverify sets the mode of the bytecode verifier Note that option -Xverify:none is deprecated and may be removed in a future release. --add-reads <module>=<target-module>(,<target-module>)* updates <module> to read <target-module>, regardless of module declaration. <target-module> can be ALL-UNNAMED to read all unnamed modules. --add-exports <module>/<package>=<target-module>(,<target-module>)* updates <module> to export <package> to <target-module>, regardless of module declaration. <target-module> can be ALL-UNNAMED to export to all unnamed modules. --add-opens <module>/<package>=<target-module>(,<target-module>)* updates <module> to open <package> to <target-module>, regardless of module declaration. --limit-modules <module name>[,<module name>...] limit the universe of observable modules --patch-module <module>=<file>(:<file>)* override or augment a module with classes and resources in JAR files or directories. --source <version> set the version of the source in source-file mode. These extra options are subject to change without notice.
-X
開頭的選項(xiàng)屬于非標(biāo)準(zhǔn)選項(xiàng)。很多小伙伴應(yīng)該能從上面的輸出內(nèi)容中看到兩個頗為熟悉的選項(xiàng):-Xms<size>
和 -Xmx<size>
。這兩個參數(shù)是用來設(shè)置 JVM 堆大小的,前者設(shè)置的是堆大小的初始值和最小值,而后者設(shè)置的是堆大小的最大值。例如 -Xms100m -Xmx1g
會在啟動 JVM 的時候?qū)⒍训某跏即笮≡O(shè)置為 100MB,允許堆最多使用 1GB 的內(nèi)存。
需要注意的是,上面輸出的這些非標(biāo)準(zhǔn)選項(xiàng)并不是所有 JVM 都支持,它們只是你機(jī)器上安裝的 JVM 所支持的一些通用選項(xiàng)。非標(biāo)準(zhǔn)選項(xiàng)的支持是與 JVM 的具體實(shí)現(xiàn)緊密相關(guān)的,并且這些非標(biāo)準(zhǔn)選項(xiàng)可能在不通知你的情況下悄悄地被改變。
高級選項(xiàng)
高級選項(xiàng)以 -XX
開頭,這些選項(xiàng)一般用于開發(fā)者調(diào)整 JVM 的行為、性能或輸出調(diào)試信息等。根據(jù)參數(shù)值類型的不同,高級選項(xiàng)又可以分為兩類:布爾類型的選項(xiàng)和帶參數(shù)的選項(xiàng)。
布爾選項(xiàng)
布爾類型的選項(xiàng)不帶參數(shù),只是一個開關(guān)。開關(guān)是不需要參數(shù)的,你可以通過 +
啟用某個功能(-XX:+Option
),而通過 -
禁用某個功能(-XX:-Option
)。例如,在 HotSpot JVM 中,你可以通過 -XX:+Inline
啟用方法內(nèi)聯(lián)。不過 HotSpot 為了提高性能,默認(rèn)是開啟了方法內(nèi)聯(lián)的,所以你可以通過 -XX:-Inline
關(guān)閉方法內(nèi)聯(lián)。
帶參選項(xiàng)
還有一類高級選項(xiàng)是需要設(shè)置相應(yīng)的參數(shù)值的,形式一般為:-XX:OptionName=OptionValue
。我們來看一些例子:
-XX:ErrorFile=file.log
告訴 JVM:當(dāng)不可恢復(fù)的錯誤發(fā)生時,將錯誤信息寫入file.log
這個文件。-XX:TreadStackSize=256k
將線程棧的大小設(shè)置為256k
。-XX:MaxHeapSize=1g
將堆的最大大小限制為1GB
,等價于-Xmx1g
。- ……
如何查看 JVM 的所有高級選項(xiàng)
這一部分涉及的命令適用于 HotSpot JVM,其它的 JVM 實(shí)現(xiàn)可能也支持相同或類似的功能。
JVM 可以自動根據(jù)機(jī)器的配置等信息調(diào)整一些選項(xiàng)的值,如果你想知道某些選項(xiàng)在 JVM 自動微調(diào)之前的初始值,那么你可以使用 -XX:+PrintFlagsInitial
。
如果你想知道某些選項(xiàng)在 JVM 中實(shí)際生效的值,你可以使用 -XX:+PrintFlagsFinal
。
如果你想知道哪些選項(xiàng)是被用戶或 JVM 特意設(shè)置過,你可以使用 -XX:+PrintCommandLineFlags
。
-XX:+PrintFlagsInitial
和 -XX:+PrintFlagsFinal
-XX:+PrintFlagsFinal
會打印出 JVM 最終在運(yùn)行 Java 代碼時采用的選項(xiàng)值,而 -XX:+PrintFlagsInitial
會打印出各個選項(xiàng)在 JVM 進(jìn)行微調(diào)之前的默認(rèn)值。 比較這兩個的輸出結(jié)果會非常有意思,你能學(xué)到 JVM 自動調(diào)整了哪些選項(xiàng)、你覆蓋了哪些選項(xiàng)、這些選項(xiàng)的類型是什么、值是多少、選項(xiàng)是否與特定的平臺有關(guān)等等。
我們先從 java -XX:+PrintFlagsFinal -version
開始。
$ java -XX:+PrintFlagsFinal -version [Global flags] // ... size_t AsyncLogBufferSize = 2097152 {product} {default} intx AutoBoxCacheMax = 128 {C2 product} {default} intx BCEATraceLevel = 0 {product} {default} bool BackgroundCompilation = true {pd product} {default} size_t BaseFootPrintEstimate = 268435456 {product} {default} intx BiasedLockingBulkRebiasThreshold = 20 {product} {default} intx BiasedLockingBulkRevokeThreshold = 40 {product} {default} intx BiasedLockingDecayTime = 25000 {product} {default} intx BiasedLockingStartupDelay = 0 {product} {default} // ... openjdk version "17.0.5" 2022-10-18 OpenJDK Runtime Environment (build 17.0.5+8-Ubuntu-2ubuntu120.04) OpenJDK 64-Bit Server VM (build 17.0.5+8-Ubuntu-2ubuntu120.04, mixed mode, sharing)
這條命令輸出的內(nèi)容非常多,有幾百行,所以我只截取了其中的一部分。命令輸出的第一行是 [Global flags]
,隨后的每一行都是 JVM 的一個配置項(xiàng),最后面的幾行是 JDK 的版本信息(也就是 java -version
的輸出內(nèi)容)。
第一行和最后三行之間的每一行都是一個選項(xiàng)。每個選項(xiàng)包含五列:
- 第一列是選項(xiàng)的類型,例如
intx
- 第二列是選項(xiàng)的名稱,例如
AsyncLogBufferSize
- 第三列是
=
。有些版本的 JDK 采用=
表示默認(rèn)值,:=
表示選項(xiàng)的值被覆蓋過。但是測試發(fā)現(xiàn) OpenJDK 17 已經(jīng)不會像之前的 JDK 版本那樣輸出:=
了。 - 第四列是選項(xiàng)的值
- 第五列是選項(xiàng)的類型。例如:
{product}
表示該配置項(xiàng)是產(chǎn)品自帶的(平臺無關(guān)的),{pd product}
表示該配置項(xiàng)是平臺相關(guān)的(platform-dependent),{manageable}
則表示配置項(xiàng)的值可以在運(yùn)行時被動態(tài)調(diào)整。 - 第六列表示第四列值的來源。例如:
{default}
表示選項(xiàng)目前是默認(rèn)值,{ergonomic}
表示該選項(xiàng)是 JVM 自動微調(diào)設(shè)置的,{command line}
表示該選項(xiàng)是通過命令行設(shè)置的。
$ java -XX:+PrintFlagsFinal -version | grep command bool PrintFlagsFinal = true {product} {command line}
其實(shí)還有第七列,但是由于我的 JVM 是產(chǎn)品版本的,沒有相關(guān)支持。只有 debug 版本的 JVM 才支持:
$ java -XX:+PrintFlagsWithComments -version Error: VM option 'PrintFlagsWithComments' is notproduct and is available only in debug version of VM. Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit.
相關(guān)細(xì)節(jié)可以在 JDK 的源碼 中找到。
-XX:+PrintFlagsInitial
:打印出各個 JVM 參數(shù)的默認(rèn)值。它的輸出內(nèi)容和 -XX:PrintFlagsFinal
類似。
在 OpenJDK 17 中,這兩個選項(xiàng)輸出行數(shù)是一樣的,都是 559 行:
$ java -XX:+PrintFlagsInitial -version | wc -l 559 $ java -XX:+PrintFlagsFinal -version | wc -l openjdk version "17.0.5" 2022-10-18 OpenJDK Runtime Environment (build 17.0.5+8-Ubuntu-2ubuntu120.04) OpenJDK 64-Bit Server VM (build 17.0.5+8-Ubuntu-2ubuntu120.04, mixed mode, sharing) 559
比較這兩個選項(xiàng)的輸出非常有趣,你可以使用:
$ diff <(java -XX:+PrintFlagsInitial -version) <(java -XX:+PrintFlagsFinal -version)
但這 559 個選項(xiàng)并不就是 HotSpot 支持的所有選項(xiàng),因?yàn)檫€有些選項(xiàng)是用于診斷虛擬機(jī)的,你可以使用 -XX:+UnlockDiagnosticVMOptions
:
$ java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version | wc -l openjdk version "17.0.5" 2022-10-18 OpenJDK Runtime Environment (build 17.0.5+8-Ubuntu-2ubuntu120.04) OpenJDK 64-Bit Server VM (build 17.0.5+8-Ubuntu-2ubuntu120.04, mixed mode, sharing) 771
還有些選項(xiàng)是實(shí)驗(yàn)性的,你可以使用 -XX:+UnlockExperimentalVMOptions
:
$ java -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+PrintFlagsFinal -version | w c -l openjdk version "17.0.5" 2022-10-18 OpenJDK Runtime Environment (build 17.0.5+8-Ubuntu-2ubuntu120.04) OpenJDK 64-Bit Server VM (build 17.0.5+8-Ubuntu-2ubuntu120.04, mixed mode, sharing) 891
891 個了!但這還不是全部!從 Java 9 開始,JVMCI 允許我們使用基于 Java 的編譯器接口:
$ java -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+JVMCIPrintProperties -XX:+EnableJVMCI -XX:+PrintFlagsFinal -version | wc -l 908
-XX:+PrintCommandLineFlags
-XX:+PrintCommandLineFlags
也是一個非常有用的參數(shù),它可以打印出那些我們通過命令行指定或者 JVM 自動在命令行上設(shè)置的參數(shù)。
java -XX:+PrintCommandLineFlags -version -XX:ConcGCThreads=2 -XX:G1ConcRefinementThreads=8 -XX:GCDrainStackTargetSize=64 -XX:InitialHeapSize=62422080 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=998753280 -XX:MinHeapSize=6815736 -XX:+PrintCommandLineFlags -XX:ReservedCodeCacheSize=251658240 -XX:+SegmentedCodeCache -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC openjdk version "17.0.5" 2022-10-18 OpenJDK Runtime Environment (build 17.0.5+8-Ubuntu-2ubuntu120.04) OpenJDK 64-Bit Server VM (build 17.0.5+8-Ubuntu-2ubuntu120.04, mixed mode, sharing)
總結(jié)
- JVM 包含多種不同類型的參數(shù)選項(xiàng)
-D
用來設(shè)置系統(tǒng)屬性,屬于標(biāo)準(zhǔn)選項(xiàng)-X
設(shè)置非標(biāo)準(zhǔn)選項(xiàng),支持的選項(xiàng)范圍跟具體的 JVM 實(shí)現(xiàn)有關(guān)-XX
設(shè)置高級選項(xiàng),允許開發(fā)者調(diào)整 JVM 的行為、性能、輸出調(diào)試信息,支持的選項(xiàng)范圍也跟具體的 JVM 實(shí)現(xiàn)有關(guān)- 布爾類型的高級選項(xiàng)是起到功能的開關(guān)作用,不帶參數(shù)。使用
+
啟用功能,使用-
禁用功能;對于帶參數(shù)的高級選項(xiàng),需要指定參數(shù)值 - 使用
java -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:+PrintFlagsFinal -version
命令可以查看 JVM 所有的選項(xiàng)
到此這篇關(guān)于JVM中-D、-X、-XX參數(shù)的區(qū)別的文章就介紹到這了,更多相關(guān)JVM -D -X -XX內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringSecurity 自定義表單登錄的實(shí)現(xiàn)
這篇文章主要介紹了SpringSecurity 自定義表單登錄的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01Java如何實(shí)現(xiàn)通過證書訪問Https請求
這篇文章主要介紹了Java如何實(shí)現(xiàn)通過證書訪問Https請求,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01maven一行命令引入第三方包打包的實(shí)現(xiàn)
在項(xiàng)目開發(fā)過程中,難免會用到第三方j(luò)ar的時候,本文主要介紹了maven一行命令引入第三方包打包的實(shí)現(xiàn),具有一定的參考價值,感興趣的可以了解一下2024-01-01SpringBoot實(shí)用小技巧之如何動態(tài)設(shè)置日志級別
這篇文章主要給大家介紹了關(guān)于SpringBoot實(shí)用小技巧之如何動態(tài)設(shè)置日志級別的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用SpringBoot具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04JVM分配和回收堆外內(nèi)存的方式與注意點(diǎn)
JVM啟動時分配的內(nèi)存稱為堆內(nèi)存,與之相對的,在代碼中還可以使用堆外內(nèi)存,比如Netty,廣泛使用了堆外內(nèi)存,下面這篇文章主要給大家介紹了關(guān)于JVM分配和回收堆外內(nèi)存的方式與注意點(diǎn),需要的朋友可以參考下2022-07-07SpringMVC HttpMessageConverter報文信息轉(zhuǎn)換器
??HttpMessageConverter???,報文信息轉(zhuǎn)換器,將請求報文轉(zhuǎn)換為Java對象,或?qū)ava對象轉(zhuǎn)換為響應(yīng)報文。???HttpMessageConverter???提供了兩個注解和兩個類型:??@RequestBody,@ResponseBody???,??RequestEntity,ResponseEntity??2023-01-01自定義JmsListenerContainerFactory時,containerFactory字段解讀
這篇文章主要介紹了自定義JmsListenerContainerFactory時,containerFactory字段解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07