Bootstrap

mac下使用arthas分析工具报错



依赖

在 JDK8 中,arthas-boot.jar 工具包的使用,需要依赖于 JDK 中的 tools.jar。
而 tools.jar 是存在于 JDK 的 lib 目录下的,在 JRE 的 lib 目录下不存在。

初次运行报错

初次运行 arthas 工具
如图所示,运行 arthas-boot.jar 会爆异常,表示找不到在 JAVA_HOME 指定的目录下找不到 tools.jar。
而 JAVA_HOME 指向的是:/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home

同时,使用 which java 获取的返回结果是:/usr/bin/java (留下一个问题:为什么是这个呢?)

好,现在开始逐一分析前置准备。

运行前的准备

需要先确定系统的环境变量中是否有我们自己安装的完整版 JDK 路径。
使用如下命令查看返回结果:

echo $JAVA_HOME

如果返回结果为空,说明我们系统的环境变量中并没有设置我们的 JDK 路径。
需要先设置 JDK 的完整路径。
如果有返回值,需要确定该返回值的指向位置,是完整版的 JDK,而不是瘦身版的 JRE(如何确定,继续往下看 ⬇️)。

因此,需要先确定我们的 JDK 的安装路径。可以使用如下命令:

/usr/libexec/java_home -V

返回的结果大致如下:

# 匹配到了两个 Java 虚拟机,说明有两个版本的虚拟机
Matching Java Virtual Machines (2):
	# 版本1
    1.8.411.09 (arm64) "Oracle Corporation" - "Java" /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home
    # 版本2
    1.8.0_411 (arm64) "Oracle Corporation" - "Java SE 8" /Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home
/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home

值得注意的是,必须要加参数 -V,才能打印出我们自己电脑系统中安装了的所有 JDK 版本的全部安装路径。
博主在这里就因为省略参数被坑了。(后面会分析)

对返回的结果进行分析,如下:

返回结果中列出了两种不同的 Java 虚拟机(JVM)版本,它们都属于 Oracle 的 Java 8(Java SE 8)。这些 JVM 版本分别位于不同的目录,表示系统上安装了两个不同的 Java 8 版本。


以下是每个 JVM 的详细信息:

  1. JVM 版本 1.8.411.09 (arm64) - 位于 /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home
  • 版本号:1.8.411.09
  • 体系结构:arm64
  • 供应商:Oracle Corporation
  • 安装位置:这个版本位于 /Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home,这是一个与 Java Applet 插件相关的路径,通常用于浏览器中的 Java 支持。这可能是一个与浏览器插件相关的 JRE(Java Runtime Environment),而不是一个完整的 JDK(Java Development Kit)。
  1. JVM 版本 1.8.0_411 (arm64) - 位于 /Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home
  • 版本号:1.8.0_411
  • 体系结构:arm64
  • 供应商:Oracle Corporation
  • 安装位置:这个版本位于 /Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home,是标准的 JDK(Java Development Kit)安装路径,适用于开发 Java 程序。这个版本包含 JDK 和 JRE,允许开发和运行 Java 应用程序。

/usr/libexec/java_home -V 返回结果解释:

  • 第一个版本JavaAppletPlugin.plugin)通常与浏览器插件有关,可能是为了支持在浏览器中运行 Java 小程序(applet)。这是一个轻量级的 JRE(Java 运行时环境),主要用于浏览器插件的目的。
  • 第二个版本jdk-1.8.jdk)是标准的 JDK 安装路径,通常用于开发 Java 应用程序。这个版本包含了编译器、调试工具和其他开发工具。

为什么有两个版本?

  • 不同的用途:第一个版本(位于 JavaAppletPlugin.plugin)是专门为浏览器支持 Java applet 提供的,而第二个版本(jdk-1.8.jdk)是完整的开发工具包,包含 JDK 和 JRE。
  • 路径和版本差异:两个版本的位置和版本号有所不同。第一个版本是旧的 JRE 安装路径,可能是通过浏览器插件安装的,而第二个版本是通过常规 JDK 安装过程安装的。

如果使用的是不带参数的命令:

# 请求
[MacBook-Pro ~ % /usr/libexec/java_home
# 响应
/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home

可以看到,如果不带 -V 参数的话,返回结果就只会显示第一条路径,而这个路径是 JRE 路径,不是 JDK 路径。

而开头我们提到了,arthas-boot.jar 的运行是需要依赖 tools.jar 的,但/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home 是 JRE,不包含 tools.jar 的,因此设置 JAVA_HOME 时不能设置为这个路径。

而在网上搜索设置 JAVA_HOME 的快捷配置时,就会有如下的设置:

export JAVA_HOME=$(/usr/libexec/java_home)
export PATH=$JAVA_HOME/bin:$PATH

很明显,它把/usr/libexec/java_home 的返回结果作为了 JAVA_HOME 的路径,但是我的系统中是有多个 JVM 版本的,而这个指令会获取到第一个 JVM 版本,也就是JavaAppletPlugin.plugin 的虚拟机路径,而这个只是个 JRE,不是完整的 JDK,因此 lib 目录下是不会有 tools.jar 的,最终就会报错。
解决方案是手动指定正确的、完整的 JDK 路径。

设置 JAVA_HOME / 如何选择要使用的 JVM:

如果开发环境中有多个 JVM 版本,可以通过设置环境变量 JAVA_HOME 来指定要使用的 JVM(在 mac 中,使用的是 zsh 终端【bash 终端需要更改指令】):

  1. 使用如下命令,打开配置文件
nano ~/.zshrc
  1. 在配置文件的末尾添加如下的两条配置
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home
export PATH=$JAVA_HOME/bin:$PATH

注:JAVA_HOME 的路径是要在上一步的指令返回结果中找到完整版的 JDK 路径

  1. 保存配置文件,并重新加载配置文件使更改生效
source ~/.zshrc
  1. 验证 JAVA_HOME 是否已存在
echo $JAVA_HOME

当输出结果不为空,且路径指向了 JDK 的路径时,证明我们的 JAVA_HOME 设置成功了,这样,系统会使用指定路径下的 JDK,而不是浏览器插件相关的 JRE。
此时我们再使用如下指令即可运行 arthas-boot.jar 工具包了。

java -jar arthas-boot.jar所在的位置

遗留的问题

在第二小节中,为什么我们没有设置 JAVA_HOME 的情况下,which java 却有返回值,且 java -version 等指令也可以执行呢?

其实从返回值中可以看出,返回的结果是:/usr/bin/java
而 /usr/bin/ 目录下的命令通常是全局可用的,我们在下载 JDK 并默认安装时,其实就会自动将基础指令添加进该目录中,其中就包括了 java、javac 等指令。

在设置完 JAVA_HOME 后,我们再次执行指令:

[MacBook-Pro ~ % which java
/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home/bin/java

可以看到,最新的 java 指令位置,已经指向了我们前面设置的 JDK 全路径位置了。

;