面向 Java 開發人員的 JVM 參數指南
當你在編寫源代碼時,你是在編寫人類可以閱讀的代碼。在將代碼編譯成機器語言之前,計算機無法執行它。機器語言是一個通用術語,指的是特定機器所需的任意數量的語言。通常,如果你在 Linux 上編譯代碼,它只能 Linux 上運行;如果你在 Windows 上編譯代碼,它就只在 Windows 上運行。但是,Java 是不同的,它並不以真實的機器為目標,而是面向 Java 虛擬機 (JVM)。因此,它可以在任何機器上運行。
Java 源代碼被編譯成 位元組碼 ,然後由安裝在計算機上的 JVM 運行。JVM 是一個執行引擎,但我們通常不會直接與它交互。它在後台靜默運行,替我們處理 Java 位元組碼。大多數人不需要考慮,甚至也不需要知道 JVM。但是,了解它的工作原理是對我們來說是非常有用的,因為這會有助於我們調試和優化 Java 代碼。例如:
- 在生產環境中,你發現已經部署的應用程序可能需要提升性能。
- 如果你寫的應用程序出錯了,開發人員和最終用戶都可以選擇對問題進行調試。
- 如果你想了解關於 JDK(即 Java 開發工具包 ,用於開發/運行 Java 應用程序)的詳細信息,你可以通過查詢 JVM 來獲取。
本文介紹了一些基礎的 JVM 參數,希望在這些場景中可以提供幫助。
(圖源:Jayashree Huttanagoudar,CC BY-SA 4.0)
JVM、JDK 和 JRE 有什麼不同?
Java 有許多 J 開頭的縮略詞,包括 JVM、JDK 和 JRE。
- Java 開發工具包 (JDK)可供需要在代碼中使用開發庫的程序員使用。
- Java 運行時環境 (JRE)可供想運行 Java 應用程序的人使用。
- Java 虛擬機 (JVM)是運行 Java 位元組碼的組件。
JDK 同時包含 JRE 和 JVM,但有些 Java 發行版提供了包含 JRE(包括 JVM)的替代下載。
(圖源:Jayashree Huttanagoudar,CC BY-SA 4.0)
Java 是開源的,因此,許多不同的公司都會構建和發行他們自己的 JDK 發行版。你可以在系統上安裝多個 JDK,這會對你參與或者運行不同的 Java 項目時很有幫助,因為其中一些項目可能使用舊版本的 JDK。
你可以使用 alternatives
命令,來查看 Linux 系統上的 JDK 列表:
$ 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 之間進行切換,請再次執行該命令:
$ sudo alternatives --config java
或者可以使用 SDKMan,它可以下載、更新和管理系統中的所有 JDK。
什麼是 JVM 調優?
JVM 調優指的是,通過調整 JVM 參數,來提高 Java 應用程序性能的過程,它還有助於診斷應用程序的故障。
通常情況下,在調試之前需要考慮以下幾點:
- 成本:有時改進運行代碼的硬體可以提高應用程序的性能。這可能看起來像是在「作弊」,但請考慮你願意花多少時間調整 JVM 參數。有時應用程序需要更多的內存來執行所需的功能,而這點是任何軟體技術都無法改變的。
- 期望結果:長期來看,穩定性比性能更重要。如果你的調優對穩定性產生了影響,那麼謹慎地選擇你的調優參數可能會更好。
- 底層問題:有時,問題可能是主機操作系統的底層問題。那麼,在調整 JVM 之前,請確保 JVM 平台按預期工作。
- 內存泄漏:如果你在使用垃圾回收(GC)調優參數,那麼,應用程序代碼中很可能會存在需要修復的內存泄漏。
參數類型
JVM 參數可以分為以下三類:標準參數、非標準參數和高級選項。
標準參數
所有的 JVM 實現都支持標準參數,在終端執行 java
命令來查看標準參數列表:
$ java
Usage: java [options] <mainclass> [args...]
(to execute a class)
or java [options] -jar <jarfile> [args...]
(to execute a jar file)
where options include:
-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.
--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>.
這些是所有 JVM 都會包含的標準參數,你可以像使用任何 命令行選項 一樣安全地使用它們。例如,要驗證配置的命令選項,創建 VM 並載入主類而不執行主類,請使用:
$ java --dry-run <classfile>
非標準參數
非標準選項以 -X
開頭。這些是通用的,並且特定於 JVM 的特定實現。要列出這些參數,請輸入:
$ 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
[...]
在這些參數可能會不經通知就發生變化。而且,並非所有 JVM 實現都支持這些參數。
微軟構建的 JVM 可能與 RedHat 構建的 JVM 有不同的參數,諸如此類。
要獲取詳細的 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)
要獲取這些屬性設置,請使用:
$ java -XshowSettings:properties --version
高級選項
這些參數不是隨意使用的,而是用於調整 Hotspot VM 的特定區域。這些參數可能會發生變化,並且不能保證得到所有 JVM 實現的支持。
這些參數以 -XX
開頭。如需列出參數列表,使用如下命令:
$ java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version
例如,需要跟蹤類的載入,那麼使用下面的命令:
$ java -XX:+TraceClassLoading Hello
在 Hello.java
中:
public class Hello {
public static void main(String[] args) {
System.out.println("Inside Hello World!");
}
}
另一個可能會面臨的問題是 OOM( 內存超出 )錯誤,它發生的時候可能沒有太多的調試信息。為了解決這個問題,使用調試參數 -XX:+HeapDumpOnOutOfMemoryError
,它可以創建一個帶有調試信息的 .hprof
文件。
// TestClass.java
import java.util.ArrayList;
import java.util.List;
public class TestClass {
public static void main(String[] args) {
List<Object> list = new ArrayList<Object>();
for (int i = 0; i < 1000; i++) {
list.add(new char[1000000]);
}
}
}
$ 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
文件以了解問題所在。
總結
通過了解和使用 JVM 以及 JVM 參數,開發人員和終端用戶都可以診斷故障並提高 Java 應用程序的性能。下次使用 Java 時,請花點時間看看有哪些參數可以用吧!
(題圖由 Seksak Kerdkanno 在 Pixabay 上發布 )
via: https://opensource.com/article/22/4/jvm-parameters-java-developers
作者:Jayashree Huttanagoudar 選題:lkxed 譯者:Veryzzj 校對:wxy
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive