通過理解和使用JVM和JVM參數(shù),開發(fā)人員和最終用戶都可以診斷故障并改進Java應(yīng)用程序的性能。
當你編寫源代碼時,你是在編寫供人類閱讀的代碼。在代碼被編譯成機器語言之前,計算機不能執(zhí)行源代碼。機器語言是一個通用術(shù)語,指的是特定機器所需的任意數(shù)量的語言。通常,如果在Linux上編譯代碼,它就在Linux上運行,如果在Windows上編譯代碼,它就在Windows上運行,以此類推。然而,Java是不同的。它并不以某種真正的機器為目標。它的目標是Java虛擬機(JVM),因此它可以在任何機器上運行。
Java源代碼被編譯成字節(jié)碼,由安裝在計算機上的JVM運行。JVM是一個執(zhí)行引擎,但它不是一個你通常直接與之交互的引擎。它安靜地運行,處理Java字節(jié)碼。大多數(shù)人不需要考慮甚至不需要了解JVM,但是了解JVM的工作原理對調(diào)試和優(yōu)化Java代碼是很有用的。例如:
- 生產(chǎn)環(huán)境中,你可能會發(fā)現(xiàn)已部署的應(yīng)用程序需要性能提升。
- 如果編寫的應(yīng)用程序出現(xiàn)問題,開發(fā)人員和最終用戶都可以選擇調(diào)試該問題。
- 你是否希望了解用于開發(fā)或運行Java應(yīng)用程序的Java開發(fā)工具包(JDK)的詳細信息,可以通過查詢JVM獲得這些詳細信息
本文介紹了一些基本的JVM參數(shù),希望可以在這些場景中提供幫助……
JVM、JDK和JRE之間的區(qū)別是什么?
Java有很多J首字母縮略詞,包括JVM、JDK和JRE。
- Java開發(fā)者工具包(JDK)可供需要在代碼中使用開發(fā)庫的程序員使用。
- Java運行時環(huán)境(JRE)是由想要運行Java應(yīng)用程序的人所使用的。
- Java虛擬機(JVM)是運行Java字節(jié)碼的組件。
JDK包含JRE和JVM,但是一些Java發(fā)行版提供了包含JRE(包括JVM)的替代下載。
Java是開源的,所以會有不同的公司構(gòu)建和發(fā)行不同版本的JDK。你可以在系統(tǒng)上安裝多個JDK,當你正在處理或使用不同的Java項目(其中一些可能使用舊的JDK)時,這會很有幫助。
要列出Linux系統(tǒng)上的JDK,你可以使用alternatives命令:
$ alternatives --config java
There are 2 programs that provide java.
Selection Command
-----------------------------------------------
*+ 1 java-11-openjdk.x86_64 (/usr/lib/jvm/java-11-openjdk-11.0.13.0.8-2.fc35.x86_64/bin/java)
2 java-1.8.0-openjdk.x86_64 (/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.312.b07-2.fc35.x86_64/jre/bin/java)
Enter to keep the current selection[+], or type selection number:
要在可用的JDK之間切換,請再次執(zhí)行以下命令:
$ sudo alternatives --config java
另一個選擇是使用SDKMan,它可以幫助你下載、更新和管理系統(tǒng)上的JDK。
什么是JVM調(diào)優(yōu)?
JVM調(diào)優(yōu)是調(diào)整JVM參數(shù)以提高Java應(yīng)用程序性能的過程。它還有助于診斷應(yīng)用程序故障。
一般來說,在調(diào)優(yōu)之前考慮這些要點是很重要的:
- 成本:有時候,改進運行代碼的硬件可以提高應(yīng)用程序的性能。這似乎是一種“欺騙”,但請考慮你愿意花多少時間來調(diào)優(yōu)JVM參數(shù)。有時,應(yīng)用程序需要更多的內(nèi)存來執(zhí)行所需的操作,任何軟件優(yōu)化都無法改變這一點。
- 預(yù)期結(jié)果:長期來看,穩(wěn)定比性能更重要。如果調(diào)優(yōu)影響穩(wěn)定性,那么明智地選擇調(diào)優(yōu)參數(shù)可能會更好。
- 底層問題:有時,問題可能是主機操作系統(tǒng)的底層問題。在調(diào)優(yōu)JVM之前,請確保JVM的平臺按預(yù)期工作。
- 內(nèi)存泄漏:如果你發(fā)現(xiàn)自己在使用垃圾收集(GC)調(diào)優(yōu)參數(shù),那么可能存在需要在應(yīng)用程序代碼中修復(fù)的內(nèi)存泄漏。
JVM參數(shù)類型
JVM參數(shù)分為三類:標準參數(shù)、非標準參數(shù)和高級選項。
標準參數(shù)
所有JVM實現(xiàn)都支持標準參數(shù)。在終端中運行'java'命令查看標準參數(shù)列表。
$ java
Usage: java [options] <mainclass> [args...]
To specify an argument for a long option, you can use --<name>=<value> or
--<name> <value>.
這些都是包含在任意JVM中的標準參數(shù),你可以在使用任何命令行選項時安全地使用它們。例如,為了驗證配置的命令參數(shù),創(chuàng)建一個VM并在不執(zhí)行主類的情況下加載一個主類,使用以下命令:
$ java --dry-run <classfile>
非標準參數(shù)
非標準參數(shù)以-X開頭。它們用于通用用途,并且特定于JVM的特定實現(xiàn)。列出這些選項:
$ java -X
-Xbatch disable background compilation
-Xbootclasspath/a:<directories and zip/jar files separated by :>
append to end of bootstrap class path
-Xinternalversion
displays more detailed JVM version information than the
-version option
-Xloggc:<file> log GC status to a file with time stamps
[...]
這些額外的參數(shù)可以在沒有通知的情況下更改,并且不是所有的JVM實現(xiàn)都支持這些參數(shù)。由Microsoft構(gòu)建的JVM可能與由Red Hat構(gòu)建的JVM有不同的參數(shù),等等。
要獲取詳細的JVM版本信息,請使用以下命令:
$ java -Xinternalversion --version
OpenJDK 64-Bit Server VM (11.0.13+8) for linux-amd64 JRE (11.0.13+8), built on Nov 8 2021 00:00:00 by "mockbuild" with gcc 11.2.1 20210728 (Red Hat 11.2.1-1)
要獲取屬性設(shè)置,請使用:
java -XshowSettings:properties --version
高級選項
這些選項不是臨時使用的,而是用于調(diào)整Hotspot VM的特定區(qū)域。這些參數(shù)可能會發(fā)生變化,并且不能保證所有JVM實現(xiàn)都會支持它。
這些參數(shù)以-XX開頭。要列出這些參數(shù),請使用以下命令:
$ java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version
例如,要跟蹤類的加載,可以使用下面的命令:
$ java -XX:+TraceClassLoading Hello
Hello.java如下:
$ cat Hello. java
public class Hello {
}
你可能面臨的另一個常見問題是OOM(內(nèi)存不足)錯誤,這可能在沒有太多調(diào)試信息的情況下發(fā)生。要解決這樣的問題,你可以使用調(diào)試選項 -XX:+HeapDumpOnOutOfMemoryError,它會創(chuàng)建一個包含調(diào)試信息的.hprof文件。
$ cat TestClass. java
import java.util.ArrayList;
import java.util.List;
public class TestClass {
}
$ Javac TestClass.java
$ java -XX:+HeapDumpOnOutOfMemoryError -Xms10m -Xmx1g TestClass
java.lang.OutOfMemoryError: java heap space
Dumping heap to java_pid444496.hprof ...
Heap dump file created [1018925828 bytes in 1.442 secs]
Exception in thread "main" java.lang.OutOfMemoryError: java heap space
at TestClass.main(TestClass.Java:8)
有一些工具可以查看這個.hprof文件,以了解哪里出了問題。
結(jié)語
通過理解和使用JVM和JVM參數(shù),開發(fā)人員和最終用戶都可以診斷故障并改進Java應(yīng)用程序的性能。下次使用Java時,可以花些時間看看可供選擇的選項。
譯者介紹
盧鑫旺,51CTO社區(qū)編輯,半路出家的九零后程序員。做過前端頁面,寫過業(yè)務(wù)接口,搞過爬蟲,研究過JS,有幸接觸Golang,參與微服務(wù)架構(gòu)轉(zhuǎn)型。目前主寫Java,負責公司可定制化低代碼平臺的數(shù)據(jù)引擎層設(shè)計開發(fā)工作。
原文標題:??A guide to JVM parameters for Java developers??,作者:Jayashree Huttanagoudar