当你编写源代码时,你是在为人类编写可读的代码。计算机无法执行源代码,除非代码被编译成机器语言,这是一个通用术语,指特定机器所需的任何数量的语言。通常,如果你在 Linux 上编译代码,它就在 Linux 上运行,如果你在 Windows 上编译代码,它就在 Windows 上运行,等等。然而,Java 是不同的。它不针对实际的机器。它针对的是 Java 虚拟机 (JVM),因此它可以运行在任何机器上。
Java 源代码被编译成字节码,由安装在计算机上的 JVM 运行。JVM 是一个执行引擎,但通常你不会直接与之交互。它静默运行,处理 Java 字节码。大多数人不需要考虑甚至了解 JVM,但了解 JVM 的工作原理对于调试和优化 Java 代码可能很有用。例如
-
在生产环境中,你可能会发现已部署的应用程序需要性能提升。
-
如果在你编写的应用程序中出现问题,开发人员和最终用户都可以选择调试问题。
-
如果你想了解用于开发或运行 Java 应用程序的 Java 开发工具包 (JDK) 的详细信息,你可以通过查询 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。
要列出你的 Linux 系统上的 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 之间切换,再次运行该命令
$ sudo alternatives --config java
另一种选择是使用 SDKMan,它可以帮助你下载、更新和管理系统上的 JDK。
什么是 JVM 调优?
调优 JVM 是指调整 JVM 参数以提高 Java 应用程序的性能的过程。它也有助于诊断应用程序故障。
一般来说,在调优之前考虑以下几点很重要
-
成本:有时,改进运行代码的硬件可以提高应用程序的性能。这可能看起来像是一种“作弊”,但请考虑你愿意花多少时间来调优 JVM 参数。有时,应用程序需要更多内存才能达到预期的性能,而再多的软件技巧也无法改变这一点。
-
预期结果:从长远来看,稳定性比性能更重要。如果你的调优影响了稳定性,那么最好明智地选择你的调优参数。
-
底层问题:有时,问题可能是主机操作系统存在底层问题。在调优 JVM 之前,请确保 JVM 的平台运行正常。
-
内存泄漏:如果你发现自己正在使用垃圾回收 (GC) 调优参数,则很可能存在需要在应用程序代码中修复的内存泄漏。
JVM 参数的类型
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 实现都支持这些选项。
Microsoft 构建的 JVM 可能与 Red Hat 构建的 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 具有
$ cat Hello. java
public class Hello {
public static void main(String[] args) {
System.out.println("Inside Hello World!");
}
}
你可能面临的另一个常见问题是 OOM(内存溢出)错误,这可能在没有太多调试信息的情况下发生。要解决此类问题,你可以使用调试选项 -XX:+HeapDumpOnOutOfMemoryError,它会创建一个包含调试信息的 .hprof 文件。
$ 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)
有一些工具 可以查看此 .hprof 文件,以了解哪里出了问题。
结论
通过理解和使用 JVM 和 JVM 参数,开发人员和最终用户都可以诊断故障并提高 Java 应用程序的性能。下次你使用 Java 时,花点时间看看可用的选项。
评论已关闭。