在 IDE 中开发自定义探针 (probe) 需要清楚地了解拦截点以及该探针将带来的好处。另一方面,通过脚本探针,您可以直接在 JProfiler GUI 中快速定义简单的探针并进行实验,而无需学习任何 API。与嵌入式或注入式自定义探针不同,脚本探针可以在正在运行的分析会话 (session) 中重新定义,从而实现快速的“编辑-编译-测试”循环。
定义脚本探针
脚本探针的定义方式是选择一个被拦截的方法,并输入一个返回该探针有效负载 (payload) 字符串的脚本。可以在单个探针中捆绑多个此类“方法-脚本”对。
可以在会话 (session) 设置中访问脚本探针配置。在此处可以创建和删除脚本探针,以及将脚本探针保存到可由其他分析会话导入的集合中。
每个脚本探针都需要一个名称以及可选的描述。该名称用于在 JProfiler 位于“JVM & Custom Probes”部分的视图 (view) 选择器中添加一个探针视图 (view)。描述显示在探针视图的页眉中,应当对其用途进行简短说明。
对于选择方法,您有多种选择,包括从已配置的类路径 (classpath) 中选择类,或者在分析会话 (session) 已运行时从被分析 (profiled) 类中选择类。在第二步中,您可以从所选类中选择一个方法。
选择被拦截方法的更简便方式是从调用树 (call tree) 视图 (view) 中选择。在上下文菜单中,Intercept Method With Script Probe 操作将询问您是要创建新探针还是向现有探针添加拦截。
探针脚本
在脚本编辑器中,您可以访问被拦截方法的所有参数以及调用该方法的对象。如果您需要访问被拦截方法的返回值或任何抛出的异常 (exception),则必须编写嵌入式或注入式探针。
在此环境中,您的脚本可以构造有效负载 (payload) 字符串,既可以作为表达式,也可以作为带有 return 语句的语句序列。此类脚本的最简单版本只需对某个参数返回
parameter.toString(),或对基本类型的参数返回 String.valueOf(parameter)。如果返回
null,则不会创建任何有效负载。
如果您同时记录 CPU 和探针数据,CPU 部分中的调用树 (call tree) 视图 (view) 将在相应的调用栈 (call stack) 处显示指向探针视图的链接。或者,您可以选择在 CPU 调用树视图中内联显示有效负载 (payload) 字符串。探针向导的“Payload interceptions->Call tree annotations”步骤包含此选项。
脚本可用的另一个参数是脚本上下文(script context),这是一个类型为 com.jprofiler.api.agent.ScriptContext
的对象,允许您在为当前探针定义的任何脚本调用之间存储数据。例如,假设被拦截的方法 A 只能看到没有良好文本表示的对象,但对象与显示名称之间的关联可以通过拦截方法 B 来获取。那么您可以在同一个探针中拦截方法
B,并将对象到文本的关联直接保存到脚本上下文中。在方法 A 中,您随后即可从脚本上下文中获取该显示文本,并用它来构建有效负载 (payload) 字符串。
如果这类关注点变得过于复杂,您应该考虑切换到嵌入式或注入式探针 API。
缺失的功能
脚本探针旨在降低自定义探针开发的门槛,但它们缺少完整探针系统的一些功能,您应该注意这些限制:
- 脚本探针无法执行调用树拆分。在 JProfiler UI 中,这是一项独立的功能,详见自定义探针概念中的说明。嵌入式和注入式探针直接提供调用树拆分功能。
- 脚本探针无法创建控制对象 (control object) 或创建自定义探针事件类型。这只能通过嵌入式或注入式探针实现。
- 与嵌入式和注入式探针不同,脚本探针无法访问返回值或抛出的异常 (exception)。
- 脚本探针无法处理可重入拦截。如果一个方法被递归调用,则仅拦截对它的第一次调用。嵌入式和注入式探针为您提供了对重入行为的细粒度控制。
- 无法将默认遥测 (telemetry) 之外的遥测捆绑到探针视图 (view) 中。相反,您可以使用脚本遥测功能,如自定义探针概念中所示。







