JProfiler 支持通过 Gradle 使用特殊任务进行分析。此外,JProfiler 还提供了许多 用于处理快照的命令行可执行文件, 这些文件都有对应的 Gradle 任务。
使用 Gradle 任务
要在 Gradle 构建文件中使用 JProfiler Gradle 任务,可以使用 plugins 块:
plugins {
id 'com.jprofiler' version 'X.Y.Z'
}
如果不想为此使用 Gradle 插件仓库,Gradle 插件也可在文件 bin/gradle.jar 中找到。
接下来,需要告知 JProfiler Gradle 插件 JProfiler 的安装位置。
jprofiler {
installDir = file('/path/to/jprofiler/home')
}
从 Gradle 进行分析
使用类型为 com.jprofiler.gradle.JavaProfile 的任务,可以分析任何 Java 进程。
该类继承自 Gradle 内置的 JavaExec,因此可以使用相同的参数来配置进程。
对于测试分析,请使用类型为 com.jprofiler.gradle.TestProfile 的任务,
它继承自 Gradle 的 Test 任务。
在没有任何额外配置的情况下,两个任务都会启动一个交互式分析会话(session), 分析代理(agent)在默认端口 8849 上等待来自 JProfiler GUI 的连接。 对于离线分析,可以引用导出的配置文件,或者直接使用下表中所示的属性配置常用 session 设置和自动化记录。
| 属性 | 描述 | 是否必填 |
|---|---|---|
| offline | 分析运行是否应处于离线模式。 |
否,offline 和 nowait 不能同时为 true。
|
| nowait | 分析是否应立即开始,或者被分析的 JVM 是否应等待来自 JProfiler GUI 的连接。 | |
| sessionId |
定义应从中获取配置文件设置(profiling settings)的 session ID。
如果 nowait 和 offline 均未设置,则此项无效,
因为在这种情况下,分析 session 将在 GUI 中选择。
|
仅当为离线分析设置了 configFile 时
|
| configFile | 定义应从中读取配置文件设置(profiling settings)的配置文件。 如果在离线分析中省略此属性,可以直接使用下面的属性配置常用 session 设置。 如果这些属性均未设置,则使用默认的离线 session 设置。 | 否 |
| callTreeMode |
为无配置文件的离线分析选择调用树(call tree)收集模式。在 Gradle 中,可以使用
com.jprofiler.buildtools.CallTreeMode 的值。字符串值为
sampling、instrumentation、instr
和 async。
|
否 |
| profile, compact, ignore |
用于无配置文件的离线分析的包或类过滤器。值可以是以 : 分隔条目的字符串,
或字符串列表。
|
否 |
| lineNumbers | 是否应在调用树(call tree)中记录行号。 | 否 |
| snapshotFile |
用于自动化离线记录的快照文件。如果设置了此项但未设置 recording,
则记录 CPU 数据。线程和遥测(telemetry)始终会被记录。
|
否 |
| recording |
用于自动化离线记录的数据类型。值可以是以 : 分隔条目的字符串,
或字符串列表。常用值有 cpu、allocation、
jdbc、jpa、mongo_db、
http_server 和 http_client。
支持的记录值的完整列表记录在相应的
-agentpath 选项中。选择探针(probe)记录也会同时记录 CPU 数据。
|
否,但如果设置了此项则需要 snapshotFile |
| duration |
自动化离线记录的持续时间,例如 30s、10m 或
1h。如果未设置此属性,记录将持续到 JVM 终止,届时保存快照。
|
否,但如果设置了此项则需要 snapshotFile |
| delay |
自动化离线记录开始前的延迟时间,例如 10s 或 1m。
|
否,但如果设置了此项则需要 snapshotFile |
| port |
定义分析代理(agent)应监听来自 JProfiler GUI 连接的端口号。
此端口必须与 remote session 配置中配置的端口相同。
如果未设置或为零,将使用默认端口(8849)。
如果设置了 offline,则此项无效,因为在这种情况下没有来自 GUI 的连接。
|
否 |
| debugOptions | 如果需要传递任何额外的库(library)参数用于调优或调试,可以通过此属性进行设置。 | 否 |
以下是一个分析包含 main 方法的 Java 类的示例,该类由所在项目编译:
task run(type: com.jprofiler.gradle.JavaProfile) {
mainClass = 'com.mycorp.MyMainClass'
classpath sourceSets.main.runtimeClasspath
offline = true
callTreeMode = 'sampling'
profile = ['com.mycorp.', 'org.example.']
snapshotFile = file('build/snapshots/run.jps')
recording = ['cpu', 'allocation', 'jdbc']
duration = '10m'
}
对于无配置文件属性未涵盖的高级设置,请导出配置文件并通过
configFile 和 sessionId 引用它。
task run(type: com.jprofiler.gradle.JavaProfile) {
mainClass = 'com.mycorp.MyMainClass'
classpath sourceSets.main.runtimeClasspath
offline = true
sessionId = 80
configFile = file('path/to/jprofiler_config.xml')
}
您可以在 api/samples/offline 示例项目中查看此任务的可运行示例。
与标准的 JavaExec 任务不同,JavaProfile 任务
也可以通过调用其上的 createProcess() 在后台启动。
请参阅 api/samples/mbean 示例项目以了解此功能的演示。
如果需要分析所需的 VM 参数,com.jprofiler.gradle.SetAgentpathProperty 任务
会将其分配给一个属性,该属性的名称通过 propertyName 属性配置。
应用 JProfiler 插件会自动向您的项目添加一个名为 setAgentPathProperty
的此类型任务。要获取前一个示例中将使用的 VM 参数,只需添加:
setAgentPathProperty {
propertyName = 'profilingVmParameter'
offline = true
callTreeMode = 'sampling'
profile = ['com.mycorp.', 'org.example.']
}
到您的项目中,并为某个其他任务添加对 setAgentPathProperty 的依赖。
然后,您可以在该任务的执行阶段使用项目属性 profilingVmParameter。
在将属性赋值给其他任务属性时,请用 doFirst {...} 代码块包围其用法,
以确保处于 Gradle 执行阶段而非配置阶段。
从快照导出数据
com.jprofiler.gradle.Export 任务可用于从已保存的快照中导出视图(view),
并复制 bin/jpexport
命令行工具 的参数。
它支持以下属性:
| 属性 | 描述 | 是否必填 |
|---|---|---|
| snapshotFile |
快照文件的路径。必须是扩展名为 .jps 的文件。
|
是 |
| ignoreErrors |
忽略无法为视图(view)设置选项时发生的错误,并继续处理下一个视图(view)。
默认值为 false,表示在发生第一个错误时终止导出。
|
否 |
| csvSeparator | CSV 导出的字段分隔符。默认为 ","。 | 否 |
| obfuscator |
对所选混淆器的类名和方法名进行反混淆。默认为 "none",对于其他值,
必须指定 mappingFile 选项。可选值为 none、
proguard 或 yguard。
|
否 |
| mappingFile |
所选混淆器的映射文件。仅当指定了 obfuscator 属性时才可设置。
|
仅当指定了 obfuscator 时
|
在导出任务上,调用 views 方法并向其传递一个闭包,在闭包中一次或多次调用
view(name, file[, options])。每次调用 view 都会生成一个输出文件。
name 参数是视图(view)名称。有关可用视图(view)名称的列表,请参阅
jpexport
命令行可执行文件 的帮助页面。
file 参数是输出文件,可以是绝对路径文件或相对于项目的文件。
最后,可选的 options 参数是一个包含所选视图(view)导出选项的 map。
以下是使用导出任务的示例:
task export(type: com.jprofiler.gradle.Export) {
snapshotFile = file('snapshot.jps')
views {
view('CallTree', 'callTree.html')
view('HotSpots', 'hotSpots.html',
[threadStatus: 'all', expandBacktraces: 'true'])
}
}
比较快照
与 bin/jpcompare
命令行工具 类似,
com.jprofiler.gradle.Compare 任务可以比较两个或多个快照。
其属性如下:
| 属性 | 描述 | 是否必填 |
|---|---|---|
| snapshotFiles |
要比较的快照文件。可以传递任何包含 Gradle 解析为文件集合的对象的 Iterable。
如果快照文件具有各自的反混淆设置,文件名可以采用以下形式: <file name>:<obfuscator>:<mapping file>, 其中 <obfuscator> 和 <mapping file> 对应下面的全局选项。 |
是 |
| obfuscator |
对所选混淆器的类名和方法名进行反混淆。默认为 "none",对于其他值,
必须指定 mappingFile 选项。可选值为 none、
proguard 或 yguard。
|
否 |
| mappingFile |
所选混淆器的映射文件。仅当指定了 obfuscator 属性时才可设置。
|
仅当指定了 obfuscator 时
|
| sortByTime |
如果设置为 true,所有提供的快照文件将按其文件修改时间排序,
否则将按照在 snapshotFiles 属性中指定的顺序进行比较。
|
否 |
| ignoreErrors |
忽略无法为比较设置选项时发生的错误,并继续进行下一次比较。
默认值为 false,表示在发生第一个错误时终止导出。
|
否 |
就像为 Export 任务定义导出视图(view)一样,Compare 任务
有一个 comparisons 方法,其中对 comparison(name, file[, options])
的嵌套调用定义了要执行的比较。可用比较名称列表可在
jpcompare
命令行可执行文件 的帮助页面上找到。
以下是使用比较任务的示例:
task compare(type: com.jprofiler.gradle.Compare) {
snapshotFiles = files('snapshot1.jps', 'snapshot2.jps')
comparisons {
comparison('CallTree', 'callTree.html')
comparison('HotSpots', 'hotSpots.csv',
[valueSummation: 'total', format: 'csv'])
}
}
或者,如果要为多个快照创建遥测(telemetry)比较:
task compare(type: com.jprofiler.gradle.Compare) {
snapshotFiles = fileTree(dir: 'snapshots', include: '*.jps')
sortByTime = true
comparisons {
comparison('TelemetryHeap', 'heap.html', [valueType: 'maximum'])
comparison('ProbeTelemetry', 'jdbc.html', [probeId: 'JdbcProbe'])
}
}
分析堆快照
Gradle 任务 com.jprofiler.gradle.Analyze 与
bin/jpanalyze
命令行工具 具有相同的功能。
该任务具有与 Compare 任务类似的 snapshotFiles 属性,
用于指定要处理的快照,以及与 Export 任务类似的 obfuscator
和 mappingfile 属性用于反混淆。属性
removeUnreferenced、retainSoft、retainWeak、
retainPhantom、retainFinalizer 和 retained
对应命令行工具的参数。
以下是使用 Analyze 任务的示例:
task analyze(type: com.jprofiler.gradle.Analyze) {
snapshotFiles = fileTree(dir: 'snapshots', include: '*.jps')
retainWeak = true
obfuscator = 'proguard'
mappingFile = file('obfuscation.txt')
}