面向 Java 开发人员的 JVM 参数指南
JVM Java
![](/data/attachment/album/202205/06/134624iiubdjkqmxaaqhmx.jpg)



> 
> 通过理解和使用 JVM 以及 JVM 参数，开发人员和最终用户都可以诊断故障并且提高 Java 应用程序的性能。
> 
> 
> 


当你在编写源代码时，你是在编写人类可以阅读的代码。在将代码编译成机器语言之前，计算机无法执行它。机器语言是一个通用术语，指的是特定机器所需的任意数量的语言。通常，如果你在 Linux 上编译代码，它只能 Linux 上运行；如果你在 Windows 上编译代码，它就只在 Windows 上运行。但是，Java 是不同的，它并不以真实的机器为目标，而是面向 <ruby> Java 虚拟机 <rt>  Java Virtual Machine </rt></ruby>（JVM）。因此，它可以在任何机器上运行。


Java 源代码被编译成<ruby> 字节码 <rt>  bytecode </rt></ruby>，然后由安装在计算机上的 JVM 运行。JVM 是一个执行引擎，但我们通常不会直接与它交互。它在后台静默运行，替我们处理 Java 字节码。大多数人不需要考虑，甚至也不需要知道 JVM。但是，了解它的工作原理是对我们来说是非常有用的，因为这会有助于我们调试和优化 Java 代码。例如：


* 在生产环境中，你发现已经部署的应用程序可能需要提升性能。
* 如果你写的应用程序出错了，开发人员和最终用户都可以选择对问题进行调试。
* 如果你想了解关于 JDK（即 <ruby> Java 开发工具包 <rt>  Java Development Kit </rt></ruby>，用于开发/运行 Java 应用程序）的详细信息，你可以通过查询 JVM 来获取。


本文介绍了一些基础的 JVM 参数，希望在这些场景中可以提供帮助。


![JVM 参数](/data/attachment/album/202205/06/134703i1xjwxj1xkskxj13.jpg)


（图源：Jayashree Huttanagoudar，CC BY-SA 4.0）


### JVM、JDK 和 JRE 有什么不同？


Java 有许多 J 开头的缩略词，包括 JVM、JDK 和 JRE。


* <ruby> Java 开发工具包 <rt>  Java Development Kit </rt></ruby>（JDK）可供需要在代码中使用开发库的程序员使用。
* <ruby> Java 运行时环境 <rt>  Java Runtime Environment </rt></ruby>（JRE）可供想运行 Java 应用程序的人使用。
* <ruby> Java 虚拟机 <rt>  Java Virtual Machine </rt></ruby>（JVM）是运行 Java 字节码的组件。


JDK 同时包含 JRE 和 JVM，但有些 Java 发行版提供了包含 JRE（包括 JVM）的替代下载。


![JDK](/data/attachment/album/202205/06/134703nbozba6zlql7wyob.jpg)


（图源：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](https://opensource.com/%5Bhttps%3A//opensource.com/article/22/3/manage-java-versions-sdkman%5D%28https%3A//opensource.com/article/22/3/manage-java-versions-sdkman%29)，它可以下载、更新和管理系统中的所有 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 都会包含的标准参数，你可以像使用任何 [命令行选项](https://opensource.com/%5Bhttps%3A//opensource.com/article/21/8/linux-terminal%5D%28https%3A//opensource.com/article/21/8/linux-terminal%29) 一样安全地使用它们。例如，要验证配置的命令选项，创建 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（<ruby> 内存超出 <rt>  Out Of Memory </rt></ruby>）错误，它发生的时候可能没有太多的调试信息。为了解决这个问题，使用调试参数 `-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)

```

[有一些工具](https://opensource.com/%5Bhttps%3A//docs.oracle.com/javase/7/docs/technotes/tools/share/jhat.html%5D%28https%3A//docs.oracle.com/javase/7/docs/technotes/tools/share/jhat.html%29) 可以查看这个 `.hprof` 文件以了解问题所在。


### 总结


通过了解和使用 JVM 以及 JVM 参数，开发人员和终端用户都可以诊断故障并提高 Java 应用程序的性能。下次使用 Java 时，请花点时间看看有哪些参数可以用吧！


（题图由 [Seksak Kerdkanno](https://pixabay.com/zh/users/kerdkanno-1334070/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=5959810) 在 [Pixabay](https://pixabay.com/zh/?utm_source=link-attribution&utm_medium=referral&utm_campaign=image&utm_content=5959810) 上发布 ）




---


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


作者：[Jayashree Huttanagoudar](https://opensource.com/users/jayashree-huttanagoudar) 选题：[lkxed](https://github.com/lkxed) 译者：[Veryzzj](https://github.com/Veryzzj) 校对：[wxy](https://github.com/wxy)


本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译，[Linux中国](https://linux.cn/) 荣誉推出


OK
When you write source code, you're writing code for humans to read. Computers can't execute source code until the code is compiled into *machine language*, a generic term referring to any number of languages required by a specific machine. Normally, if you compile code on Linux, it runs on Linux, and if you compile code on Windows, it runs on Windows, and so on. However, Java is different. It doesn't target an actual machine. It targets something called the Java Virtual Machine (JVM), and so it can run on any machine.


Java source code gets compiled into bytecode which is run by a JVM installed on a computer. The JVM is an execution engine, but it's not one you usually interact with directly. It runs quietly, processing Java bytecode. Most people don't need to think or even know about the JVM, but it can be useful to understand how the JVM works so you can debug and optimize Java code. For example:

-
In the production environment, you might find a deployed application needs a performance boost.

-
If something goes wrong in an application you've written, both the developer and end-user have options to debug the problem.

-
Should you want to know the details of the Java Development Kit (JDK) being used to develop or run a Java application, you can get those details by querying the JVM.


This article introduces some basic JVM parameters to help in these scenarios…

![Jvm parameters](https://opensource.com/sites/default/files/2022-03/java-jvm-parameters.jpg)

(Jayashree Huttanagoudar CC BY-SA 4.0)

## What's the difference between a JVM, JDK, and JRE?

Java has a lot of J-acronyms, including JVM, JDK, and JRE.

-
A Java Developer Kit (JDK) is accessed by programmers who need development libraries to use in their code.

-
The Java Runtime Environment (JRE) is employed by people who want to run a Java application.

-
The Java Virtual Machine (JVM) is the component that runs Java bytecode.


The JDK contains both a JRE and a JVM, but some Java distributions provide an alternate download containing a JRE (including a JVM).

![JDK](https://opensource.com/sites/default/files/2022-03/jdk.jpg)

(Jayashree Huttanagoudar CC BY-SA 4.0)

Java is open source, so different companies build and distribute JDKs. You can install more than one on your system, which can be helpful when you're working on or using different Java projects, some of which might use an old JDK.

To list the JDKs on your Linux system, you can use the alternatives command:

```
``````
$ 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:
```


To switch between available JDKs, run the command again:

```
````$ sudo alternatives --config java`


Another option is to use [SDKMan](https://opensource.com/%5Bhttps%3A//opensource.com/article/22/3/manage-java-versions-sdkman%5D%28https%3A//opensource.com/article/22/3/manage-java-versions-sdkman%29), which helps you download, update, and manage the JDKs on your system.

## What is JVM tuning?

Tuning a JVM is the process of adjusting JVM parameters to improve the performance of the Java application. It also helps to diagnose application failure.

In general, it's important to consider these points before tuning:

-
**Cost**: Sometimes, improving the hardware running your code can improve an application's performance. That might seem like a "cheat" but consider how much time you're willing to spend tuning the JVM parameters. Sometimes, an application requires more memory to perform as desired, and no amount of software hacking will change that. -
**Desired Outcome**: Stability is more important than performance in the long run. If your tuning affects the stability, it's probably better to wisely choose your tuning parameters. -
**Underlying issues**: Sometimes, the issue could be an underlying issue with the host operating system. Before tuning the JVM, ensure that the JVM's platform is working as expected. -
**Memory leaks**: If you find yourself using Garbage Collection (GC) tuning parameters, there are likely memory leaks that need to get fixed in the application code.

## Types of JVM Parameters

JVM parameters are grouped under three categories: Standard options, Non-standard, and Advanced.

### Standard options

All JVM implementations support standard options. Run the 'java' command in a terminal to see a list of standard options.

```
``````
$ 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>.
```


These are all standard options included with any JVM, and you can safely use them as you use any [command-line option](https://opensource.com/%5Bhttps%3A//opensource.com/article/21/8/linux-terminal%5D%28https%3A//opensource.com/article/21/8/linux-terminal%29). For example, to validate command options for configuration, and create a VM and load a main class without executing the main class, use:

```
````$ java --dry-run <classfile>`


### Non-standard options

Non-standard options start with `-X`

. These are for general purpose use and are specific to a particular implementation of JVM. To list these options:


```
``````
$ 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
[...]
```


These extra options are subject to change without notice and are not supported by all JVM implementations.

A JVM built by Microsoft may have different options than one built by Red Hat, and so on.

To get detailed JVM version information, use the following option:


```
``````
$ 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)
```


To get the property setting use:

```
````$ java -XshowSettings:properties --version`


### Advanced options

These options are not for casual use and are used for tuning the specific areas of the Hotspot VM. These options are subject to change, and there is no guarantee that all JVM implementations will support it.

These options start with -XX. To list these options, use the following command:

```
````$ java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version`


For example, to trace the class loading then use the below command:

```
````$ java -XX:+TraceClassLoading Hello`


The Hello.java has:

```
``````
$ cat Hello. java
public class Hello {
public static void main(String[] args) {
System.out.println("Inside Hello World!");
}
}
```


Another common problem you might face is OOM (Out Of Memory) errors, which can happen without much debug information. To solve such a problem, you might use the debug option -XX:+HeapDumpOnOutOfMemoryError, which creates a .hprof file with debug information.


```
``````
$ cat 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)
```


[There are tools](https://opensource.com/%5Bhttps%3A//docs.oracle.com/javase/7/docs/technotes/tools/share/jhat.html%5D%28https%3A//docs.oracle.com/javase/7/docs/technotes/tools/share/jhat.html%29) to look at this .hprof file to understand what went wrong.

## Conclusion

By understanding and using JVM and JVM parameters, both developers and end users can diagnose failures and improve the performance of a Java application. The next time you're working with Java, take a moment to look at the options available to you.

## Comments are closed.