要分析JVM,必须将JProfiler的分析代理加载到JVM中。这可以通过两种不同的方式实现:
在启动脚本中指定-agentpath
VM参数,或者使用attach API将代理加载到已经运行的JVM中。
JProfiler支持这两种模式。添加VM参数是首选的分析方式,并且被集成向导、IDE插件和从JProfiler内部启动JVM的会话配置所使用。 附加既可以在本地进行,也可以通过SSH远程进行。
-agentpath VM参数
理解加载分析代理的VM参数的组成是有用的。-agentpath
是JVM提供的一个通用VM参数,用于加载使用JVMTI接口的任何类型的本地库。
由于分析接口JVMTI是一个本地接口,因此分析代理必须是一个本地库。这意味着您只能在
明确支持的平台上进行分析。
32位和64位JVM也需要不同的本地库。
另一方面,Java代理是通过-javaagent
VM参数加载的,并且只能访问有限的功能集。
在-agentpath:
之后,附加本地库的完整路径名。还有一个等效的参数-agentlib:
,
其中您只需指定平台特定的库名称,但随后您必须确保库包含在库路径中。在库路径之后,您可以添加等号并将选项传递给代理,选项之间用逗号分隔。
例如,在Linux上,整个参数可能如下所示:
-agentpath:/opt/jprofiler15/bin/linux-x64/libjprofilerti.so=port=8849,nowait
第一个等号将路径名与参数分开,第二个等号是参数port=8849
的一部分。这个常见参数定义了分析代理监听
JProfiler GUI连接的端口。8849实际上是默认端口,因此您也可以省略该参数。
如果您想在同一台机器上分析多个JVM,则必须分配不同的端口。
IDE插件和本地启动的会话会自动分配此端口,对于集成向导,您必须明确选择端口。
第二个参数nowait
告诉分析代理不要在启动时阻塞JVM并等待JProfiler GUI连接。
启动时阻塞是默认设置,因为分析代理不会通过命令行参数接收其分析设置,而是通过JProfiler GUI或配置文件接收。
命令行参数仅用于引导分析代理,告诉它如何开始并传递调试标志。
在某些情况下,在启动时设置分析设置 是必需的,并且可能需要一些手动工作来实现这一点。
默认情况下,JProfiler代理将通信socket绑定到回环接口。您可以添加选项address=[IP地址]
以选择特定接口,
或者address=0.0.0.0
以将通信socket绑定到所有可用的网络接口。
如果您想从docker容器发布分析端口,这可能是必要的。
本地启动的会话
像IDE中的“运行配置”一样,您可以直接在JProfiler中配置本地启动的会话。您指定类路径、主类、工作目录、VM参数和参数, JProfiler为您启动会话。所有随JProfiler一起提供的演示会话都是本地启动的会话。
一种特殊的启动模式是“Web Start”,您可以选择JNLP文件的URL,JProfiler将启动一个JVM来分析它。 此功能支持OpenWebStart,不支持Java 9之前Oracle JREs的旧版WebStart。
本地启动的会话可以通过调用主菜单中的Session→Conversion Wizards将其转换为独立会话。
Convert Application Session to Remote只是创建一个启动脚本,并将-agentpath
VM参数插入到Java调用中。
Convert Application Session to Offline为离线分析创建一个启动脚本,
这意味着配置在启动时加载,并且不需要JProfiler GUI。
Convert Application Session to Redistributed Session做同样的事情,但在其旁边创建一个目录
jprofiler_redist
,其中包含分析代理和配置文件,以便您可以将其发送到未安装JProfiler的其他机器。
如果您自己开发被分析的应用程序,请考虑使用IDE集成而不是启动会话。 这将更方便,并为您提供更好的源代码导航。如果您不是自己开发应用程序,但已经有一个启动脚本,请考虑使用远程集成向导。 它会告诉您必须添加到Java调用中的确切VM参数。
集成向导
JProfiler的集成向导处理许多知名的第三方容器,这些容器具有可以通过编程方式修改的启动脚本或配置文件,以包含额外的VM参数。 对于某些产品,可以生成启动脚本,其中VM参数作为参数或通过环境变量传递。
在所有情况下,您都必须从第三方产品中定位一些特定文件,以便JProfiler具有执行其修改所需的上下文。 一些通用向导只会给您指示,告诉您为了启用分析需要做什么。
每个集成向导的第一步是选择是在本地机器上分析还是在远程机器上分析。 在本地机器的情况下,您需要提供较少的信息,因为JProfiler已经知道平台、JProfiler安装的位置以及其配置文件的位置。
一个重要的决定是上面讨论的“启动模式”。默认情况下,分析设置在启动时从JProfiler UI传输,但您也可以告诉分析代理立即启动JVM。 在后一种情况下,分析设置可以在JProfiler GUI连接后应用。
然而,您也可以指定一个包含分析设置的配置文件,这样效率更高。 这是在Config synchronization步骤中完成的。在这种情况下,主要问题是每次在本地编辑分析设置时,您必须与远程端同步配置文件。 最优雅的方法是在Remote address步骤中通过SSH连接到远程机器,然后可以通过SSH自动传输配置文件。
在集成向导的最后,将创建一个会话来启动分析,并且在非通用情况下,还会启动第三方产品,例如应用服务器。
外部启动脚本由会话配置对话框的Application settings选项卡上的Execute start script和Execute stop script 选项处理,并且可以通过选择Open browser with URL复选框来显示URL。这也是您可以更改远程机器地址和配置同步选项的地方。
所有集成向导都处理被分析的JVM在远程机器上运行的情况。然而,当必须修改配置文件或启动脚本时,您必须将其复制到本地机器,
并将修改后的版本传输回远程机器。直接在远程机器上运行命令行工具 jpintegrate
并让它就地执行修改可能更方便。
jpintegrate
需要完整安装JProfiler,并具有与JProfiler GUI相同的JRE要求。
当在启动远程分析会话时发生错误时,请参阅 故障排除指南以获取可以采取的步骤清单来解决问题。
IDE集成
通过IDE集成分析应用程序是最方便的方法。如果您在开发过程中通常从IDE启动应用程序,IDE已经拥有所有必需的信息, JProfiler插件可以简单地添加用于分析的VM参数,必要时启动JProfiler,并将被分析的JVM连接到JProfiler主窗口。
所有IDE集成都包含在JProfiler安装的integrations
目录中。
原则上,可以使用各自IDE中的插件安装机制手动安装该目录中的存档。然而,安装IDE集成的首选方法是从主菜单中调用
Session→IDE integrations。
从IDE分析的会话不会在JProfiler中获得自己的会话条目,因为这样的会话无法从JProfiler GUI启动。 分析设置根据IDE中的设置以每个项目或每个运行配置为基础持久化。
当连接到IDE时,JProfiler在工具栏中显示一个窗口切换器,使您可以轻松跳回到IDE中的关联窗口。 所有Show Source操作现在直接在IDE中显示源代码,而不是在JProfiler中内置的源代码查看器中。
IDE集成在后续章节中详细讨论。
Attach模式
您不必事先决定要分析JVM。通过JProfiler中的attach功能,您可以选择正在运行的JVM并动态加载分析代理。 虽然attach模式很方便,但它有一些您应该注意的缺点:
- 您必须从正在运行的JVM列表中识别要分析的JVM。如果同一台机器上运行了很多JVM,这有时可能会很棘手。
- 存在额外的开销,因为可能需要重新定义许多类以添加检测。
- JProfiler中的某些功能在attach模式下不可用。这主要是因为JVMTI的某些功能只能在JVM初始化时开启,而在JVM生命周期的后期阶段不可用。
- 某些功能需要在所有类的大部分中进行检测。在类加载时进行检测很便宜,而在类已经加载后再添加检测则不便。 使用attach模式时,这些功能默认被禁用。
-
Attach功能支持OpenJDK JVM、Oracle JVM(版本6或更高)、最近的OpenJ9 JVM(8u281+、11.0.11+或Java 17+)或基于此类版本的IBM JVM。
JVM不能指定VM参数
-XX:+PerfDisableSharedMem
和-XX:+DisableAttachMechanism
。
JProfiler启动中心的Quick Attach选项卡列出了所有可以分析的JVM。列表条目的背景颜色指示是否已经加载了分析代理, 是否当前连接了JProfiler GUI,或者是否已配置了离线分析。
当您启动分析会话时,您可以在会话设置对话框中配置分析设置。 当您反复分析相同的进程时,您不想一次又一次地重新输入相同的配置,因此当您关闭使用快速附加功能创建的会话时,可以保存持久会话。 下次您想分析此进程时,请从Open Session选项卡而不是Quick Attach选项卡启动已保存的会话。 您仍然需要选择正在运行的JVM,但分析设置与您之前配置的相同。
附加到本地服务
JVM中的attach API要求调用进程以与您要附加的进程相同的用户身份运行,因此JProfiler显示的JVM列表仅限于当前用户。 不同用户启动的进程大多是服务。附加到服务的方法因Windows、Linux和基于Unix的平台而异。
在Windows上,附加对话框有一个Show Services按钮 ,列出所有本地运行的服务。JProfiler启动桥接可执行文件,以便能够附加到这些进程,无论它们以哪个用户身份运行。
在Linux上,JProfiler支持通过PolicyKit直接在UI中切换用户,PolicyKit是大多数Linux发行版的一部分。 通过在附加对话框中单击Switch user,您可以输入不同的用户名并通过系统密码对话框进行身份验证。
在包括macOS在内的基于Unix的平台上,您可以使用 su
或 sudo
以不同的用户身份执行命令行工具
jpenable
,具体取决于您的Unix变体或Linux发行版。在macOS和基于Debian的Linux发行版(如Ubuntu)上,使用
sudo
。
使用sudo,调用
sudo -u userName jpenable使用su,所需的命令行是
su userName -c jpenable
jpenable
将让您选择JVM,并告诉您分析代理正在监听的端口。
之后,您可以通过JProfiler UI的本地会话或直接连接jpenable给定端口的SSH连接进行连接。
附加到远程机器上的JVM
分析最苛刻的设置是远程分析 - JProfiler GUI在本地机器上运行,被分析的JVM在另一台机器上。 对于传递-agentpath VM参数到被分析JVM的设置,您必须在远程机器上安装JProfiler,并在本地机器上设置远程会话。 使用JProfiler中的远程附加功能,不需要进行此类修改。您只需要SSH凭据即可登录到远程机器。
SSH连接使JProfiler能够上传在 “安装JProfiler”帮助主题中讨论的代理包,并在远程机器上执行包含的命令行工具。 您不需要在本地机器上设置SSH,JProfiler附带自己的实现。在最简单的设置中,您只需定义主机、用户名和身份验证。
通过SSH连接,JProfiler可以自动发现正在运行的JVM,或者连接到已经在监听的分析代理的特定端口。
对于后一种情况,您可以在远程机器上使用 jpenable
或 jpintegrate
,
如上所述,并准备一个特殊的JVM进行分析。然后,SSH远程附加可以配置为直接连接到配置的分析端口。
自动发现将列出远程机器上以SSH登录用户身份启动的所有JVM。在大多数情况下,这不会是启动您想要分析的服务的用户。
因为启动服务的用户通常不允许进行SSH连接,JProfiler添加了一个Switch User超链接,
允许您使用 sudo
或 su
切换到该用户。
在复杂的网络拓扑中,有时您无法直接连接到远程机器。在这种情况下,您可以告诉JProfiler在GUI中使用多跳SSH隧道进行连接。 在SSH隧道的末端,您可以进行一次直接的网络连接,通常是到“127.0.0.1”。
对于其他身份验证机制,您可以使用OpenSSH隧道模式。您可以输入主机名,就像在使用OpenSSH可执行文件时在命令行上输入一样。 这也可以是OpenSSH配置文件中配置的别名。除了主机名之外,还可以选择指定端口和用户名。在Windows上,仅支持Microsoft的内置OpenSSH客户端。
SSH选项文本字段接受您在命令行上指定的OpenSSH可执行文件的任意附加参数。这在您遵循教程中给出的指示时特别有用, 例如如何通过AWS会话管理器隧道SSH连接。
HPROF快照只能为以SSH登录用户身份启动的JVM拍摄。这是因为HPROF快照需要一个中间文件,该文件是以启动JVM的用户的访问权限写入的。 出于安全原因,无法将文件权限转移给SSH登录用户进行下载。完整的分析会话不存在此类限制。
附加到在Docker容器中运行的JVM
Docker容器通常没有安装SSH服务器,虽然您可以在Docker容器中使用jpenable,但除非您在Docker文件中指定了分析端口,否则分析端口将无法从外部访问。
在JProfiler中,您可以通过在快速附加对话框中选择Docker容器来附加到在Windows或macOS的本地Docker Desktop安装中运行的JVM。
默认情况下,JProfiler会自动检测到 docker
可执行文件的路径。
或者,您可以在常规设置对话框的“外部工具”选项卡上进行配置。
选择容器后,将显示在Docker容器中运行的所有JVM。当您选择一个JVM时,JProfiler将使用Docker命令自动在选定的容器中安装分析代理, 准备JVM进行分析并将分析协议隧道到外部。
对于远程Docker安装,您可以使用SSH远程附加功能,然后选择远程机器上的Docker容器。 如果登录用户不在docker组中,您可以首先按照上述描述切换用户。
在远程附加对话框中使用Select container超链接,您可以选择正在运行的Docker容器并显示其中运行的所有JVM。
附加到在Kubernetes集群上运行的JVM
要分析在Kubernetes集群上运行的JVM,JProfiler使用 kubectl
命令行工具,
用于发现pod和容器,以及连接到容器、列出其JVM并最终连接到选定的JVM。
kubectl
命令行工具可以在本地计算机上使用,或者在您具有SSH访问权限的远程机器上使用。
JProfiler直接支持这两种情况。对于本地安装,JProfiler将尝试自动检测 kubectl
的路径,
但您可以在常规设置对话框的“外部工具”选项卡上配置一个显式路径。
JProfiler在一个具有三个级别的树中列出所有检测到的容器。顶部是包含检测到的pod的子节点的命名空间节点。 叶节点是容器本身,必须选择其中一个以继续选择正在运行的JVM。
kubectl
可能需要额外的命令行选项进行身份验证,以便能够连接到Kubernetes集群。
这些选项可以在容器选择对话框的顶部输入。由于这些选项可能是敏感信息,只有在您明确选择复选框以在重启时记住它们时,才会将其保存到磁盘。
取消选择此复选框将立即清除任何先前保存的信息。
设置正在运行的JVM的显示名称
在JVM选择表中,显示的进程名称是被分析JVM的主类及其参数。对于由exe4j或install4j生成的启动器,显示的是可执行文件名称。
如果您希望自己设置显示的名称,例如,因为您有几个具有相同主类的进程,否则将无法区分,您可以设置VM参数
-Djprofiler.displayName=[name]
。如果名称包含空格,请使用单引号:
-Djprofiler.displayName='My name with spaces'
,如果需要,请用双引号引用整个VM参数。
除了-Djprofiler.displayName
,JProfiler还识别-Dvisualvm.display.name
。