Linux中國

面向 Java 開發人員的 JVM 參數指南

通過理解和使用 JVM 以及 JVM 參數,開發人員和最終用戶都可以診斷故障並且提高 Java 應用程序的性能。

當你在編寫源代碼時,你是在編寫人類可以閱讀的代碼。在將代碼編譯成機器語言之前,計算機無法執行它。機器語言是一個通用術語,指的是特定機器所需的任意數量的語言。通常,如果你在 Linux 上編譯代碼,它只能 Linux 上運行;如果你在 Windows 上編譯代碼,它就只在 Windows 上運行。但是,Java 是不同的,它並不以真實的機器為目標,而是面向 Java 虛擬機 Java Virtual Machine JVM)。因此,它可以在任何機器上運行。

Java 源代碼被編譯成 位元組碼 bytecode ,然後由安裝在計算機上的 JVM 運行。JVM 是一個執行引擎,但我們通常不會直接與它交互。它在後台靜默運行,替我們處理 Java 位元組碼。大多數人不需要考慮,甚至也不需要知道 JVM。但是,了解它的工作原理是對我們來說是非常有用的,因為這會有助於我們調試和優化 Java 代碼。例如:

  • 在生產環境中,你發現已經部署的應用程序可能需要提升性能。
  • 如果你寫的應用程序出錯了,開發人員和最終用戶都可以選擇對問題進行調試。
  • 如果你想了解關於 JDK(即 Java 開發工具包 Java Development Kit ,用於開發/運行 Java 應用程序)的詳細信息,你可以通過查詢 JVM 來獲取。

本文介紹了一些基礎的 JVM 參數,希望在這些場景中可以提供幫助。

JVM 參數

(圖源:Jayashree Huttanagoudar,CC BY-SA 4.0)

JVM、JDK 和 JRE 有什麼不同?

Java 有許多 J 開頭的縮略詞,包括 JVM、JDK 和 JRE。

  • Java 開發工具包 Java Development Kit (JDK)可供需要在代碼中使用開發庫的程序員使用。
  • Java 運行時環境 Java Runtime Environment (JRE)可供想運行 Java 應用程序的人使用。
  • Java 虛擬機 Java Virtual Machine (JVM)是運行 Java 位元組碼的組件。

JDK 同時包含 JRE 和 JVM,但有些 Java 發行版提供了包含 JRE(包括 JVM)的替代下載。

JDK

(圖源: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( 內存超出 Out Of Memory )錯誤,它發生的時候可能沒有太多的調試信息。為了解決這個問題,使用調試參數 -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 KerdkannoPixabay 上發布 )

via: https://opensource.com/article/22/4/jvm-parameters-java-developers

作者:Jayashree Huttanagoudar 選題:lkxed 譯者:Veryzzj 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的電子郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國