JVMTM工具界面

版本 20.0


什么是 JVM 工具接口?

虚拟机TM工具接口(JVM TI) 是开发和监控工具使用的编程接口。它提供了一种检查状态和控制在 Java 中运行的应用程序执行的方法TM虚拟机 (VM)。
JVM TI 旨在为需要访问 VM 状态的各种工具提供 VM 接口,包括但不限于:分析、调试、监控、线程分析和重写率分析工具。
JVM TI 可能不适用于 Java 的所有实现TM虚拟机。
JVM TI 是双向接口。 JVM的客户端 TI,以下称为代理人可以通过 events 通知有趣的事件。虚拟机 TI 可以通过许多 功能 查询和控制应用程序,以响应事件或独立于事件。
代理与执行正在检查的应用程序的虚拟机在同一进程中运行并直接通信。这种通信是通过本机接口(JVM 钛)。本机进程内接口允许最大程度地控制,同时将工具部分的干扰降至最低。通常,代理相对紧凑。它们可以由一个单独的进程控制,该进程实现工具的大部分功能,而不会干扰目标应用程序的正常执行。

架构

工具可以直接写入JVM TI 或间接通过更高级别的接口。 Java 平台调试器架构包括 JVM TI,还包含更高级别的进程外调试器接口。高层接口比JVM更合适 TI 适用于许多工具。有关 Java 平台调试器体系结构的更多信息,请参阅 Java 平台调试器架构网站

代笔

代理可以用支持 C 语言调用约定和 C 或 C++ 定义的任何本地语言编写。
使用 JVM 所需的函数、事件、数据类型和常量定义 TI 在包含文件 jvmti.h 中定义。要使用这些定义,请添加 J2SETM包含目录到您的包含路径并添加
#include <jvmti.h>
  
到你的源代码。

部署代理

代理以特定于平台的方式部署,但通常是动态库的平台等价物。在 Windows 上TM操作系统,例如,代理库是“动态链接库”(DLL)。在 Linux 上TMOperating Environment,代理库是一个共享对象(.so 文件)。
通过使用 命令行选项 指定代理程序库名称,可以在 VM 启动时启动代理程序。某些实现可能支持在实时 阶段 中使用 启动代理 的机制。这是如何启动的细节是特定于实现的。

静态链接代理(自版本 1.2.3 起)

本机 JVMTI 代理可能是静态链接与虚拟机。库和 VM 映像的组合方式取决于实现。其图像已与 VM 组合的智能体 L 定义为静态链接当且仅当代理导出名为 Agent_OnLoad_L 的函数时。
如果一个静态链接agent L 导出了一个名为 Agent_OnLoad_L 的函数和一个名为 Agent_OnLoad 的函数,Agent_OnLoad 函数将被忽略。如果代理 L 是静态链接, 将使用为 Agent_OnLoad 函数指定的相同参数和预期返回值调用 Agent_OnLoad_L 函数。代理 L 是静态链接将禁止动态加载同名代理。
VM 将在 VM 执行期间调用动态入口点 Agent_OnUnLoad 的同一点调用代理的 Agent_OnUnload_L 函数(如果导出此类函数)。无法卸载静态加载的代理。 Agent_OnUnload_L 函数仍将被调用以执行任何其他代理关闭相关任务。如果一个静态链接agent L 导出一个名为 Agent_OnUnLoad_L 的函数和一个名为 Agent_OnUnLoad 的函数,Agent_OnUnLoad 函数将被忽略。
如果代理 L 是静态链接, 将使用为 Agent_OnAttach 函数指定的相同参数和预期返回值调用 Agent_OnAttach_L 函数。如果一个静态链接代理 L 导出一个名为 Agent_OnAttach_L 的函数和一个名为 Agent_OnAttach 的函数,Agent_OnAttach 函数将被忽略。

代理命令行选项

下面使用术语“命令行选项”来表示 JNI 调用 API 的 JavaVMInitArgs 参数中提供给 JNI_CreateJavaVM 函数的选项。
以下两个命令行选项之一用于 VM 启动以正确加载和运行代理。这些参数标识包含代理的库以及要在启动时传入的选项字符串。
-agentlib: <代理库名称>= <选项>
-agentlib: 后面的名称是要加载的库的名称。库的查找,包括其全名和位置,以特定于平台的方式进行。通常,<代理库名称>扩展为操作系统特定的文件名。这<选项>将在启动时传递给代理。例如,如果指定选项-agentlib:foo=opt1,opt2,则VM将尝试从Windows下的系统PATH加载共享库foo.dllTMlibfoo.so 来自 Linux 下的 LD_LIBRARY_PATHTM.如果代理库静态链接到可执行文件,则不会发生实际加载。
-agentpath: <path-to-agent>= <选项>
-agentpath: 之后的路径是加载库的绝对路径。不会发生库名称扩展。这<选项>将在启动时传递给代理。例如,如果指定选项 -agentpath:c:\myLibs\foo.dll=opt1,opt2,VM 将尝试加载共享库 c:\myLibs\foo.dll。如果代理库静态链接到可执行文件,则不会发生实际加载。
对于动态共享库代理,将调用库中的启动例程Agent_OnLoad 。如果代理库静态链接到可执行文件,则系统将尝试调用 Agent_OnLoad_<agent-lib-name> 入口点,其中 <agent-lib-name> 是代理的基本名称。在上面的示例 -agentpath:c:\myLibs\foo.dll=opt1,opt2 中,系统将尝试查找并调用 Agent_OnLoad_foo 启动例程。
加载了 -agentlib:-agentpath: 的库将搜索 JNI 本机方法实现,以方便在工具中使用 Java 编程语言代码,正如 字节码检测 所需要的那样。
在搜索完所有其他库后,将搜索代理库(希望覆盖或拦截非代理方法的本机方法实现的代理可以使用 NativeMethodBind 事件 )。
这些开关仅执行上述操作 - 它们不会更改 VM 或 JVM 的状态 TI。启用 JVM 不需要命令行选项 TI 或 JVM 方面 TI,这是通过使用 capabilities 以编程方式处理的。

代理启动

VM 通过调用启动函数来启动每个代理。如果在 OnLoad 阶段 中启动代理,将调用用于静态链接代理的函数 Agent_OnLoad Agent_OnLoad_L 。如果代理在 live 阶段 中启动,将调用静态链接代理的函数 Agent_OnAttach Agent_OnAttach_L 。每个代理只调用一次启动函数。

代理启动(加载阶段)

如果代理在 OnLoad 阶段启动,则其代理库必须导出具有以下原型的启动函数:
JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
或者对于名为“L”的静态链接代理:
JNIEXPORT jint JNICALL
Agent_OnLoad_L(JavaVM *vm, char *options, void *reserved)
VM 将通过调用此函数来启动代理。它将在 VM 初始化时足够早地被调用:
VM 将调用 Agent_OnLoadAgent_OnLoad_<agent-lib-name> 函数<选项>作为第二个参数 - 也就是说,使用命令行选项示例,"opt1,opt2" 将传递给 Agent_OnLoadchar *options 参数。 options 参数被编码为 修改后的 UTF-8 字符串。如果=<选项>未指定,零长度字符串将传递给 optionsoptions 字符串的生命周期是 Agent_OnLoadAgent_OnLoad_<agent-lib-name> 调用。如果需要超出此时间,则必须复制字符串或字符串的一部分。 Agent_OnLoad 被调用和它返回之间的时间段称为加载阶段.由于 VM 在 OnLoad 阶段 期间未初始化,因此 Agent_OnLoad 中允许的操作集受到限制(请参阅此时可用功能的功能描述)。代理可以安全地处理选项并使用 SetEventCallbacks 设置事件回调。一旦收到 VM 初始化事件(即调用 虚拟机初始化 回调),代理就可以完成其初始化。

理由:需要提前启动,以便代理可以设置所需的功能,其中许多功能必须在 VM 初始化之前设置。在 JVMDI 中,-Xdebug 命令行选项提供了非常粗粒度的功能控制。 JVMPI 实现使用各种技巧来提供单个“JVMPI on”开关。没有合理的命令行选项可以提供平衡所需功能与性能影响所需的精细控制。还需要提前启动,以便代理可以控制执行环境——修改文件系统和系统属性以安装它们的功能。

Agent_OnLoadAgent_OnLoad_<agent-lib-name> 的返回值用于指示错误。除零以外的任何值都表示错误并导致 VM 终止。

代理启动(实时阶段)

VM 可能支持一种机制,允许代理在实时 阶段 期间在 VM 中启动。如何支持这一点的细节是特定于实现的。例如,一个工具可以使用一些特定于平台的机制或特定于实现的 API 来附加到正在运行的 VM,并请求它启动给定的代理。
如果代理在实时阶段启动,则其代理库必须导出具有以下原型的启动函数:
JNIEXPORT jint JNICALL
Agent_OnAttach(JavaVM* vm, char *options, void *reserved)
或者对于名为“L”的静态链接代理:
JNIEXPORT jint JNICALL
Agent_OnAttach_L(JavaVM* vm, char *options, void *reserved)
VM 将通过调用此函数来启动代理。它将在附加到 VM 的线程的上下文中调用。第一个参数<虚拟机>是 Java 虚拟机。这<选项>参数是提供给代理的启动选项。<选项>被编码为 修改后的 UTF-8 字符串。如果未提供启动选项,则会将零长度字符串传递给 optionsoptions 字符串的生命周期是 Agent_OnAttachAgent_OnAttach_<agent-lib-name> 调用。如果需要超出此时间,则必须复制字符串或字符串的一部分。
请注意,某些 capabilities 可能无法在实时阶段使用。
Agent_OnAttachAgent_OnAttach_<agent-lib-name > 函数初始化代理并向 VM 返回一个值以指示是否发生错误。任何非零值都表示错误。错误不会导致 VM 终止。相反,VM 会忽略错误,或采取一些特定于实现的操作——例如,它可能会向标准错误打印错误,或在系统日志中记录错误。

代理关闭

该库可以选择导出具有以下原型的关闭函数:
JNIEXPORT void JNICALL
Agent_OnUnload(JavaVM *vm)
或者对于名为“L”的静态链接代理:
JNIEXPORT void JNICALL
Agent_OnUnload_L(JavaVM *vm)
该函数将在库即将卸载时由 VM 调用。库将被卸载(除非它被静态链接到可执行文件中)并且如果某些特定于平台的机制导致卸载(本文档中未指定卸载机制)或库(实际上)被卸载,则将调用此函数VM 的终止。 VM 终止包括正常终止和 VM 故障,包括启动失败,但当然不包括非受控关闭。如果 Agent_OnAttach / Agent_OnAttach_L 函数报告错误(返回非零值),实现也可以选择不调用此函数。请注意此函数与 虚拟机死亡事件 之间的区别:要发送 VM 死亡事件,VM 必须至少运行到初始化点和有效的 JVM 必须存在已为 VMDeath 设置回调并启用事件的 TI 环境。 Agent_OnUnloadAgent_OnUnload_<agent-lib-name> 不需要这些,如果库因其他原因被卸载,也会调用此函数。在发送 VM Death 事件的情况下,它将在调用此函数之前发送(假设由于 VM 终止而调用此函数)。此函数可用于清理代理分配的资源。

JAVA_TOOL_OPTIONS

由于不能始终访问或修改命令行,例如在嵌入式 VM 中或只是在脚本深处启动 VM,因此提供了一个 JAVA_TOOL_OPTIONS 变量,以便在这些情况下可以启动代理。
支持环境变量或其他命名字符串的平台可能支持 JAVA_TOOL_OPTIONS 变量。该变量将在空白边界处分解为选项。空白字符包括空格、制表符、回车符、换行符、垂直制表符和换页符。空白字符序列被认为等同于单个空白字符。除非引用,否则选项中不包含空格。报价如下: JNI_CreateJavaVM(在 JNI 调用 API 中)会将这些选项添加到其 JavaVMInitArgs 参数中提供的选项之前。在担心安全问题的情况下,平台可能会禁用此功能;例如,当有效用户或组 ID 与真实 ID 不同时,参考实现会在 Unix 系统上禁用此功能。此功能旨在支持工具的初始化——具体包括启动本机或 Java 编程语言代理。多个工具可能希望使用此功能,因此不应覆盖变量,而是应将选项附加到变量。请注意,由于变量是在 JNI 调用 API 创建 VM 调用时处理的,因此不会处理启动器处理的选项(例如,VM 选择选项)。

环境

虚拟机 TI规范支持同时使用多个JVM 德州仪器代理商。每个代理都有自己的 JVM 德州仪器环境。也就是说,JVM TI 状态对于每个代理都是独立的 - 对一个环境的更改不会影响其他环境。 JVM 的状态 TI 环境包括: 虽然他们的 JVM TI 状态是独立的,代理检查和修改 VM 的共享状态,它们还共享它们执行的本机环境。因此,一个代理可以扰乱其他代理的结果或导致它们失败。指定与其他代理的兼容性级别是代理编写者的责任。虚拟机 TI 实现无法防止代理之间的破坏性交互。减少这些事件发生可能性的技术超出了本文档的范围。
代理创建 JVM TI环境通过一个JVM TI 版本作为 JNI 调用 API 函数 GetEnv 的接口 ID。有关创建和使用 JVM 的更多详细信息,请参阅 Accessing JVM TI Functions 德州仪器环境。通常,JVM TI 环境是通过从 Agent_OnLoad 调用 GetEnv 创建的。

字节码检测

该接口不包括一些在具有分析支持的接口中可能会发生的事件。一些示例包括全速方法进入和退出事件。该接口改为提供对字节码检测,改变构成目标程序的 Java 虚拟机字节码指令的能力。通常,这些更改是将“事件”添加到方法的代码中 - 例如,在方法的开头添加对 MyProfiler.methodEntered() 的调用。由于更改纯粹是附加的,因此它们不会修改应用程序状态或行为。因为插入的代理代码是标准字节码,VM 可以全速运行,不仅优化了目标程序,还优化了检测。如果检测不涉及从字节码执行切换,则不需要昂贵的状态转换。结果是高性能事件。这种方法还为代理提供了完全控制:检测可以限制在代码的“有趣”部分(例如,最终用户的代码)并且可以是有条件的。 Instrumentation 可以完全以 Java 编程语言代码运行,也可以调用本地代理。仪器可以简单地维护计数器或可以对事件进行统计采样。
可以通过以下三种方式之一插入仪器:
此接口中提供的类修改功能旨在提供一种检测机制(ClassFileLoadHook 事件和 RetransformClasses 函数),以及在开发期间用于修复并继续调试(RedefineClasses 函数)的机制。
必须小心避免扰乱依赖性,尤其是在检测核心类时。例如,获取每个对象分配通知的方法是检测 Object 上的构造函数。假设构造函数最初为空,则构造函数可以更改为:
   public Object() {
    MyProfiler.allocationTracker(this);
   }
  
但是,如果此更改是使用 ClassFileLoadHook 事件进行的,那么这可能会影响典型的 VM,如下所示:第一个创建的对象将调用构造函数,导致类加载 MyProfiler ;这将导致对象创建,并且由于 MyProfiler 尚未加载,无限递归;导致堆栈溢出。对此的改进是将调用跟踪方法延迟到安全时间。例如,可以在 VMInit 事件的处理程序中设置 trackAllocations
   static boolean trackAllocations = false;

   public Object() {
    if (trackAllocations) {
     MyProfiler.allocationTracker(this);
    }
   }
  
SetNativeMethodPrefix 允许通过使用包装器方法来检测本机方法。

模块中代码的字节码检测

代理可以使用函数 AddModuleReads AddModuleExports AddModuleOpens AddModuleUses AddModuleProvides 来更新模块以扩展它读取的模块集、它导出或打开给其他模块的包集,或者它使用和提供的服务。
作为在引导类加载器的搜索路径或加载主类的类加载器的搜索路径上部署支持类的代理的帮助,Java 虚拟机安排由ClassFileLoadHook 事件转换的类模块读取两个类加载器的未命名模块。

修改后的 UTF-8 字符串编码

JVM TI 使用修改后的 UTF-8 对字符串进行编码。这与 JNI 使用的编码相同。修改后的 UTF-8 与标准 UTF-8 的区别在于补充字符和空字符的表示。有关详细信息,请参阅 JNI 规范的 修改后的 UTF-8 字符串 部分。

规范上下文

由于此接口提供了对 Java 虚拟机中运行的应用程序状态的访问;该术语指的是 Java 平台而不是本机平台(除非另有说明)。例如:
Sun、Sun Microsystems、Sun 徽标、Java 和 JVM 是 Oracle 和/或其附属公司在美国和其他国家/地区的商标或注册商标。


功能

访问函数

本机代码访问 JVM TI通过调用JVM的特性 德州仪器功能。访问 JVM TI 函数是通过使用接口指针以与Java 本机接口 (JNI) 函数 相同的方式访问的。虚拟机 TI接口指针被称为环境指针.
环境指针是指向环境的指针,类型为 jvmtiEnv* 。一个环境有关于它的 JVM 的信息 德州仪器连接。环境中的第一个值是指向函数表的指针。函数表是指向 JVM 的指针数组 德州仪器功能。每个函数指针都位于数组内的预定义偏移量处。
从 C 语言使用时:使用双重间接访问函数;环境指针提供上下文,是每个函数调用的第一个参数;例如:
jvmtiEnv *jvmti;
...
jvmtiError err = (*jvmti)->GetLoadedClasses(jvmti, &class_count, &classes);
  
从 C++ 语言使用时:函数作为 jvmtiEnv 的成员函数访问;环境指针未传递给函数调用;例如:
jvmtiEnv *jvmti;
...
jvmtiError err = jvmti->GetLoadedClasses(&class_count, &classes);
  
除非另有说明,本规范中的所有示例和声明均使用 C 语言。
A JVM TI环境可以通过JNI Invocation APIGetEnv函数获取:
jvmtiEnv *jvmti;
...
(*jvm)->GetEnv(jvm, &jvmti, JVMTI_VERSION_1_0);
  
每次调用 GetEnv 都会创建一个新的 JVM TI 连接和新的 JVM 德州仪器环境。 GetEnvversion 参数必须是 JVM TI 版本。返回的环境可能与请求的版本不同,但返回的环境必须兼容。如果兼容版本不可用,GetEnv 将返回 JNI_EVERSION,如果 JVM 不支持 TI 或 JVM 当前 VM 配置不支持 TI。可以添加其他接口用于创建 JVM 特定上下文中的 TI 环境。每个环境都有自己的状态(例如,期望的事件事件处理函数capabilities)。环境随 DisposeEnvironment 一起发布。因此,与每个线程只有一个环境的 JNI 不同,JVM TI 环境跨线程工作并且是动态创建的。

函数返回值

JVM TI 函数始终通过 jvmtiError 函数返回值返回 错误代码。一些函数可以通过调用函数提供的指针返回附加值。在某些情况下,JVM TI 函数分配您的程序必须显式释放的内存。这在单独的 JVM 中指示 TI 函数说明。空列表、数组、序列等作为 NULL 返回。
如果 JVM TI 函数遇到错误(除 JVMTI_ERROR_NONE 以外的任何返回值)参数指针引用的内存值未定义,但不会分配任何内存,也不会分配任何全局引用。如果由于输入无效而发生错误,则不会发生任何操作。

管理 JNI 对象引用

JVM TI 函数使用 JNI 引用(jobject jclass )及其派生物(jthread jthreadGroup )识别对象。传递给 JVM 的引用 TI 函数可以是全局的也可以是局部的,但必须是强引用。 JVM 返回的所有引用 TI 函数是本地引用——这些本地引用是在 JVM 期间创建的 德州仪器电话。本地引用是必须管理的资源(参见 JNI 文档 )。当线程从本机代码返回时,所有本地引用都将被释放。请注意,某些线程(包括典型的代理线程)永远不会从本机代码返回。确保线程能够创建十六个本地引用而无需任何显式管理。对于执行有限数量的 JVM 的线程 TI 在从本机代码返回之前调用(例如,线程处理事件),可以确定不需要显式管理。但是,长时间运行的代理线程将需要显式本地引用管理——通常使用 JNI 函数 PushLocalFramePopLocalFrame。相反,要保留本机代码返回之外的引用,必须将它们转换为全局引用。这些规则不适用于 jmethodID jfieldID ,因为它们不是 jobject s。

调用函数的先决条件

除非函数明确声明代理必须将线程或 VM 置于特定状态(例如,挂起),否则 JVM TI 实现负责使 VM 进入安全且一致的状态以执行该功能。

异常和函数

JVM TI 函数从不抛出异常;错误情况通过 函数返回值 传达。在对 JVM 的调用中保留任何现有的异常状态 TI 功能。有关处理异常的信息,请参阅 JNI 规范的 Java 异常 部分。

功能索引


内存管理

内存管理功能: 这些函数提供 JVM 使用的内存的分配和释放 TI 功能,可用于为代理提供工作记忆。 JVM 管理的内存 TI 与其他内存分配库和机制不兼容。

分配

jvmtiError
Allocate(jvmtiEnv* env,
      jlong size,
      unsigned char** mem_ptr)
通过JVM分配一块内存 TI 分配器。应使用 Deallocate 释放分配的内存。
可以在任何阶段调用
此函数可以从回调到 迭代函数,或从 GarbageCollectionStart GarbageCollectionFinish ObjectFree 事件的事件处理程序调用。
46
1.0
能力
所需功能
参数
Name Type Description
size jlong 要分配的字节数。

理由:jlong 用于与 JVMDI 兼容。

mem_ptr unsigned char** 返回时,指向分配内存开头的指针。如果 size 为零,则返回 NULL
Agent 传递一个指向 unsigned char* 的指针。返回时,unsigned char* 指向新分配的大小为 size 的数组。该数组应使用 Deallocate 释放。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_OUT_OF_MEMORY 无法满足内存请求。
JVMTI_ERROR_ILLEGAL_ARGUMENT size 小于零。
JVMTI_ERROR_NULL_POINTER mem_ptr NULL

解除分配

jvmtiError
Deallocate(jvmtiEnv* env,
      unsigned char* mem)
使用 JVM 释放 mem TI 分配器。此函数应用于释放由 JVM 分配和返回的任何内存 TI 函数(包括分配给 Allocate 的内存)。必须释放所有分配的内存,否则无法回收内存。
可以在任何阶段调用
此函数可以从回调到 迭代函数,或从 GarbageCollectionStart GarbageCollectionFinish ObjectFree 事件的事件处理程序调用。
47
1.0
能力
所需功能
参数
Name Type Description
mem unsigned char * 指向已分配内存开头的指针。请忽略“返回时,元素已设置”。
代理传递一个 unsigned char 数组。忽略数组元素的传入值。返回时,元素已设置。如果 memNULL ,调用将被忽略。
错误
这个函数返回一个 普遍错误


线

线程函数: 线程函数类型: 线程类型: 线程标志和常量: 这些函数提供有关线程的信息并允许代理挂起和恢复线程。
指定给这些函数的 jthread 可以是对 平台线程虚拟线程 的 JNI 引用。某些函数在虚拟线程上不受支持,并且在使用对虚拟线程的引用调用时返回 JVMTI_ERROR_UNSUPPORTED_OPERATION

获取线程状态

jvmtiError
GetThreadState(jvmtiEnv* env,
      jthread thread,
      jint* thread_state_ptr)
获取线程的状态。线程的状态由以下分层问题集的答案表示:
答案由以下位向量表示。
线程状态标志
持续的 Value Description
JVMTI_THREAD_STATE_ALIVE 0x0001 线程还活着。如果线程是新的(未启动)或已终止则为零。
JVMTI_THREAD_STATE_TERMINATED 0x0002 线程已完成执行。
JVMTI_THREAD_STATE_RUNNABLE 0x0004 线程可运行。
JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER 0x0400 线程正在等待进入同步块/方法,或者在 Object.wait() 之后等待重新进入同步块/方法。
JVMTI_THREAD_STATE_WAITING 0x0080 线程正在等待。
JVMTI_THREAD_STATE_WAITING_INDEFINITELY 0x0010 线程正在等待,没有超时。例如,Object.wait()
JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT 0x0020 线程正在等待指定的最长时间等待。例如,Object.wait(long)
JVMTI_THREAD_STATE_SLEEPING 0x0040 线程正在休眠 - Thread.sleep
JVMTI_THREAD_STATE_IN_OBJECT_WAIT 0x0100 线程正在等待对象监视器 - Object.wait
JVMTI_THREAD_STATE_PARKED 0x0200 线程已停放,例如:LockSupport.parkLockSupport.parkUtilLockSupport.parkNanos。在 Thread.sleep 中处于休眠状态的虚拟线程可能会设置此状态标志而不是 JVMTI_THREAD_STATE_SLEEPING
JVMTI_THREAD_STATE_SUSPENDED 0x100000 线程被挂起函数挂起(例如 SuspendThread )。如果设置了该位,则其他位指的是挂起前的线程状态。
JVMTI_THREAD_STATE_INTERRUPTED 0x200000 线程已被中断。
JVMTI_THREAD_STATE_IN_NATIVE 0x400000 线程在本机代码中——也就是说,一个本机方法正在运行,它没有回调到 VM 或 Java 编程语言代码中。
在运行 VM 编译的 Java 编程语言代码时不设置此标志,在运行 VM 代码或 VM 支持代码时也不设置。本地 VM 接口函数,例如 JNI 和 JVM TI 功能,可以实现为 VM 代码。
JVMTI_THREAD_STATE_VENDOR_1 0x10000000 由 VM 供应商定义。
JVMTI_THREAD_STATE_VENDOR_2 0x20000000 由 VM 供应商定义。
JVMTI_THREAD_STATE_VENDOR_3 0x40000000 由 VM 供应商定义。
以下定义用于转换JVM TI 线程状态到 java.lang.Thread.State 样式状态。
java.lang.Thread.State 转换掩码
持续的 Value Description
JVMTI_JAVA_LANG_THREAD_STATE_MASK JVMTI_THREAD_STATE_TERMINATED | JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT 在比较之前用这个掩盖状态
JVMTI_JAVA_LANG_THREAD_STATE_NEW 0 java.lang.Thread.State.NEW
JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED JVMTI_THREAD_STATE_TERMINATED java.lang.Thread.State.TERMINATED
JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE java.lang.Thread.State.RUNNABLE
JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER java.lang.Thread.State.BLOCKED
JVMTI_JAVA_LANG_THREAD_STATE_WAITING JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY java.lang.Thread.State.WAITING
JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT java.lang.Thread.State.TIMED_WAITING
规则
一个问题只能有一个答案,尽管可以没有答案(因为答案未知,不适用,或者没有一个答案是正确的)。只有当封闭的答案匹配时才会设置答案。也就是说,不超过一个 可以设置(一个J2SETM如果设置了 JVMTI_THREAD_STATE_ALIVE,兼容的实现将始终设置其中之一)。如果设置了其中任何一个,则设置封闭的答案 JVMTI_THREAD_STATE_ALIVE。不超过其中之一 可以设置(一个J2SETM如果设置了 JVMTI_THREAD_STATE_WAITING,兼容的实现将始终设置其中之一)。如果设置了其中一个,则设置了封闭的答案 JVMTI_THREAD_STATE_ALIVEJVMTI_THREAD_STATE_WAITING。不超过其中之一 可以设置。如果设置了其中任何一个,则设置封闭的答案 JVMTI_THREAD_STATE_ALIVEJVMTI_THREAD_STATE_WAITING。此外,如果设置了 JVMTI_THREAD_STATE_SLEEPING,则设置了 JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT。如果一个状态A使用状态机制实现B然后是状态A这是由这个函数返回的。例如,如果 Thread.sleep(long) 是使用 Object.wait(long) 实现的,那么返回的仍然是 JVMTI_THREAD_STATE_SLEEPING。不止一个 可以设置,但如果设置了任何一个,JVMTI_THREAD_STATE_ALIVE 也会被设置。
最后,除非未设置 JVMTI_THREAD_STATE_ALIVE,否则无法设置 JVMTI_THREAD_STATE_TERMINATED
线程状态表示是为规范的未来版本中的扩展而设计的;应相应地使用线程状态值,即它们不应用作序数。大多数查询都可以通过测试单个位来进行,如果需要在 switch 语句中使用,则应该用感兴趣的位来屏蔽状态位。上面未定义的所有位都保留供将来使用。符合当前规范的 VM 必须将保留位设置为零。代理应该忽略保留位——它们不应该被假定为零,因此不应该被包含在比较中。
示例
请注意,以下值不包括保留位和供应商位。
synchronized 语句处阻塞的线程状态为:
      JVMTI_THREAD_STATE_ALIVE + JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER
    
尚未启动的线程的状态为:
      0
    
Object.wait(3000) 处的线程状态为:
      JVMTI_THREAD_STATE_ALIVE + JVMTI_THREAD_STATE_WAITING +
        JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT +
        JVMTI_THREAD_STATE_MONITOR_WAITING
    
可运行时挂起的线程的状态为:
      JVMTI_THREAD_STATE_ALIVE + JVMTI_THREAD_STATE_RUNNABLE + JVMTI_THREAD_STATE_SUSPENDED
    
测试状态
在大多数情况下,可以通过测试与该问题对应的一位来确定线程状态。例如,测试线程是否正在休眠的代码:
    jint state;
    jvmtiError err;

    err = (*jvmti)->GetThreadState(jvmti, thread, &state);
    if (err == JVMTI_ERROR_NONE) {
      if (state & JVMTI_THREAD_STATE_SLEEPING) { ...
    
对于等待(即,在 Object.wait 、停放或睡觉),它将是:
      if (state & JVMTI_THREAD_STATE_WAITING) { ...
    
对于某些状态,需要测试不止一位,就像测试线程是否尚未启动时的情况一样:
      if ((state & (JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_TERMINATED)) == 0) { ...
    
区分定时和不定时 Object.wait
      if (state & JVMTI_THREAD_STATE_IN_OBJECT_WAIT) {
       if (state & JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT) {
        printf("in Object.wait(long timeout)\n");
       } else {
        printf("in Object.wait()\n");
       }
      }
    
java.lang.Thread.State的关系
java.lang.Thread.getState() 返回的 java.lang.Thread.State 表示的线程状态是从该函数返回的信息的子集。可以使用提供的转换掩码确定相应的java.lang.Thread.State。例如,这将返回 java.lang.Thread.State 线程状态的名称:
      err = (*jvmti)->GetThreadState(jvmti, thread, &state);
      abortOnError(err);
      switch (state & JVMTI_JAVA_LANG_THREAD_STATE_MASK) {
      case JVMTI_JAVA_LANG_THREAD_STATE_NEW:
       return "NEW";
      case JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED:
       return "TERMINATED";
      case JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE:
       return "RUNNABLE";
      case JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED:
       return "BLOCKED";
      case JVMTI_JAVA_LANG_THREAD_STATE_WAITING:
       return "WAITING";
      case JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING:
       return "TIMED_WAITING";
      }
    
只能在直播阶段调用
17
1.0
能力
所需功能
参数
Name Type Description
thread jthread 要查询的线程。如果 threadNULL ,则使用当前线程。
thread_state_ptr jint* 返回时,指向由 线程状态标志 定义的状态标志。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_NULL_POINTER thread_state_ptr NULL

获取当前线程

jvmtiError
GetCurrentThread(jvmtiEnv* env,
      jthread* thread_ptr)
获取当前线程。当前线程是调用函数的Java编程语言线程。如果 can_generate_early_vmstart 功能已启用且 java.lang.Thread 类尚未初始化,则该函数可能会在启动阶段返回 NULL
请注意,大多数 JVM 将线程作为参数的 TI 函数将接受 NULL 来表示当前线程。
只能在开始或直播阶段调用
18
1.1
能力
所需功能
参数
Name Type Description
thread_ptr jthread* 返回时,指向当前线程或 NULL
Agent 传递一个指向 jthread 的指针。返回时,jthread 已设置。 thread_ptr 返回的对象是 JNI 本地引用,必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER thread_ptr NULL

获取所有线程

jvmtiError
GetAllThreads(jvmtiEnv* env,
      jint* threads_count_ptr,
      jthread** threads_ptr)
获取附加到 VM 的所有实时平台线程。线程列表包括 代理线程 。它不包括虚拟线程。如果 java.lang.Thread.isAlive() 将返回 true,则线程处于活动状态,也就是说,线程已启动且尚未终止。线程的范围由 JVM 的上下文决定 TI 环境,通常是附加到 VM 的所有线程。
只能在直播阶段调用
4
1.0
能力
所需功能
参数
Name Type Description
threads_count_ptr jint* 返回时,指向线程数。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
threads_ptr jthread** 返回时,指向一组引用,每个线程一个。
Agent 传递一个指向 jthread* 的指针。返回时,jthread* 指向新分配的大小为 *threads_count_ptr 的数组。该数组应使用 Deallocate 释放。 threads_ptr 返回的对象是 JNI 本地引用,必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER threads_count_ptr NULL
JVMTI_ERROR_NULL_POINTER threads_ptr NULL

挂起线程

jvmtiError
SuspendThread(jvmtiEnv* env,
      jthread thread)
挂起指定的线程。如果指定了调用线程,则此函数将不会返回,直到其他某个线程调用 ResumeThread 。如果线程当前挂起,则此函数不执行任何操作并返回错误。
只能在直播阶段调用
5
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_suspend 可以暂停和恢复线程
参数
Name Type Description
thread jthread 要挂起的线程。如果 threadNULL ,则使用当前线程。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_suspend 。使用 AddCapabilities
JVMTI_ERROR_THREAD_SUSPENDED 线程已暂停。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。

挂起线程列表

jvmtiError
SuspendThreadList(jvmtiEnv* env,
      jint request_count,
      const jthread* request_list,
      jvmtiError* results)
挂起 request_list 数组中指定的 request_count 个线程。可以使用 ResumeThreadList ResumeThread 恢复线程。如果在 request_list 数组中指定了调用线程,则此函数将不会返回,直到某个其他线程恢复它。线程挂起遇到的错误在results 数组中返回,不是在这个函数的返回值中。当前挂起的线程不会改变状态。
只能在直播阶段调用
92
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_suspend 可以暂停和恢复线程
参数
Name Type Description
request_count jint 要挂起的线程数。
request_list const jthread* 要挂起的线程列表。
代理传入 jthreadrequest_count 个元素的数组。
results jvmtiError* 代理提供了 request_count 个元素的数组。返回时,填充相应线程挂起的错误代码。如果线程被此调用挂起,错误代码将为 JVMTI_ERROR_NONE 。可能的错误代码是为 SuspendThread 指定的代码。
Agent 传递一个足够大的数组来容纳 jvmtiErrorrequest_count 个元素。忽略数组元素的传入值。返回时,元素已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_suspend 。使用 AddCapabilities
JVMTI_ERROR_ILLEGAL_ARGUMENT request_count 小于 0
JVMTI_ERROR_NULL_POINTER request_list NULL
JVMTI_ERROR_NULL_POINTER results NULL

挂起所有虚拟线程

jvmtiError
SuspendAllVirtualThreads(jvmtiEnv* env,
      jint except_count,
      const jthread* except_list)
SuspendAllVirtualThreads 是 Java 平台的预览 API。 预览功能可能会在未来的版本中删除,或升级为 Java 平台的永久功能。
挂起除异常列表中的虚拟线程之外的所有虚拟线程。当前挂起的虚拟线程不会改变状态。可以使用 ResumeAllVirtualThreads ResumeThreadList ResumeThread 恢复虚拟线程。
只能在直播阶段调用
118
19
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_suspend 可以暂停和恢复线程
can_support_virtual_threads 可以支持虚拟线程
参数
Name Type Description
except_count jint 线程列表中不被挂起的线程数。
except_list const jthread * 不被挂起的线程列表。
代理传入 jthreadexcept_count 个元素的数组。如果 except_listNULL ,如果是 except_count == 0 则不是错误。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_suspend 。使用 AddCapabilities
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_support_virtual_threads 。使用 AddCapabilities
JVMTI_ERROR_INVALID_THREAD except_list 中的线程无效。
JVMTI_ERROR_NULL_POINTER except_list NULL 并且 except_count 都是非零的。
JVMTI_ERROR_ILLEGAL_ARGUMENT except_count 小于 0

恢复线程

jvmtiError
ResumeThread(jvmtiEnv* env,
      jthread thread)
恢复挂起的线程。当前通过 JVM 挂起的任何线程 TI 暂停功能(例如 SuspendThread )将恢复执行;所有其他线程不受影响。
只能在直播阶段调用
6
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_suspend 可以暂停和恢复线程
参数
Name Type Description
thread jthread 要恢复的线程。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_suspend 。使用 AddCapabilities
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未暂停。
JVMTI_ERROR_INVALID_TYPESTATE 线程的状态已被修改,现在不一致。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。

恢复线程列表

jvmtiError
ResumeThreadList(jvmtiEnv* env,
      jint request_count,
      const jthread* request_list,
      jvmtiError* results)
恢复 request_list 数组中指定的 request_count 个线程。通过 JVM 挂起的任何线程 TI 暂停功能(例如 SuspendThreadList )将恢复执行。
只能在直播阶段调用
93
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_suspend 可以暂停和恢复线程
参数
Name Type Description
request_count jint 要恢复的线程数。
request_list const jthread* 要恢复的线程。
代理传入 jthreadrequest_count 个元素的数组。
results jvmtiError* 代理提供的 request_count 元素数组。返回时,填充相应线程恢复的错误代码。如果线程被此调用挂起,错误代码将为 JVMTI_ERROR_NONE 。可能的错误代码是为 ResumeThread 指定的代码。
Agent 传递一个足够大的数组来容纳 jvmtiErrorrequest_count 个元素。忽略数组元素的传入值。返回时,元素已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_suspend 。使用 AddCapabilities
JVMTI_ERROR_ILLEGAL_ARGUMENT request_count 小于 0
JVMTI_ERROR_NULL_POINTER request_list NULL
JVMTI_ERROR_NULL_POINTER results NULL

恢复所有虚拟线程

jvmtiError
ResumeAllVirtualThreads(jvmtiEnv* env,
      jint except_count,
      const jthread* except_list)
ResumeAllVirtualThreads 是 Java 平台的预览 API。 预览功能可能会在未来的版本中删除,或升级为 Java 平台的永久功能。
恢复除异常列表中的虚拟线程之外的所有虚拟线程。当前恢复的虚拟线程不会改变状态。可以使用 SuspendAllVirtualThreads SuspendThreadList SuspendThread 暂停虚拟线程。
只能在直播阶段调用
119
19
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_suspend 可以暂停和恢复线程
can_support_virtual_threads 可以支持虚拟线程
参数
Name Type Description
except_count jint 线程列表中不被恢复的线程数。
except_list const jthread * 不恢复的线程列表。
代理传入 jthreadexcept_count 个元素的数组。如果 except_listNULL ,如果是 except_count == 0 则不是错误。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_suspend 。使用 AddCapabilities
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_support_virtual_threads 。使用 AddCapabilities
JVMTI_ERROR_INVALID_THREAD except_list 中的线程无效。
JVMTI_ERROR_NULL_POINTER except_list NULL 并且 except_count 都是非零的。
JVMTI_ERROR_ILLEGAL_ARGUMENT except_count 小于 0

停止线程

jvmtiError
StopThread(jvmtiEnv* env,
      jthread thread,
      jobject exception)
将指定的异步异常发送到指定的平台线程。
只能在直播阶段调用
7
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_signal_thread 可以向线程发送停止或中断
参数
Name Type Description
thread jthread 线程停止。 thread 可能不是虚拟线程。否则,将返回错误代码JVMTI_ERROR_UNSUPPORTED_OPERATION
exception jobject 异步异常对象。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_signal_thread 能力。使用 AddCapabilities
JVMTI_ERROR_UNSUPPORTED_OPERATION thread 是一个虚拟线程。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_INVALID_OBJECT exception 不是对象。

中断线程

jvmtiError
InterruptThread(jvmtiEnv* env,
      jthread thread)
中断指定的线程(类似于 java.lang.Thread.interrupt )。
只能在直播阶段调用
8
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_signal_thread 可以向线程发送停止或中断
参数
Name Type Description
thread jthread 要中断的线程。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_signal_thread 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。

获取线程信息

typedef struct {
  char* name;
  jint priority;
  jboolean is_daemon;
  jthreadGroup thread_group;
  jobject context_class_loader;
} jvmtiThreadInfo;
jvmtiError
GetThreadInfo(jvmtiEnv* env,
      jthread thread,
      jvmtiThreadInfo* info_ptr)
获取线程信息。 jvmtiThreadInfo 结构的字段填充了指定线程的详细信息。
只能在直播阶段调用
9
1.0
能力
所需功能

jvmtiThreadInfo - 线程信息结构
Field Type Description
name char* 线程名称,编码为 修改后的 UTF-8 字符串。
priority jint 线程优先级。请参阅线程优先级常量:jvmtiThreadPriority 。虚拟线程的优先级始终是 JVMTI_THREAD_NORM_PRIORITY
is_daemon jboolean 这是守护线程吗?虚拟线程的守护进程状态始终为 JNI_TRUE
thread_group jthreadGroup 该线程所属的线程组。 NULL 如果线程已终止。
context_class_loader jobject 与此线程关联的上下文类加载器。
参数
Name Type Description
thread jthread 要查询的线程。如果 threadNULL ,则使用当前线程。
info_ptr jvmtiThreadInfo* 返回时,填充了描述指定线程的信息。
Agent 传递一个指向 jvmtiThreadInfo 的指针。返回时,jvmtiThreadInfo 已设置。 jvmtiThreadInfoname 字段中返回的指针是一个新分配的数组。该数组应使用 Deallocate 释放。 jvmtiThreadInfothread_group 字段中返回的对象是 JNI 本地引用,必须是 管理jvmtiThreadInfo 的字段 context_class_loader 中返回的对象是 JNI 本地引用,必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_NULL_POINTER info_ptr NULL

获取拥有的显示器信息

jvmtiError
GetOwnedMonitorInfo(jvmtiEnv* env,
      jthread thread,
      jint* owned_monitor_count_ptr,
      jobject** owned_monitors_ptr)
获取有关指定线程拥有的监视器的信息。
只能在直播阶段调用
10
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_get_owned_monitor_info 可以获得有关监视器所有权的信息 - GetOwnedMonitorInfo
参数
Name Type Description
thread jthread 要查询的线程。如果 threadNULL ,则使用当前线程。
owned_monitor_count_ptr jint* 返回的监视器数。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
owned_monitors_ptr jobject** 拥有的监视器数组。
Agent 传递一个指向 jobject* 的指针。返回时,jobject* 指向新分配的大小为 *owned_monitor_count_ptr 的数组。该数组应使用 Deallocate 释放。 owned_monitors_ptr 返回的对象是 JNI 本地引用,必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_get_owned_monitor_info 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_NULL_POINTER owned_monitor_count_ptr NULL
JVMTI_ERROR_NULL_POINTER owned_monitors_ptr NULL

获取拥有的监视器堆栈深度信息

typedef struct {
  jobject monitor;
  jint stack_depth;
} jvmtiMonitorStackDepthInfo;
jvmtiError
GetOwnedMonitorStackDepthInfo(jvmtiEnv* env,
      jthread thread,
      jint* monitor_info_count_ptr,
      jvmtiMonitorStackDepthInfo** monitor_info_ptr)
获取有关指定线程拥有的监视器以及锁定它们的堆栈帧深度的信息。
只能在直播阶段调用
153
1.1
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_get_owned_monitor_stack_depth_info 可以获取有关具有堆栈深度的拥有监视器的信息 - GetOwnedMonitorStackDepthInfo

jvmtiMonitorStackDepthInfo - 监控堆栈深度信息结构
Field Type Description
monitor jobject 自有显示器。
stack_depth jint 堆栈深度。对应于 栈帧函数 中使用的堆栈深度。即零为当前帧,一为调用当前帧的帧。如果实现无法确定堆栈深度(例如,对于 JNI MonitorEnter 获取的监视器),则为负数。
参数
Name Type Description
thread jthread 要查询的线程。如果 threadNULL ,则使用当前线程。
monitor_info_count_ptr jint* 返回的监视器数。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
monitor_info_ptr jvmtiMonitorStackDepthInfo ** 拥有的监视器深度信息的数组。
Agent 传递一个指向 jvmtiMonitorStackDepthInfo* 的指针。返回时,jvmtiMonitorStackDepthInfo* 指向新分配的大小为 *monitor_info_count_ptr 的数组。该数组应使用 Deallocate 释放。 jvmtiMonitorStackDepthInfomonitor 字段中返回的对象是 JNI 本地引用,必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_get_owned_monitor_stack_depth_info 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_NULL_POINTER monitor_info_count_ptr NULL
JVMTI_ERROR_NULL_POINTER monitor_info_ptr NULL

获取当前竞争监视器

jvmtiError
GetCurrentContendedMonitor(jvmtiEnv* env,
      jthread thread,
      jobject* monitor_ptr)
通过 java.lang.Object.wait 获取指定线程正在等待进入或等待重新获得其监视器的对象(如果有)。
只能在直播阶段调用
11
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_get_current_contended_monitor 可以GetCurrentContendedMonitor
参数
Name Type Description
thread jthread 要查询的线程。如果 threadNULL ,则使用当前线程。
monitor_ptr jobject* 返回时,填充当前竞争的监视器,如果没有则为 NULL。
代理传递一个指向 jobject 的指针。返回时,jobject 已设置。 monitor_ptr 返回的对象是 JNI 本地引用,必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_get_current_contended_monitor 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_NULL_POINTER monitor_ptr NULL

代理启动函数

typedef void (JNICALL *jvmtiStartFunction)
  (jvmtiEnv* jvmti_env,
   JNIEnv* jni_env,
   void* arg);
代理提供的回调函数。此函数是以 RunAgentThread 开头的代理线程的入口点。
参数
Name Type Description
jvmti_env jvmtiEnv * 虚拟机 TI 环境。
jni_env JNIEnv * JNI 环境。
arg void * 传递给 RunAgentThread arg 参数。

运行代理线程

jvmtiError
RunAgentThread(jvmtiEnv* env,
      jthread thread,
      jvmtiStartFunction proc,
      const void* arg,
      jint priority)
开始执行代理线程。具有指定的本机功能。参数 arg 作为其单个参数转发给 开始功能(用 proc 指定)。此函数允许创建代理线程来处理与另一个进程的通信或处理事件,而无需加载 java.lang.Thread 的特殊子类或 java.lang.Runnable 的实现者。相反,创建的线程可以完全以本机代码运行。但是,创建的线程确实需要一个新创建的 java.lang.Thread 实例(由参数 thread 引用),它将与之关联。可以使用 JNI 调用创建线程对象。
为方便起见,提供了以下公共线程优先级:
线程优先级常量
持续的 Value Description
JVMTI_THREAD_MIN_PRIORITY 1 最低可能的线程优先级
JVMTI_THREAD_NORM_PRIORITY 5 普通线程优先级
JVMTI_THREAD_MAX_PRIORITY 10 最大可能的线程优先级
新线程作为具有指定 priority 的守护线程启动。如果启用,将发送 ThreadStart 事件。
由于线程已经启动,除非线程立即终止,否则当此函数返回时线程将处于活动状态。
线程的线程组被忽略——具体来说,线程没有添加到线程组中,并且在 Java 编程语言或 JVM 的线程组查询中都看不到线程 TI 级别。
该线程对 Java 编程语言查询不可见,但包含在 JVM 中 TI 查询(例如,GetAllThreads GetAllStackTraces )。
执行 proc 后,新线程将附加到 VM - 请参阅 附加到虚拟机 上的 JNI 文档。
只能在直播阶段调用
12
1.0
能力
所需功能
参数
Name Type Description
thread jthread 要运行的线程。 thread 可能不是虚拟线程。否则,将返回错误代码JVMTI_ERROR_UNSUPPORTED_OPERATION
proc jvmtiStartFunction 启动函数。
arg const void * 启动函数的参数。
Agent 传入一个指针。如果 argNULL ,则 NULL 将传递给启动函数。
priority jint 启动线程的优先级。 java.lang.Thread.setPriority 允许的任何线程优先级都可以使用,包括 jvmtiThreadPriority 中的线程优先级。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_PRIORITY priority 小于 JVMTI_THREAD_MIN_PRIORITY 或大于 JVMTI_THREAD_MAX_PRIORITY
JVMTI_ERROR_UNSUPPORTED_OPERATION thread 是一个虚拟线程。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_NULL_POINTER proc NULL

设置线程本地存储

jvmtiError
SetThreadLocalStorage(jvmtiEnv* env,
      jthread thread,
      const void* data)
VM 存储与每个环境线程对关联的指针值。这个指针值被称为线程本地存储.这个值是NULL除非用这个函数设置。代理可以分配存储线程特定信息的内存。通过设置线程本地存储,然后可以使用 GetThreadLocalStorage 访问它。
此函数由代理调用以设置 JVM 的值 TI 线程本地存储。虚拟机 TI 向代理提供指针大小的线程本地存储,可用于记录每个线程的信息。
只能在开始或直播阶段调用
103
1.0
能力
所需功能
参数
Name Type Description
thread jthread 存储到此线程。如果 threadNULL ,则使用当前线程。
data const void * 要输入到线程本地存储中的值。
Agent 传入一个指针。如果 dataNULL,则值设置为 NULL
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。

获取线程本地存储

jvmtiError
GetThreadLocalStorage(jvmtiEnv* env,
      jthread thread,
      void** data_ptr)
被agent调用获取JVM的值 TI 线程本地存储。
只能在开始或直播阶段调用
102
1.0
能力
所需功能
参数
Name Type Description
thread jthread 从此线程中检索。如果 threadNULL ,则使用当前线程。
data_ptr void** 返回线程本地存储值的指针。如果未使用 SetThreadLocalStorage 设置线程本地存储,则返回的指针为 NULL
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_NULL_POINTER data_ptr NULL


线程组

线程组函数: 线程组类型:

获取顶级线程组

jvmtiError
GetTopThreadGroups(jvmtiEnv* env,
      jint* group_count_ptr,
      jthreadGroup** groups_ptr)
返回 VM 中的所有顶级(无父级)线程组。
只能在直播阶段调用
13
1.0
能力
所需功能
参数
Name Type Description
group_count_ptr jint* 返回时,指向顶级线程组的数量。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
groups_ptr jthreadGroup** 返回时,指的是指向顶级线程组数组的指针。
Agent 传递一个指向 jthreadGroup* 的指针。返回时,jthreadGroup* 指向新分配的大小为 *group_count_ptr 的数组。该数组应使用 Deallocate 释放。 groups_ptr 返回的对象是 JNI 本地引用,必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER group_count_ptr NULL
JVMTI_ERROR_NULL_POINTER groups_ptr NULL

获取线程组信息

typedef struct {
  jthreadGroup parent;
  char* name;
  jint max_priority;
  jboolean is_daemon;
} jvmtiThreadGroupInfo;
jvmtiError
GetThreadGroupInfo(jvmtiEnv* env,
      jthreadGroup group,
      jvmtiThreadGroupInfo* info_ptr)
获取有关线程组的信息。 jvmtiThreadGroupInfo 结构的字段填充了指定线程组的详细信息。
只能在直播阶段调用
14
1.0
能力
所需功能

jvmtiThreadGroupInfo - 线程组信息结构
Field Type Description
parent jthreadGroup 父线程组。
name char* 线程组的名称,编码为 修改后的 UTF-8 字符串。
max_priority jint 此线程组的最大优先级。
is_daemon jboolean 这是守护进程线程组吗?
参数
Name Type Description
group jthreadGroup 要查询的线程组。
info_ptr jvmtiThreadGroupInfo* 返回时,填充了描述指定线程组的信息。
Agent 传递一个指向 jvmtiThreadGroupInfo 的指针。返回时,jvmtiThreadGroupInfo 已设置。 jvmtiThreadGroupInfo 的字段 parent 中返回的对象是 JNI 本地引用,必须是 管理jvmtiThreadGroupInfoname 字段中返回的指针是一个新分配的数组。该数组应使用 Deallocate 释放。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_THREAD_GROUP group 不是线程组对象。
JVMTI_ERROR_NULL_POINTER info_ptr NULL

获取线程组子项

jvmtiError
GetThreadGroupChildren(jvmtiEnv* env,
      jthreadGroup group,
      jint* thread_count_ptr,
      jthread** threads_ptr,
      jint* group_count_ptr,
      jthreadGroup** groups_ptr)
获取直播平台线程和该线程组中的子线程组。此函数不返回虚拟线程。
只能在直播阶段调用
15
1.0
能力
所需功能
参数
Name Type Description
group jthreadGroup 要查询的组。
thread_count_ptr jint* 返回时,指向此线程组中的活动线程数。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
threads_ptr jthread** 返回时,指向该线程组中活动线程的数组。
Agent 传递一个指向 jthread* 的指针。返回时,jthread* 指向新分配的大小为 *thread_count_ptr 的数组。该数组应使用 Deallocate 释放。 threads_ptr 返回的对象是 JNI 本地引用,必须是 管理
group_count_ptr jint* 返回时,指向子线程组的数量
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
groups_ptr jthreadGroup** 返回时,指向子线程组的数组。
Agent 传递一个指向 jthreadGroup* 的指针。返回时,jthreadGroup* 指向新分配的大小为 *group_count_ptr 的数组。该数组应使用 Deallocate 释放。 groups_ptr 返回的对象是 JNI 本地引用,必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_THREAD_GROUP group 不是线程组对象。
JVMTI_ERROR_NULL_POINTER thread_count_ptr NULL
JVMTI_ERROR_NULL_POINTER threads_ptr NULL
JVMTI_ERROR_NULL_POINTER group_count_ptr NULL
JVMTI_ERROR_NULL_POINTER groups_ptr NULL


栈帧

栈帧函数: 栈帧类型: 这些函数提供有关线程堆栈的信息。堆栈帧按深度引用。深度为零的帧是当前帧。
堆栈帧如中所述Java™ 虚拟机规范,第 3.6 章,也就是说,它们对应于方法调用(包括原生方法),但不对应于平台原生或VM内部框架。
A JVM TI 实现可能会使用方法调用来启动线程,并且相应的帧可能会包含在这些函数所呈现的堆栈中——也就是说,可能会显示比 main()run() 更深的帧。然而,这种表示必须在所有 JVM 中保持一致 使用堆栈帧或堆栈深度的 TI 功能。

栈帧信息结构

在此结构中返回有关堆栈帧的信息。
typedef struct {
  jmethodID method;
  jlocation location;
} jvmtiFrameInfo;
jvmtiFrameInfo - 栈帧信息结构
Field Type Description
method jmethodID 在此框架中执行的方法。
location jlocation 在此帧中执行的指令的索引。 -1 如果框架正在执行本地方法。

堆栈信息结构

在此结构中返回有关一组堆栈帧的信息。
typedef struct {
  jthread thread;
  jint state;
  jvmtiFrameInfo* frame_buffer;
  jint frame_count;
} jvmtiStackInfo;
jvmtiStackInfo - 堆栈信息结构
Field Type Description
thread jthread 返回时,跟踪线程。
state jint 返回时,线程状态。参见 GetThreadState
frame_buffer jvmtiFrameInfo * 返回时,此代理分配的缓冲区将填充堆栈帧信息。
frame_count jint 返回时,填入 frame_buffer 的记录数。这将是 min(max_frame_count ,堆栈深度).

获取堆栈跟踪

jvmtiError
GetStackTrace(jvmtiEnv* env,
      jthread thread,
      jint start_depth,
      jint max_frame_count,
      jvmtiFrameInfo* frame_buffer,
      jint* count_ptr)
获取有关线程堆栈的信息。如果 max_frame_count 小于堆栈深度,则返回 max_frame_count 最顶层帧,否则返回整个堆栈。最顶层的帧,即最近调用的帧,位于返回缓冲区的开头。
以下示例导致返回最多五个最顶层的帧,并且(如果有任何帧)打印当前正在执行的方法名称。
jvmtiFrameInfo frames[5];
jint count;
jvmtiError err;

err = (*jvmti)->GetStackTrace(jvmti, aThread, 0, 5,
                frames, &count);
if (err == JVMTI_ERROR_NONE && count >= 1) {
  char *methodName;
  err = (*jvmti)->GetMethodName(jvmti, frames[0].method,
            &methodName, NULL, NULL);
  if (err == JVMTI_ERROR_NONE) {
   printf("Executing method: %s", methodName);
  }
}
    
thread 无需暂停即可调用此函数。
GetLineNumberTable 函数可用于将位置映射到行号。请注意,此map可以延迟完成。
只能在直播阶段调用
104
1.0
能力
所需功能
参数
Name Type Description
thread jthread 获取此线程的堆栈跟踪。如果 threadNULL ,则使用当前线程。
start_depth jint 在此深度开始检索帧。如果非负,则从当前帧开始计数,检索到的第一帧深度为 start_depth 。例如,如果为零,则从当前帧开始;如果有,则从当前帧的调用者开始;如果是两个,则从当前帧的调用者的调用者开始;等等。如果为负数,则从最旧的帧以下开始计数,检索到的第一帧在深度堆栈深度 + start_depth ,其中堆栈深度是堆栈上的帧数。例如,如果为负数,则只检索最旧的帧;如果为负二,则从最旧的帧调用的帧开始。
max_frame_count jint 要检索的最大 jvmtiFrameInfo 记录数。
frame_buffer jvmtiFrameInfo * 返回时,此代理分配的缓冲区将填充堆栈帧信息。
Agent 传递一个大到足以容纳 jvmtiFrameInfomax_frame_count 个元素的数组。忽略数组元素的传入值。返回时,设置了 *count_ptr 个元素。
count_ptr jint* 返回时,指向填写的记录数。对于非负 start_depth ,这将是 min(max_frame_count ,堆栈深度 - start_depth)。对于负数 start_depth ,这将是 min(max_frame_count , -start_depth )。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_ILLEGAL_ARGUMENT start_depth 为正且大于或等于堆栈深度.或者start_depth 为负且小于-堆栈深度.
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_ILLEGAL_ARGUMENT max_frame_count 小于 0
JVMTI_ERROR_NULL_POINTER frame_buffer NULL
JVMTI_ERROR_NULL_POINTER count_ptr NULL

获取所有堆栈跟踪

jvmtiError
GetAllStackTraces(jvmtiEnv* env,
      jint max_frame_count,
      jvmtiStackInfo** stack_info_ptr,
      jint* thread_count_ptr)
获取附加到 VM 的所有实时平台线程的堆栈跟踪。该列表包括 代理线程 的堆栈跟踪。它不包括虚拟线程的堆栈跟踪。
如果 max_frame_count 小于堆栈深度,则为该线程返回 max_frame_count 最顶层帧,否则返回整个堆栈。最顶层的帧,即最近调用的帧,位于返回缓冲区的开头。
同时收集所有堆栈,也就是说,在一个线程和下一个线程的采样之间,线程状态或堆栈不会发生任何变化。不需要挂起线程。
jvmtiStackInfo *stack_info;
jint thread_count;
int ti;
jvmtiError err;

err = (*jvmti)->GetAllStackTraces(jvmti, MAX_FRAMES, &stack_info, &thread_count);
if (err != JVMTI_ERROR_NONE) {
  ...
}
for (ti = 0; ti < thread_count; ++ti) {
  jvmtiStackInfo *infop = &stack_info[ti];
  jthread thread = infop->thread;
  jint state = infop->state;
  jvmtiFrameInfo *frames = infop->frame_buffer;
  int fi;

  myThreadAndStatePrinter(thread, state);
  for (fi = 0; fi < infop->frame_count; fi++) {
   myFramePrinter(frames[fi].method, frames[fi].location);
  }
}
/* this one Deallocate call frees all data allocated by GetAllStackTraces */
err = (*jvmti)->Deallocate(jvmti, stack_info);
    
只能在直播阶段调用
100
1.0
能力
所需功能
参数
Name Type Description
max_frame_count jint 每个线程要检索的最大 jvmtiFrameInfo 记录数。
stack_info_ptr jvmtiStackInfo ** 返回时,此缓冲区会填充每个线程的堆栈信息。 jvmtiStackInfo 记录的数量由 thread_count_ptr 决定。
请注意,分配此缓冲区以包含 jvmtiStackInfo.frame_buffer 指向的 jvmtiFrameInfo 缓冲区。这些缓冲区不得单独释放。
Agent 传递一个指向 jvmtiStackInfo* 的指针。返回时,jvmtiStackInfo* 指向一个新分配的数组。该数组应使用 Deallocate 释放。 jvmtiStackInfothread 字段中返回的对象是 JNI 本地引用,必须是 管理
thread_count_ptr jint* 跟踪的线程数。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_ILLEGAL_ARGUMENT max_frame_count 小于 0
JVMTI_ERROR_NULL_POINTER stack_info_ptr NULL
JVMTI_ERROR_NULL_POINTER thread_count_ptr NULL

获取线程列表堆栈跟踪

jvmtiError
GetThreadListStackTraces(jvmtiEnv* env,
      jint thread_count,
      const jthread* thread_list,
      jint max_frame_count,
      jvmtiStackInfo** stack_info_ptr)
获取有关所提供线程堆栈的信息。如果 max_frame_count 小于堆栈深度,则为该线程返回 max_frame_count 最顶层帧,否则返回整个堆栈。最顶层的帧,即最近调用的帧,位于返回缓冲区的开头。
同时收集所有堆栈,也就是说,在采样一个线程和下一个线程之间,线程状态或堆栈不会发生任何变化。不需要挂起线程。
如果在收集堆栈信息之前线程尚未启动或终止,则将返回零长度堆栈(jvmtiStackInfo.frame_count 将为零)并且可以检查线程 jvmtiStackInfo.state
请参阅类似函数 GetAllStackTraces 的示例。
只能在直播阶段调用
101
1.0
能力
所需功能
参数
Name Type Description
thread_count jint 要跟踪的线程数。
thread_list const jthread* 要跟踪的线程列表。
代理传入 jthreadthread_count 个元素的数组。
max_frame_count jint 每个线程要检索的最大 jvmtiFrameInfo 记录数。
stack_info_ptr jvmtiStackInfo ** 返回时,此缓冲区会填充每个线程的堆栈信息。 jvmtiStackInfo 记录的数量由 thread_count 决定。
请注意,分配此缓冲区以包含 jvmtiStackInfo.frame_buffer 指向的 jvmtiFrameInfo 缓冲区。这些缓冲区不得单独释放。
Agent 传递一个指向 jvmtiStackInfo* 的指针。返回时,jvmtiStackInfo* 指向新分配的大小为 *thread_count 的数组。该数组应使用 Deallocate 释放。 jvmtiStackInfothread 字段中返回的对象是 JNI 本地引用,必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_THREAD thread_list 中的元素不是线程对象。
JVMTI_ERROR_ILLEGAL_ARGUMENT thread_count 小于 0
JVMTI_ERROR_NULL_POINTER thread_list NULL
JVMTI_ERROR_ILLEGAL_ARGUMENT max_frame_count 小于 0
JVMTI_ERROR_NULL_POINTER stack_info_ptr NULL

获取帧数

jvmtiError
GetFrameCount(jvmtiEnv* env,
      jthread thread,
      jint* count_ptr)
获取当前在指定线程的调用堆栈中的帧数。
如果为主动执行字节码的线程调用此函数(例如,不是当前线程且未挂起),则返回的信息是瞬态的。
只能在直播阶段调用
16
1.0
能力
所需功能
参数
Name Type Description
thread jthread 要查询的线程。如果 threadNULL ,则使用当前线程。
count_ptr jint* 返回时,指向调用堆栈中的帧数。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_NULL_POINTER count_ptr NULL

流行框架

jvmtiError
PopFrame(jvmtiEnv* env,
      jthread thread)
弹出 thread 堆栈的当前帧。弹出一帧会将您带到上一帧。当线程恢复时,线程的执行状态将重置为调用被调用方法之前的状态。那就是(使用Java™ 虚拟机规范术语): 但是请注意,在被调用方法中发生的对参数的任何更改都将保留;当执行继续时,要执行的第一条指令将是调用。
在调用 PopFrame 和恢复线程之间,堆栈的状态是未定义的。要弹出第一帧之后的帧,必须重复这三个步骤:
通过调用被调用方法(如果是synchronized方法)获得的锁和通过在被调用方法中进入synchronized块获得的锁被释放。注意:这不适用于本机锁或 java.util.concurrent.locks 锁。
finally 块不被执行。
全局状态的变化没有得到解决,因此保持不变。
指定的线程必须挂起或者必须是当前线程。
被调用方法和调用方法都必须是非原生 Java 编程语言方法。
无虚拟机 TI 事件由此函数生成。
只能在直播阶段调用
80
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_pop_frame 可以从堆栈中弹出帧 - PopFrame
参数
Name Type Description
thread jthread 要弹出其当前帧的线程。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_pop_frame 。使用 AddCapabilities
JVMTI_ERROR_OPAQUE_FRAME 被调用或调用的方法是本地方法。该实现无法弹出此帧。
JVMTI_ERROR_OPAQUE_FRAME 该线程是虚拟线程,实现无法弹出此帧。
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未挂起且不是当前线程。
JVMTI_ERROR_NO_MORE_FRAMES 调用堆栈上的堆栈帧少于两个。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。

获取帧位置

jvmtiError
GetFrameLocation(jvmtiEnv* env,
      jthread thread,
      jint depth,
      jmethodID* method_ptr,
      jlocation* location_ptr)
对于 Java 编程语言框架,返回当前正在执行的指令的位置。
只能在直播阶段调用
19
1.0
能力
所需功能
参数
Name Type Description
thread jthread 要查询的框架的线程。如果 threadNULL ,则使用当前线程。
depth jint 要查询的帧的深度。
method_ptr jmethodID* 返回时,指向当前位置的方法。
Agent 传递一个指向 jmethodID 的指针。返回时,jmethodID 已设置。
location_ptr jlocation* 返回时,指向当前执行指令的索引。如果框架正在执行本机方法,则设置为 -1
代理将指针传递给 jlocation 。返回时,jlocation 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_ILLEGAL_ARGUMENT depth 小于零。
JVMTI_ERROR_NO_MORE_FRAMES 指定的 depth 处没有堆栈帧。
JVMTI_ERROR_NULL_POINTER method_ptr NULL
JVMTI_ERROR_NULL_POINTER location_ptr NULL

通知帧弹出

jvmtiError
NotifyFramePop(jvmtiEnv* env,
      jthread thread,
      jint depth)
当当前位于 depth 的帧从堆栈中弹出时,生成一个 FramePop 事件。有关详细信息,请参阅 FramePop 事件。只有对应于非本机 Java 编程语言方法的框架才能接收通知。
指定的线程必须挂起或者必须是当前线程。
只能在直播阶段调用
20
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_generate_frame_pop_events 可以 set 从而获得 FramePop 事件
参数
Name Type Description
thread jthread 将为其生成框架弹出事件的框架的线程。如果 threadNULL ,则使用当前线程。
depth jint 将为其生成框架弹出事件的框架的深度。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_generate_frame_pop_events 能力。使用 AddCapabilities
JVMTI_ERROR_OPAQUE_FRAME depth 处的框架正在执行本地方法。
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未挂起且不是当前线程。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_ILLEGAL_ARGUMENT depth 小于零。
JVMTI_ERROR_NO_MORE_FRAMES 指定的 depth 处没有堆栈帧。


强制提前返回

强制提前返回功能: 这些函数允许代理强制方法在其执行期间的任何时候返回。提前返回的方法称为被调用的方法.被调用的方法是当前方法(由Java™ 虚拟机规范,第 3.6 章) 在调用函数时针对指定的线程。
指定的线程必须挂起或者必须是当前线程。在此线程上恢复执行 Java 编程语言代码时发生返回。在调用这些函数之一和恢复线程执行之间,堆栈的状态是未定义的。
在被调用的方法中没有执行进一步的指令。具体来说,finally 块不会被执行。注意:这可能会导致应用程序中出现不一致的状态。
通过调用被调用方法(如果是synchronized方法)获得的锁和通过在被调用方法中进入synchronized块获得的锁被释放。注意:这不适用于本机锁或 java.util.concurrent.locks 锁。
事件(例如 MethodExit )的生成与正常返回中的一样。
被调用的方法必须是非本机 Java 编程语言方法。在堆栈上只有一帧的线程上强制返回会导致线程在恢复时退出。

强制提前返回 - 对象

jvmtiError
ForceEarlyReturnObject(jvmtiEnv* env,
      jthread thread,
      jobject value)
此函数可用于从结果类型为 ObjectObject 的子类的方法返回。
只能在直播阶段调用
81
1.1
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_force_early_return 可以提前从方法返回,如 强制提前返回类别 中所述。
参数
Name Type Description
thread jthread 当前帧要提前返回的线程。如果 threadNULL ,则使用当前线程。
value jobject 被调用帧的返回值。一个对象或 NULL
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_force_early_return 能力。使用 AddCapabilities
JVMTI_ERROR_OPAQUE_FRAME 试图从与本机方法对应的帧提前返回。该线程是虚拟线程,实现无法强制其当前帧返回。或者实现无法在此框架上提供此功能。
JVMTI_ERROR_TYPE_MISMATCH 被调用方法的结果类型不是 ObjectObject 的子类。
JVMTI_ERROR_TYPE_MISMATCH 提供的 value 与被调用方法的结果类型不兼容。
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未挂起且不是当前线程。
JVMTI_ERROR_NO_MORE_FRAMES 调用堆栈上没有更多帧。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_INVALID_OBJECT value 不是对象。

强制提前返回 - Int

jvmtiError
ForceEarlyReturnInt(jvmtiEnv* env,
      jthread thread,
      jint value)
此函数可用于从结果类型为 intshortcharbyteboolean 的方法返回。
只能在直播阶段调用
82
1.1
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_force_early_return 可以提前从方法返回,如 强制提前返回类别 中所述。
参数
Name Type Description
thread jthread 当前帧要提前返回的线程。如果 threadNULL ,则使用当前线程。
value jint 被调用帧的返回值。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_force_early_return 能力。使用 AddCapabilities
JVMTI_ERROR_OPAQUE_FRAME 试图从与本机方法对应的帧提前返回。该线程是虚拟线程,实现无法强制其当前帧返回。或者实现无法在此框架上提供此功能。
JVMTI_ERROR_TYPE_MISMATCH 被调用方法的结果类型不是 intshortcharbyteboolean
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未挂起且不是当前线程。
JVMTI_ERROR_NO_MORE_FRAMES 调用堆栈上没有帧。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。

强制提前返回 - 长

jvmtiError
ForceEarlyReturnLong(jvmtiEnv* env,
      jthread thread,
      jlong value)
此函数可用于从结果类型为 long 的方法返回。
只能在直播阶段调用
83
1.1
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_force_early_return 可以提前从方法返回,如 强制提前返回类别 中所述。
参数
Name Type Description
thread jthread 当前帧要提前返回的线程。如果 threadNULL ,则使用当前线程。
value jlong 被调用帧的返回值。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_force_early_return 能力。使用 AddCapabilities
JVMTI_ERROR_OPAQUE_FRAME 试图从与本机方法对应的帧提前返回。该线程是虚拟线程,实现无法强制其当前帧返回。或者实现无法在此框架上提供此功能。
JVMTI_ERROR_TYPE_MISMATCH 被调用方法的结果类型不是 long
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未挂起且不是当前线程。
JVMTI_ERROR_NO_MORE_FRAMES 调用堆栈上没有帧。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。

强制提前返回 - 浮动

jvmtiError
ForceEarlyReturnFloat(jvmtiEnv* env,
      jthread thread,
      jfloat value)
此函数可用于从结果类型为 float 的方法返回。
只能在直播阶段调用
84
1.1
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_force_early_return 可以提前从方法返回,如 强制提前返回类别 中所述。
参数
Name Type Description
thread jthread 当前帧要提前返回的线程。如果 threadNULL ,则使用当前线程。
value jfloat 被调用帧的返回值。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_force_early_return 能力。使用 AddCapabilities
JVMTI_ERROR_OPAQUE_FRAME 试图从与本机方法对应的帧提前返回。该线程是虚拟线程,实现无法强制其当前帧返回。或者实现无法在此框架上提供此功能。
JVMTI_ERROR_TYPE_MISMATCH 被调用方法的结果类型不是 float
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未挂起且不是当前线程。
JVMTI_ERROR_NO_MORE_FRAMES 调用堆栈上没有帧。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。

强制提前返回 - 双

jvmtiError
ForceEarlyReturnDouble(jvmtiEnv* env,
      jthread thread,
      jdouble value)
此函数可用于从结果类型为 double 的方法返回。
只能在直播阶段调用
85
1.1
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_force_early_return 可以提前从方法返回,如 强制提前返回类别 中所述。
参数
Name Type Description
thread jthread 当前帧要提前返回的线程。如果 threadNULL ,则使用当前线程。
value jdouble 被调用帧的返回值。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_force_early_return 能力。使用 AddCapabilities
JVMTI_ERROR_OPAQUE_FRAME 试图从与本机方法对应的帧提前返回。该线程是虚拟线程,实现无法强制其当前帧返回。或者实现无法在此框架上提供此功能。
JVMTI_ERROR_TYPE_MISMATCH 被调用方法的结果类型不是 double
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未挂起且不是当前线程。
JVMTI_ERROR_NO_MORE_FRAMES 调用堆栈上没有帧。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。

强制提前返回 - 无效

jvmtiError
ForceEarlyReturnVoid(jvmtiEnv* env,
      jthread thread)
此函数可用于从没有结果类型的方法返回。也就是说,调用的方法必须声明为 void
只能在直播阶段调用
86
1.1
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_force_early_return 可以提前从方法返回,如 强制提前返回类别 中所述。
参数
Name Type Description
thread jthread 当前帧要提前返回的线程。如果 threadNULL ,则使用当前线程。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_force_early_return 能力。使用 AddCapabilities
JVMTI_ERROR_OPAQUE_FRAME 试图从与本机方法对应的帧提前返回。该线程是虚拟线程,实现无法强制其当前帧返回。或者实现无法在此框架上提供此功能。
JVMTI_ERROR_TYPE_MISMATCH 被调用的方法有一个结果类型。
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未挂起且不是当前线程。
JVMTI_ERROR_NO_MORE_FRAMES 调用堆栈上没有帧。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。


堆函数: 堆函数类型: 堆类型: 堆标志和常量: 这些函数用于分析堆。功能包括查看堆中的对象和标记这些对象的能力。

对象标签

A tag是与对象关联的值。标签由代理使用 SetTag 函数或回调函数(如 jvmtiHeapIterationCallback )显式设置。
标签是本地环境;也就是说,一个环境的标签在另一个环境中是不可见的。
标签是 jlong 值,可以简单地用于标记对象或存储指向更详细信息的指针。未标记的对象的标记为零。将标签设置为零会使对象不带标签。

堆回调函数

遍历堆并递归地遵循对象引用的堆函数使用代理提供的回调函数来传递信息。
这些堆回调函数必须遵守以下限制——这些回调不能使用 JNI 函数。这些回调不能使用 JVM TI 功能除回调安全专门允许此类使用的功能(请参阅原始监视器、内存管理和环境本地存储功能)。
实现可以在内部线程或调用迭代函数的线程上调用回调。堆回调是单线程的——一次不会调用多个回调。
堆过滤器标志可用于防止基于对象或其类的标记状态的报告。如果未设置标志(jint 为零),则不会过滤掉对象。
堆过滤器标志
持续的 Value Description
JVMTI_HEAP_FILTER_TAGGED 0x4 过滤掉标记的对象。不包括标记的对象。
JVMTI_HEAP_FILTER_UNTAGGED 0x8 过滤掉未标记的对象。不包括未标记的对象。
JVMTI_HEAP_FILTER_CLASS_TAGGED 0x10 过滤掉带有标记类的对象。不包括其类被标记的对象。
JVMTI_HEAP_FILTER_CLASS_UNTAGGED 0x20 过滤掉具有未标记类的对象。不包括其类未标记的对象。
堆访问控制标志由堆回调返回,可用于中止迭代。对于 堆引用回调 ,它也可以用于修剪遍历引用的图形(JVMTI_VISIT_OBJECTS 未设置)。
堆访问控制标志
持续的 Value Description
JVMTI_VISIT_OBJECTS 0x100 如果我们正在访问一个对象,并且如果这个回调是由 FollowReferences 发起的,则遍历这个对象的引用。否则忽略。
JVMTI_VISIT_ABORT 0x8000 中止迭代。忽略所有其他位。
堆引用枚举由 堆引用回调原始字段回调 提供,用于描述所报告的引用类型。
堆引用枚举 (jvmtiHeapReferenceKind)
持续的 Value Description
JVMTI_HEAP_REFERENCE_CLASS 1 从一个对象到它的类的引用。
JVMTI_HEAP_REFERENCE_FIELD 2 从对象到其实例字段之一的值的引用。
JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT 3 从数组到其元素之一的引用。
JVMTI_HEAP_REFERENCE_CLASS_LOADER 4 从一个类到它的类加载器的引用。
JVMTI_HEAP_REFERENCE_SIGNERS 5 从一个类到它的 signers 数组的引用。
JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN 6 从一个类到它的保护域的引用。
JVMTI_HEAP_REFERENCE_INTERFACE 7 从一个类到它的接口之一的引用。注意:接口是通过常量池引用定义的,因此引用的接口也可以使用 JVMTI_HEAP_REFERENCE_CONSTANT_POOL 引用类型进行报告。
JVMTI_HEAP_REFERENCE_STATIC_FIELD 8 从一个类到它的静态字段之一的值的引用。
JVMTI_HEAP_REFERENCE_CONSTANT_POOL 9 从类到常量池中已解析条目的引用。
JVMTI_HEAP_REFERENCE_SUPERCLASS 10 从一个类到它的超类的引用。如果超类是 java.lang.Object 则不会发送回调。注意:加载的类通过常量池引用定义超类,因此引用的超类也可以使用 JVMTI_HEAP_REFERENCE_CONSTANT_POOL 引用类型进行报告。
JVMTI_HEAP_REFERENCE_JNI_GLOBAL 21 堆根引用:JNI 全局引用。
JVMTI_HEAP_REFERENCE_SYSTEM_CLASS 22 堆根引用:系统类。
JVMTI_HEAP_REFERENCE_MONITOR 23 堆根引用:monitor。
JVMTI_HEAP_REFERENCE_STACK_LOCAL 24 堆根引用:栈上的局部变量。
JVMTI_HEAP_REFERENCE_JNI_LOCAL 25 堆根引用:JNI 本地引用。
JVMTI_HEAP_REFERENCE_THREAD 26 堆根引用:线程。
JVMTI_HEAP_REFERENCE_OTHER 27 堆根引用:其他堆根引用。
基本类型的单个字符类型描述符的定义。
原始类型枚举 (jvmtiPrimitiveType)
持续的 Value Description
JVMTI_PRIMITIVE_TYPE_BOOLEAN 90 'Z' - Java 编程语言 boolean - JNI jboolean
JVMTI_PRIMITIVE_TYPE_BYTE 66 'B' - Java 编程语言 byte - JNI jbyte
JVMTI_PRIMITIVE_TYPE_CHAR 67 'C' - Java 编程语言 char - JNI jchar
JVMTI_PRIMITIVE_TYPE_SHORT 83 'S' - Java 编程语言 short - JNI jshort
JVMTI_PRIMITIVE_TYPE_INT 73 'I' - Java 编程语言 int - JNI jint
JVMTI_PRIMITIVE_TYPE_LONG 74 'J' - Java 编程语言 long - JNI jlong
JVMTI_PRIMITIVE_TYPE_FLOAT 70 'F' - Java 编程语言 float - JNI jfloat
JVMTI_PRIMITIVE_TYPE_DOUBLE 68 'D' - Java 编程语言 double - JNI jdouble

字段引用的引用信息结构

JVMTI_HEAP_REFERENCE_FIELD JVMTI_HEAP_REFERENCE_STATIC_FIELD 引用返回的引用信息。
typedef struct {
  jint index;
} jvmtiHeapReferenceInfoField;
jvmtiHeapReferenceInfoField - 字段引用的引用信息结构
Field Type Description
index jint 对于 JVMTI_HEAP_REFERENCE_FIELD ,引用对象不是类或接口。在这种情况下,index 是引用对象类中字段的索引。这个类在下面被称为C.
对于 JVMTI_HEAP_REFERENCE_STATIC_FIELD ,引用对象是一个类(以下称为C) 或接口(以下称为I).在这种情况下,index 是该类或接口中字段的索引。
如果 referrer 对象不是接口,则字段索引确定如下:
  • 列出所有字段C及其超类,以 java.lang.Object 中的所有字段开始,以 java.lang.Object 中的所有字段结束C.
  • 在此list中,按照 GetClassFields 返回的顺序放置给定类的字段。
  • 分配此list索引中的字段n, n+1, ..., 按顺序,哪里n是实现的所有接口的字段数C.注意C实现由其超类直接实现的所有接口;以及这些接口的所有超接口。
如果 referrer 对象是接口,则字段索引确定如下:
  • 列出直接声明的字段I.
  • 在此list中,按照 GetClassFields 返回的顺序放置字段。
  • 分配此list索引中的字段n, n+1, ..., 按顺序,哪里n是所有超接口中字段的计数I.
所有字段都包含在此计算中,无论字段修饰符(静态、公共、私有等)如何。
例如,给定以下类和接口:
interface I0 {
  int p = 0;
}

interface I1 extends I0 {
  int x = 1;
}

interface I2 extends I0 {
  int y = 2;
}

class C1 implements I1 {
  public static int a = 3;
  private int b = 4;
}

class C2 extends C1 implements I2 {
  static int q = 5;
  final int r = 6;
}
      
假设GetClassFields 调用C1返回C1的字段顺序为:a,b;并且 C2 的字段按顺序返回:q,r。类 C1 的实例将具有以下字段索引:
Field 索引 Description
a 2 C1实现的接口中的字段数为2(n=2): I0pI1x
b 3 后续索引。
C1 将具有相同的字段索引。
C2 的实例将具有以下字段索引:
Field 索引 Description
a 3 C2实现的接口中字段的个数是三个(n=3): I0pI1xI2yC2 的接口)。请注意,I0 的字段 p 仅包含一次。
b 4 随后的索引为“a”。
q 5 “b”的后续索引。
r 6 “q”的后续索引。
C2 将具有相同的字段索引。请注意,一个字段可能具有不同的索引,具体取决于正在查看它的对象——例如上面的字段“a”。另请注意:并非所有字段索引都可以从回调中看到,但所有索引都是出于说明目的而显示的。
接口 I1 将具有以下字段索引:
Field 索引 Description
x 1 I1 的超接口中的字段数是一个(n=1): I0p

数组引用的引用信息结构

JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT 引用返回的引用信息。
typedef struct {
  jint index;
} jvmtiHeapReferenceInfoArray;
jvmtiHeapReferenceInfoArray - 数组引用的引用信息结构
Field Type Description
index jint 数组索引。

常量池引用的引用信息结构

JVMTI_HEAP_REFERENCE_CONSTANT_POOL 引用返回的引用信息。
typedef struct {
  jint index;
} jvmtiHeapReferenceInfoConstantPool;
jvmtiHeapReferenceInfoConstantPool - 常量池引用的引用信息结构
Field Type Description
index jint 类常量池的索引。请参阅中的说明Java™ 虚拟机规范,第 4.4 章.

局部变量引用的引用信息结构

JVMTI_HEAP_REFERENCE_STACK_LOCAL 引用返回的引用信息。
typedef struct {
  jlong thread_tag;
  jlong thread_id;
  jint depth;
  jmethodID method;
  jlocation location;
  jint slot;
} jvmtiHeapReferenceInfoStackLocal;
jvmtiHeapReferenceInfoStackLocal - 局部变量引用的引用信息结构
Field Type Description
thread_tag jlong 与此堆栈对应的线程的标记,如果未标记则为零。
thread_id jlong 这个栈对应的线程的唯一线程ID。
depth jint 框架的深度。
method jmethodID 在此框架中执行的方法。
location jlocation 此框架中的当前执行位置。
slot jint 局部变量的槽号。

JNI 本地引用的引用信息结构

JVMTI_HEAP_REFERENCE_JNI_LOCAL 引用返回的引用信息。
typedef struct {
  jlong thread_tag;
  jlong thread_id;
  jint depth;
  jmethodID method;
} jvmtiHeapReferenceInfoJniLocal;
jvmtiHeapReferenceInfoJniLocal - JNI 本地引用的引用信息结构
Field Type Description
thread_tag jlong 与此堆栈对应的线程的标记,如果未标记则为零。
thread_id jlong 这个栈对应的线程的唯一线程ID。
depth jint 框架的深度。
method jmethodID 在此框架中执行的方法。

其他参考的参考信息结构

为其他引用返回的引用信息。
typedef struct {
  jlong reserved1;
  jlong reserved2;
  jlong reserved3;
  jlong reserved4;
  jlong reserved5;
  jlong reserved6;
  jlong reserved7;
  jlong reserved8;
} jvmtiHeapReferenceInfoReserved;
jvmtiHeapReferenceInfoReserved - 其他参考的参考信息结构
Field Type Description
reserved1 jlong 保留以供将来使用。
reserved2 jlong 保留以供将来使用。
reserved3 jlong 保留以供将来使用。
reserved4 jlong 保留以供将来使用。
reserved5 jlong 保留以供将来使用。
reserved6 jlong 保留以供将来使用。
reserved7 jlong 保留以供将来使用。
reserved8 jlong 保留以供将来使用。

参考信息结构

返回的有关推荐人的信息。表示为各种参考信息的联合。
typedef union {
  jvmtiHeapReferenceInfoField field;
  jvmtiHeapReferenceInfoArray array;
  jvmtiHeapReferenceInfoConstantPool constant_pool;
  jvmtiHeapReferenceInfoStackLocal stack_local;
  jvmtiHeapReferenceInfoJniLocal jni_local;
  jvmtiHeapReferenceInfoReserved other;
} jvmtiHeapReferenceInfo;
jvmtiHeapReferenceInfo - 参考信息结构
Field Type Description
field jvmtiHeapReferenceInfoField JVMTI_HEAP_REFERENCE_FIELD JVMTI_HEAP_REFERENCE_STATIC_FIELD 引用的引用信息。
array jvmtiHeapReferenceInfoArray For JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT references 的引用信息。
constant_pool jvmtiHeapReferenceInfoConstantPool For JVMTI_HEAP_REFERENCE_CONSTANT_POOL references 的引用信息。
stack_local jvmtiHeapReferenceInfoStackLocal For JVMTI_HEAP_REFERENCE_STACK_LOCAL references 的引用信息。
jni_local jvmtiHeapReferenceInfoJniLocal For JVMTI_HEAP_REFERENCE_JNI_LOCAL references 的引用信息。
other jvmtiHeapReferenceInfoReserved 保留以供将来使用。

堆回调函数结构

typedef struct {
  jvmtiHeapIterationCallback heap_iteration_callback;
  jvmtiHeapReferenceCallback heap_reference_callback;
  jvmtiPrimitiveFieldCallback primitive_field_callback;
  jvmtiArrayPrimitiveValueCallback array_primitive_value_callback;
  jvmtiStringPrimitiveValueCallback string_primitive_value_callback;
  jvmtiReservedCallback reserved5;
  jvmtiReservedCallback reserved6;
  jvmtiReservedCallback reserved7;
  jvmtiReservedCallback reserved8;
  jvmtiReservedCallback reserved9;
  jvmtiReservedCallback reserved10;
  jvmtiReservedCallback reserved11;
  jvmtiReservedCallback reserved12;
  jvmtiReservedCallback reserved13;
  jvmtiReservedCallback reserved14;
  jvmtiReservedCallback reserved15;
} jvmtiHeapCallbacks;
jvmtiHeapCallbacks - 堆回调函数结构
Field Type Description
heap_iteration_callback jvmtiHeapIterationCallback 要调用的回调以描述堆中的对象。由 IterateThroughHeap 函数使用,由 FollowReferences 函数忽略。
heap_reference_callback jvmtiHeapReferenceCallback 要调用的回调来描述对象引用。由 FollowReferences 函数使用,由 IterateThroughHeap 函数忽略。
primitive_field_callback jvmtiPrimitiveFieldCallback 要调用的回调来描述原始字段。
array_primitive_value_callback jvmtiArrayPrimitiveValueCallback 要调用的回调来描述原始值数组。
string_primitive_value_callback jvmtiStringPrimitiveValueCallback 为描述字符串值而调用的回调。
reserved5 jvmtiReservedCallback 保留以备将来使用..
reserved6 jvmtiReservedCallback 保留以备将来使用..
reserved7 jvmtiReservedCallback 保留以备将来使用..
reserved8 jvmtiReservedCallback 保留以备将来使用..
reserved9 jvmtiReservedCallback 保留以备将来使用..
reserved10 jvmtiReservedCallback 保留以备将来使用..
reserved11 jvmtiReservedCallback 保留以备将来使用..
reserved12 jvmtiReservedCallback 保留以备将来使用..
reserved13 jvmtiReservedCallback 保留以备将来使用..
reserved14 jvmtiReservedCallback 保留以备将来使用..
reserved15 jvmtiReservedCallback 保留以备将来使用..

基本原理:堆转储功能(如下)使用每个对象的回调。虽然缓冲方法似乎可以提供更好的吞吐量,但测试并未表明情况如此——可能是由于内存引用的局部性或数组访问开销。


堆迭代回调

typedef jint (JNICALL *jvmtiHeapIterationCallback)
  (jlong class_tag,
   jlong size,
   jlong* tag_ptr,
   jint length,
   void* user_data);
代理提供的回调函数。描述(但不传入)堆中的对象。
此函数应返回所需 访问控制标志 的位向量。这将确定是否应中止整个迭代(JVMTI_VISIT_OBJECTS 标志被忽略)。
请参阅 堆回调函数限制
参数
Name Type Description
class_tag jlong 对象类的标记(如果类未标记则为零)。如果对象表示运行时类,则 class_tag 是与 java.lang.Class 关联的标记(如果 java.lang.Class 未标记则为零)。
size jlong 对象的大小(以字节为单位)。参见 GetObjectSize
tag_ptr jlong* 对象标记值,如果对象未标记则为零。要设置与对象相关联的标签值,代理会设置参数指向的jlong
length jint 如果此对象是数组,则为数组的长度。否则为负一 (-1)。
user_data void* 用户提供的数据被传递到迭代函数中。

堆引用回调

typedef jint (JNICALL *jvmtiHeapReferenceCallback)
  (jvmtiHeapReferenceKind reference_kind,
   const jvmtiHeapReferenceInfo* reference_info,
   jlong class_tag,
   jlong referrer_class_tag,
   jlong size,
   jlong* tag_ptr,
   jlong* referrer_tag_ptr,
   jint length,
   void* user_data);
代理提供的回调函数。描述从一个对象或 VM(引用者)到另一个对象(引用者)或堆根到引用者的引用。
此函数应返回所需 访问控制标志 的位向量。这将确定是否应该访问引用引用的对象,或者是否应该中止整个迭代。
请参阅 堆回调函数限制
参数
Name Type Description
reference_kind jvmtiHeapReferenceKind 参考的那种。
reference_info const jvmtiHeapReferenceInfo * 有关参考的详细信息。当 参考种类JVMTI_HEAP_REFERENCE_FIELD JVMTI_HEAP_REFERENCE_STATIC_FIELD JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT JVMTI_HEAP_REFERENCE_CONSTANT_POOL JVMTI_HEAP_REFERENCE_STACK_LOCAL JVMTI_HEAP_REFERENCE_JNI_LOCAL 时设置。否则 NULL
class_tag jlong 引用对象类的标记(如果类未标记则为零)。如果 referree 对象表示运行时类,则 class_tag 是与 java.lang.Class 关联的标记(如果 java.lang.Class 未标记则为零)。
referrer_class_tag jlong 引用对象类的标记(如果类未标记或引用是堆根则为零)。如果 referrer 对象表示运行时类,则 referrer_class_tag 是与 java.lang.Class 关联的标记(如果 java.lang.Class 未标记则为零)。
size jlong 裁判对象的大小(以字节为单位)。参见 GetObjectSize
tag_ptr jlong* 指向 referree 对象标记值,如果对象未标记则为零。要设置与对象相关联的标签值,代理会设置参数指向的jlong
referrer_tag_ptr jlong* 指向 referrer 对象的标签,如果没有标记 referrer 对象,则指向零。 NULL 如果引用者不是对象(也就是说,此回调报告堆根)。为了将标签值设置为与引用对象相关联,代理设置参数指向的jlong。如果此回调报告对象对自身的引用,则 referrer_tag_ptr == tag_ptr
length jint 如果此对象是数组,则为数组的长度。否则为负一 (-1)。
user_data void* 用户提供的数据被传递到迭代函数中。

原始字段回调

typedef jint (JNICALL *jvmtiPrimitiveFieldCallback)
  (jvmtiHeapReferenceKind kind,
   const jvmtiHeapReferenceInfo* info,
   jlong object_class_tag,
   jlong* object_tag_ptr,
   jvalue value,
   jvmtiPrimitiveType value_type,
   void* user_data);
代理提供的回调函数描述了对象的原始字段(物体).原始字段是其类型为原始类型的字段。如果对象是一个类,这个回调将描述一个静态字段,否则将描述一个实例字段。
此函数应返回所需 访问控制标志 的位向量。这将确定是否应中止整个迭代(JVMTI_VISIT_OBJECTS 标志被忽略)。
请参阅 堆回调函数限制
参数
Name Type Description
kind jvmtiHeapReferenceKind 字段的种类——实例或静态(JVMTI_HEAP_REFERENCE_FIELD JVMTI_HEAP_REFERENCE_STATIC_FIELD )。
info const jvmtiHeapReferenceInfo * 哪个字段(字段索引)。
object_class_tag jlong 对象类的标记(如果类未标记则为零)。如果对象表示运行时类,则 object_class_tag 是与 java.lang.Class 关联的标记(如果 java.lang.Class 未标记则为零)。
object_tag_ptr jlong* 指向对象的标记,如果对象未标记则为零。要设置与对象相关联的标签值,代理会设置参数指向的jlong
value jvalue 字段的值。
value_type jvmtiPrimitiveType 字段的类型。
user_data void* 用户提供的数据被传递到迭代函数中。

数组原始值回调

typedef jint (JNICALL *jvmtiArrayPrimitiveValueCallback)
  (jlong class_tag,
   jlong size,
   jlong* tag_ptr,
   jint element_count,
   jvmtiPrimitiveType element_type,
   const void* elements,
   void* user_data);
代理提供的回调函数。描述原始类型数组中的值。
此函数应返回所需 访问控制标志 的位向量。这将确定是否应中止整个迭代(JVMTI_VISIT_OBJECTS 标志被忽略)。
请参阅 堆回调函数限制
参数
Name Type Description
class_tag jlong 数组对象类的标记(如果类未标记则为零)。
size jlong 数组的大小(以字节为单位)。参见 GetObjectSize
tag_ptr jlong* 指向数组对象的标记,如果对象未标记则为零。要设置与对象相关联的标签值,代理会设置参数指向的jlong
element_count jint 原始数组的长度。
element_type jvmtiPrimitiveType 数组元素的类型。
elements const void* 每个 element_count 项大小为 element_type 的打包数组中的数组元素。
user_data void* 用户提供的数据被传递到迭代函数中。

字符串原始值回调

typedef jint (JNICALL *jvmtiStringPrimitiveValueCallback)
  (jlong class_tag,
   jlong size,
   jlong* tag_ptr,
   const jchar* value,
   jint value_length,
   void* user_data);
代理提供的回调函数。描述 java.lang.String 的值。
此函数应返回所需 访问控制标志 的位向量。这将确定是否应中止整个迭代(JVMTI_VISIT_OBJECTS 标志被忽略)。
请参阅 堆回调函数限制
参数
Name Type Description
class_tag jlong String 类的类的标记(如果该类未标记则为零)。
size jlong 字符串的大小(以字节为单位)。参见 GetObjectSize
tag_ptr jlong* 指向 String 对象的标记,如果对象未标记则为零。要设置与对象相关联的标签值,代理会设置参数指向的jlong
value const jchar* String 的值,编码为 Unicode 字符串。
value_length jint 字符串的长度。长度等于字符串中 16 位 Unicode 字符的数量。
user_data void* 用户提供的数据被传递到迭代函数中。

保留供将来使用回调

typedef jint (JNICALL *jvmtiReservedCallback)
  ();
占位符——保留以供将来使用。
参数
没有任何

按照参考资料

jvmtiError
FollowReferences(jvmtiEnv* env,
      jint heap_filter,
      jclass klass,
      jobject initial_object,
      const jvmtiHeapCallbacks* callbacks,
      const void* user_data)
此函数启动遍历可从指定对象直接和间接访问的对象,或者如果未指定 initial_object,则遍历可从堆根访问的所有对象。堆根是一组系统类、JNI 全局变量、来自线程堆栈的引用,以及用作垃圾收集目的的根的其他对象。
该函数通过遍历参考图来运行。让A, B, ... 表示对象。当引用来自AB被遍历,当引用从一个堆根到B被遍历,或者当B被指定为 initial_object ,然后B据说是参观过.来自的参考AB直到A被访问。引用的报告顺序与遍历引用的顺序相同。通过调用代理提供的回调函数 jvmtiHeapReferenceCallback 来报告对象引用。在参考资料中AB, A被称为referrerB作为referree.对于来自引用者的每个引用,回调只被调用一次;即使存在引用循环或引用者的多条路径,也是如此。一个推荐人和一个推荐人之间可能有不止一个推荐人,每一个推荐人都会被报告。这些引用可以通过检查 jvmtiHeapReferenceCallback 回调的 reference_kind reference_info 参数来区分。
此函数报告对象引用的 Java 编程语言视图,而不是虚拟机实现视图。以下对象引用在非空时会被报告:
此函数还可用于检查原始(非对象)值。访问对象后报告数组或字符串的原始值;通过调用代理提供的回调函数 jvmtiArrayPrimitiveValueCallback jvmtiStringPrimitiveValueCallback 来报告。访问具有该字段的对象后,会报告一个原始字段;它通过调用代理提供的回调函数 jvmtiPrimitiveFieldCallback 来报告。
回调的提供与否NULL只决定回调是否被调用,不影响访问哪些对象,也不影响是否调用其他回调。但是,jvmtiHeapReferenceCallback 返回的访问控制标志 确实确定当前对象引用的对象是否已访问。作为参数提供给此函数的 堆过滤器标志klass 不控制访问哪些对象,但它们控制回调报告哪些对象和原始值。例如,如果设置的唯一回调是 array_primitive_value_callback 并且 klass 设置为字节数组类,则只会报告字节数组。下表总结了这一点:
控制访问的对象 控制报告的对象 控制原语报告
jvmtiHeapReferenceCallback 返回的 堆访问控制标志 是的 是的, 因为访问是受控的 是的, 因为访问是受控的
array_primitive_value_callback callbacks 集合 是的
heap_filter 是的 是的
klass 是的 是的
在这个函数的执行过程中,堆的状态不会改变:没有对象被分配,没有对象被垃圾收集,对象的状态(包括持有的值)也没有改变。因此,执行 Java 编程语言代码的线程、尝试恢复执行 Java 编程语言代码的线程以及尝试执行 JNI 函数的线程通常会停止。
只能在直播阶段调用
115
1.1
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_tag_objects 可以设置和获取标签,如 堆类 中所述。
参数
Name Type Description
heap_filter jint 堆过滤器标志 的位向量。限制调用回调函数的对象。这适用于对象和原始回调。
klass jclass 只有当对象是此类的实例时才会报告回调。不报告作为 klass 子类实例的对象。如果 klass 是接口,则不会报告任何对象。这适用于对象和原始回调。
如果 klassNULL ,则回调不限于特定类的实例。
initial_object jobject 跟随的对象
如果 initial_objectNULL ,则从堆根开始引用。
callbacks const jvmtiHeapCallbacks * 定义回调函数集的结构。
Agent 传入一个指向 jvmtiHeapCallbacks 的指针。
user_data const void * 用户提供的数据将传递给回调。
Agent 传入一个指针。如果 user_dataNULL ,则 NULL 作为用户提供的数据传递。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_tag_objects 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_CLASS klass 不是有效的类。
JVMTI_ERROR_INVALID_OBJECT initial_object 不是有效对象。
JVMTI_ERROR_NULL_POINTER callbacks NULL

遍历堆

jvmtiError
IterateThroughHeap(jvmtiEnv* env,
      jint heap_filter,
      jclass klass,
      const jvmtiHeapCallbacks* callbacks,
      const void* user_data)
启动对堆中所有对象的迭代。这包括可到达和不可到达的对象。对象的访问没有特定顺序。
通过调用代理提供的回调函数 jvmtiHeapIterationCallback 来报告堆对象。不报告对象之间的引用。如果只需要可达对象,或者需要对象引用信息,请使用 FollowReferences
此函数还可用于检查原始(非对象)值。访问对象后报告数组或字符串的原始值;通过调用代理提供的回调函数 jvmtiArrayPrimitiveValueCallback jvmtiStringPrimitiveValueCallback 来报告。访问具有该字段的对象后,会报告一个原始字段;它通过调用代理提供的回调函数 jvmtiPrimitiveFieldCallback 来报告。
除非迭代被回调返回的 堆访问控制标志 中止,否则将访问堆中的所有对象。回调的提供与否NULL只决定回调是否被调用,不影响访问哪些对象,也不影响是否调用其他回调。作为参数提供给此函数的 堆过滤器标志klass 不控制访问哪些对象,但它们控制回调报告哪些对象和原始值。例如,如果设置的唯一回调是 array_primitive_value_callback 并且 klass 设置为字节数组类,则只会报告字节数组。下表对此进行了总结(将其与 FollowReferences 进行对比):
控制访问的对象 控制报告的对象 控制原语报告
jvmtiHeapIterationCallback 返回的 堆访问控制标志
(除非他们中止迭代)

(除非他们中止迭代)

(除非他们中止迭代)
array_primitive_value_callback callbacks 集合 是的
heap_filter 是的 是的
klass 是的 是的
在这个函数的执行过程中,堆的状态不会改变:没有对象被分配,没有对象被垃圾收集,对象的状态(包括持有的值)也没有改变。因此,执行 Java 编程语言代码的线程、尝试恢复执行 Java 编程语言代码的线程以及尝试执行 JNI 函数的线程通常会停止。
只能在直播阶段调用
116
1.1
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_tag_objects 可以设置和获取标签,如 堆类 中所述。
参数
Name Type Description
heap_filter jint 堆过滤器标志 的位向量。限制调用回调函数的对象。这适用于对象和原始回调。
klass jclass 只有当对象是此类的实例时才会报告回调。不报告作为 klass 子类实例的对象。如果 klass 是接口,则不会报告任何对象。这适用于对象和原始回调。
如果 klassNULL ,则回调不限于特定类的实例。
callbacks const jvmtiHeapCallbacks * 定义集合回调函数的结构。
Agent 传入一个指向 jvmtiHeapCallbacks 的指针。
user_data const void * 用户提供的数据将传递给回调。
Agent 传入一个指针。如果 user_dataNULL ,则 NULL 作为用户提供的数据传递。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_tag_objects 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_CLASS klass 不是有效的类。
JVMTI_ERROR_NULL_POINTER callbacks NULL

获取标签

jvmtiError
GetTag(jvmtiEnv* env,
      jobject object,
      jlong* tag_ptr)
检索与对象关联的标签。标记是一个长值,通常用于存储唯一标识符或指向对象信息的指针。标签设置为 SetTag 。没有设置标签的对象返回零标签值。
只能在开始或直播阶段调用
106
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_tag_objects 可以设置和获取标签,如 堆类 中所述。
参数
Name Type Description
object jobject 要检索其标记的对象。
tag_ptr jlong* 返回时,引用的 long 被设置为标签的值。
Agent 传递一个指向 jlong 的指针。返回时,jlong 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_tag_objects 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_OBJECT object 不是对象。
JVMTI_ERROR_NULL_POINTER tag_ptr NULL

设置标签

jvmtiError
SetTag(jvmtiEnv* env,
      jobject object,
      jlong tag)
设置与对象关联的标签。标记是一个长值,通常用于存储唯一标识符或指向对象信息的指针。使用 GetTag 可以看到标签。
只能在开始或直播阶段调用
107
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_tag_objects 可以设置和获取标签,如 堆类 中所述。
参数
Name Type Description
object jobject 要设置其标签的对象。
tag jlong 标签的新值。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_tag_objects 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_OBJECT object 不是对象。

获取带有标签的对象

jvmtiError
GetObjectsWithTags(jvmtiEnv* env,
      jint tag_count,
      const jlong* tags,
      jint* count_ptr,
      jobject** object_result_ptr,
      jlong** tag_result_ptr)
返回堆中具有指定标签的对象。格式是对象和标签的并行数组。
只能在直播阶段调用
114
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_tag_objects 可以设置和获取标签,如 堆类 中所述。
参数
Name Type Description
tag_count jint 要扫描的标签数。
tags const jlong * 扫描带有这些标签的对象。此数组中不允许使用零。
代理传入 jlongtag_count 元素数组。
count_ptr jint * 返回具有 tags 中任何标签的对象数。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
object_result_ptr jobject ** 返回具有 tags 中任何标记的对象数组。
Agent 传递一个指向 jobject* 的指针。返回时,jobject* 指向新分配的大小为 *count_ptr 的数组。该数组应使用 Deallocate 释放。如果 object_result_ptrNULL,则不会返回此信息。 object_result_ptr 返回的对象是 JNI 本地引用,必须是 管理
tag_result_ptr jlong ** 对于 object_result_ptr 中的每个对象,返回相应索引处的标签。
Agent 传递一个指向 jlong* 的指针。返回时,jlong* 指向新分配的大小为 *count_ptr 的数组。该数组应使用 Deallocate 释放。如果 tag_result_ptrNULL,则不会返回此信息。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_tag_objects 能力。使用 AddCapabilities
JVMTI_ERROR_ILLEGAL_ARGUMENT tags 中存在零。
JVMTI_ERROR_ILLEGAL_ARGUMENT tag_count 小于 0
JVMTI_ERROR_NULL_POINTER tags NULL
JVMTI_ERROR_NULL_POINTER count_ptr NULL

强制垃圾收集

jvmtiError
ForceGarbageCollection(jvmtiEnv* env)
强制 VM 执行垃圾回收。垃圾收集尽可能完整。此函数不会导致终结器运行。垃圾收集完成后,此函数才会返回。
尽管垃圾收集尽可能完整,但不能保证在该函数返回时所有 ObjectFree 事件都已发送。特别是,可能会阻止对象被释放,因为它正在等待完成。
只能在直播阶段调用
108
1.0
能力
所需功能
参数
没有任何
错误
这个函数返回一个 普遍错误


堆 (1.0)

堆 (1.0) 函数: 堆 (1.0) 函数类型: 堆 (1.0) 类型: 这些函数和数据类型是在最初的JVM中引入的 TI 版本 1.0。它们已被弃用,并将更改为在未来的版本中返回错误。它们在 JVM 中被取代 TI 1.2 版 (Java SE 6) 更多 强大而灵活的版本 哪个:
请使用 当前堆函数 .
堆对象过滤器枚举 (jvmtiHeapObjectFilter)
持续的 Value Description
JVMTI_HEAP_OBJECT_TAGGED 1 仅标记对象。
JVMTI_HEAP_OBJECT_UNTAGGED 2 仅限未标记的对象。
JVMTI_HEAP_OBJECT_EITHER 3 标记或未标记的对象。
堆根类型枚举 (jvmtiHeapRootKind)
持续的 Value Description
JVMTI_HEAP_ROOT_JNI_GLOBAL 1 JNI 全局引用。
JVMTI_HEAP_ROOT_SYSTEM_CLASS 2 系统类。
JVMTI_HEAP_ROOT_MONITOR 3 监视器。
JVMTI_HEAP_ROOT_STACK_LOCAL 4 堆栈本地。
JVMTI_HEAP_ROOT_JNI_LOCAL 5 JNI 本地引用。
JVMTI_HEAP_ROOT_THREAD 6 线。
JVMTI_HEAP_ROOT_OTHER 7 其他。
对象引用枚举 (jvmtiObjectReferenceKind)
持续的 Value Description
JVMTI_REFERENCE_CLASS 1 从一个对象到它的类的引用。
JVMTI_REFERENCE_FIELD 2 从对象到其实例字段之一的值的引用。对于此类引用,jvmtiObjectReferenceCallbackreferrer_index 参数是实例字段的索引。索引基于所有对象字段的顺序。这包括类中直接声明的静态和实例字段的所有字段,包括在超类和超接口中声明的所有字段(公共和私有)字段。因此,索引的计算方法是将直接声明的类中字段的索引(参见 GetClassFields )与所有超类和超接口中声明的字段总数(公共和私有)相加。索引从零开始。
JVMTI_REFERENCE_ARRAY_ELEMENT 3 从数组到其元素之一的引用。对于此类引用,jvmtiObjectReferenceCallbackreferrer_index 参数是数组索引。
JVMTI_REFERENCE_CLASS_LOADER 4 从一个类到它的类加载器的引用。
JVMTI_REFERENCE_SIGNERS 5 从一个类到它的 signers 数组的引用。
JVMTI_REFERENCE_PROTECTION_DOMAIN 6 从一个类到它的保护域的引用。
JVMTI_REFERENCE_INTERFACE 7 从一个类到它的接口之一的引用。
JVMTI_REFERENCE_STATIC_FIELD 8 从一个类到它的静态字段之一的值的引用。对于此类引用,jvmtiObjectReferenceCallbackreferrer_index 参数是静态字段的索引。索引基于所有对象字段的顺序。这包括类中直接声明的静态和实例字段的所有字段,包括在超类和超接口中声明的所有字段(公共和私有)字段。因此,索引的计算方法是将直接声明的类中字段的索引(参见 GetClassFields )与所有超类和超接口中声明的字段总数(公共和私有)相加。索引从零开始。注意:此定义与 JVM 中的不同 TI 1.0 规范。

理由:没有已知的实现使用 1.0 定义。

JVMTI_REFERENCE_CONSTANT_POOL 9 从类到常量池中已解析条目的引用。对于此类引用,jvmtiObjectReferenceCallbackreferrer_index 参数是该类常量池表的索引,从 1 开始。参见Java™ 虚拟机规范,第 4.4 章.
迭代控制枚举(jvmtiIterationControl
持续的 Value Description
JVMTI_ITERATION_CONTINUE 1 继续迭代。如果这是引用迭代,请遵循此对象的引用。
JVMTI_ITERATION_IGNORE 2 继续迭代。如果这是一个引用迭代,忽略这个对象的引用。
JVMTI_ITERATION_ABORT 0 中止迭代。

堆对象回调

typedef jvmtiIterationControl (JNICALL *jvmtiHeapObjectCallback)
  (jlong class_tag,
   jlong size,
   jlong* tag_ptr,
   void* user_data);
代理提供的回调函数。描述(但不传入)堆中的对象。
返回值应为 JVMTI_ITERATION_CONTINUE 以继续迭代,或 JVMTI_ITERATION_ABORT 以停止迭代。
请参阅 堆回调函数限制
参数
Name Type Description
class_tag jlong 对象类的标记(如果类未标记则为零)。如果对象表示运行时类,则 class_tag 是与 java.lang.Class 关联的标记(如果 java.lang.Class 未标记则为零)。
size jlong 对象的大小(以字节为单位)。参见 GetObjectSize
tag_ptr jlong* 对象标记值,如果对象未标记则为零。要设置与对象相关联的标签值,代理会设置参数指向的jlong
user_data void* 用户提供的数据被传递到迭代函数中。

堆根对象回调

typedef jvmtiIterationControl (JNICALL *jvmtiHeapRootCallback)
  (jvmtiHeapRootKind root_kind,
   jlong class_tag,
   jlong size,
   jlong* tag_ptr,
   void* user_data);
代理提供的回调函数。描述(但不传入)作为垃圾收集目的根的对象。
返回值应该是 JVMTI_ITERATION_CONTINUE 继续迭代,JVMTI_ITERATION_IGNORE 继续迭代而不从 referree 对象寻求引用或 JVMTI_ITERATION_ABORT 停止迭代。
请参阅 堆回调函数限制
参数
Name Type Description
root_kind jvmtiHeapRootKind 堆根的那种。
class_tag jlong 对象类的标记(如果类未标记则为零)。如果对象表示运行时类,则 class_tag 是与 java.lang.Class 关联的标记(如果 java.lang.Class 未标记则为零)。
size jlong 对象的大小(以字节为单位)。参见 GetObjectSize
tag_ptr jlong* 对象标记值,如果对象未标记则为零。要设置与对象相关联的标签值,代理会设置参数指向的jlong
user_data void* 用户提供的数据被传递到迭代函数中。

堆栈引用对象回调

typedef jvmtiIterationControl (JNICALL *jvmtiStackReferenceCallback)
  (jvmtiHeapRootKind root_kind,
   jlong class_tag,
   jlong size,
   jlong* tag_ptr,
   jlong thread_tag,
   jint depth,
   jmethodID method,
   jint slot,
   void* user_data);
代理提供的回调函数。描述(但不传入)堆栈上的对象,该对象是用于垃圾收集的根。
返回值应该是 JVMTI_ITERATION_CONTINUE 继续迭代,JVMTI_ITERATION_IGNORE 继续迭代而不从 referree 对象寻求引用或 JVMTI_ITERATION_ABORT 停止迭代。
请参阅 堆回调函数限制
参数
Name Type Description
root_kind jvmtiHeapRootKind 根的种类(JVMTI_HEAP_ROOT_STACK_LOCALJVMTI_HEAP_ROOT_JNI_LOCAL )。
class_tag jlong 对象类的标记(如果类未标记则为零)。如果对象表示运行时类,则 class_tag 是与 java.lang.Class 关联的标记(如果 java.lang.Class 未标记则为零)。
size jlong 对象的大小(以字节为单位)。参见 GetObjectSize
tag_ptr jlong* 对象标记值,如果对象未标记则为零。要设置与对象相关联的标签值,代理会设置参数指向的jlong
thread_tag jlong 与此堆栈对应的线程的标记,如果未标记则为零。
depth jint 框架的深度。
method jmethodID 在此框架中执行的方法。
slot jint 插槽号。
user_data void* 用户提供的数据被传递到迭代函数中。

对象引用回调

typedef jvmtiIterationControl (JNICALL *jvmtiObjectReferenceCallback)
  (jvmtiObjectReferenceKind reference_kind,
   jlong class_tag,
   jlong size,
   jlong* tag_ptr,
   jlong referrer_tag,
   jint referrer_index,
   void* user_data);
代理提供的回调函数。描述从一个对象(引用者)到另一个对象(引用者)的引用。
返回值应该是 JVMTI_ITERATION_CONTINUE 继续迭代,JVMTI_ITERATION_IGNORE 继续迭代而不从 referree 对象寻求引用或 JVMTI_ITERATION_ABORT 停止迭代。
请参阅 堆回调函数限制
参数
Name Type Description
reference_kind jvmtiObjectReferenceKind 引用的类型。
class_tag jlong 引用对象类的标记(如果类未标记则为零)。如果 referree 对象表示运行时类,则 class_tag 是与 java.lang.Class 关联的标记(如果 java.lang.Class 未标记则为零)。
size jlong 裁判对象的大小(以字节为单位)。参见 GetObjectSize
tag_ptr jlong* 引用对象标记值,如果对象未标记则为零。要设置与对象相关联的标签值,代理会设置参数指向的jlong
referrer_tag jlong 引用对象的标记,如果引用对象未标记,则为零。
referrer_index jint 对于 JVMTI_REFERENCE_FIELDJVMTI_REFERENCE_STATIC_FIELD 类型的引用,引用对象中字段的索引。索引基于所有对象字段的顺序 - 请参阅 JVMTI_REFERENCE_FIELDJVMTI_REFERENCE_STATIC_FIELD 以获取更多说明。
对于 JVMTI_REFERENCE_ARRAY_ELEMENT 数组索引类型的引用 - 请参阅 JVMTI_REFERENCE_ARRAY_ELEMENT 以获取更多说明。
对于 JVMTI_REFERENCE_CONSTANT_POOL 类型的引用,该类的常量池中的索引 - 请参阅 JVMTI_REFERENCE_CONSTANT_POOL 以获取更多描述。
对于其他类型的参考,referrer_index-1
user_data void* 用户提供的数据被传递到迭代函数中。

遍历从对象可达的对象

jvmtiError
IterateOverObjectsReachableFromObject(jvmtiEnv* env,
      jobject object,
      jvmtiObjectReferenceCallback object_reference_callback,
      const void* user_data)
此函数遍历所有可从指定对象直接或间接到达的对象。对于每个对象A(称为引用者)引用对象B调用指定的回调函数来描述对象引用。对于来自引用者的每个引用,回调只被调用一次;即使存在引用循环或引用者的多条路径,也是如此。 referrer 和 referree 之间可能有不止一个引用,这些可以通过 jvmtiObjectReferenceCallback.reference_kind jvmtiObjectReferenceCallback.referrer_index 来区分。对象的回调将始终在其引用者的回调之后发生。
有关报告的对象引用,请参阅 FollowReferences
在这个函数的执行过程中,堆的状态不会改变:没有对象被分配,没有对象被垃圾收集,对象的状态(包括持有的值)也没有改变。因此,执行 Java 编程语言代码的线程、尝试恢复执行 Java 编程语言代码的线程以及尝试执行 JNI 函数的线程通常会停止。
只能在直播阶段调用
109
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_tag_objects 可以设置和获取标签,如 堆类 中所述。
参数
Name Type Description
object jobject 物体
object_reference_callback jvmtiObjectReferenceCallback 要调用的回调来描述每个对象引用。
user_data const void * 用户提供的数据将传递给回调。
Agent 传入一个指针。如果 user_dataNULL ,则 NULL 作为用户提供的数据传递。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_tag_objects 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_OBJECT object 不是对象。
JVMTI_ERROR_NULL_POINTER object_reference_callback NULL

遍历可达对象

jvmtiError
IterateOverReachableObjects(jvmtiEnv* env,
      jvmtiHeapRootCallback heap_root_callback,
      jvmtiStackReferenceCallback stack_ref_callback,
      jvmtiObjectReferenceCallback object_ref_callback,
      const void* user_data)
此函数遍历根对象以及从根对象直接和间接可达的所有对象。根对象包括一组系统类、JNI 全局变量、来自线程堆栈的引用,以及用作垃圾收集目的的根的其他对象。
对于每个根,调用 heap_root_callback stack_ref_callback 回调。一个对象可以出于多种原因成为根对象,在这种情况下,针对每种原因调用适当的回调。
对于每个对象引用,调用 object_ref_callback 回调函数来描述对象引用。对于来自引用者的每个引用,回调只被调用一次;即使存在引用循环或引用者的多条路径,也是如此。 referrer 和 referree 之间可能有不止一个引用,这些可以通过 jvmtiObjectReferenceCallback.reference_kind jvmtiObjectReferenceCallback.referrer_index 来区分。对象的回调将始终在其引用者的回调之后发生。
有关报告的对象引用,请参阅 FollowReferences
根总是在报告任何对象引用之前报告给探查器。换句话说,在为所有根调用适当的回调之前,不会调用 object_ref_callback 回调。如果 object_ref_callback 回调指定为 NULL,则此函数会在向探查器报告根对象后返回。
在这个函数的执行过程中,堆的状态不会改变:没有对象被分配,没有对象被垃圾收集,对象的状态(包括持有的值)也没有改变。因此,执行 Java 编程语言代码的线程、尝试恢复执行 Java 编程语言代码的线程以及尝试执行 JNI 函数的线程通常会停止。
只能在直播阶段调用
110
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_tag_objects 可以设置和获取标签,如 堆类 中所述。
参数
Name Type Description
heap_root_callback jvmtiHeapRootCallback JVMTI_HEAP_ROOT_JNI_GLOBALJVMTI_HEAP_ROOT_SYSTEM_CLASSJVMTI_HEAP_ROOT_MONITORJVMTI_HEAP_ROOT_THREADJVMTI_HEAP_ROOT_OTHER 类型的每个堆根调用的回调函数。
如果 heap_root_callbackNULL,则不报告堆根。
stack_ref_callback jvmtiStackReferenceCallback JVMTI_HEAP_ROOT_STACK_LOCALJVMTI_HEAP_ROOT_JNI_LOCAL 的每个堆根调用的回调函数。
如果 stack_ref_callbackNULL,则不报告堆栈引用。
object_ref_callback jvmtiObjectReferenceCallback 为每个对象引用调用的回调函数。
如果 object_ref_callbackNULL ,则不要遵循根对象的引用。
user_data const void * 用户提供的数据将传递给回调。
Agent 传入一个指针。如果 user_dataNULL ,则 NULL 作为用户提供的数据传递。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_tag_objects 能力。使用 AddCapabilities

遍历堆

jvmtiError
IterateOverHeap(jvmtiEnv* env,
      jvmtiHeapObjectFilter object_filter,
      jvmtiHeapObjectCallback heap_object_callback,
      const void* user_data)
遍历堆中的所有对象。这包括可到达和不可到达的对象。
object_filter 参数表示调用回调函数的对象。如果此参数为 JVMTI_HEAP_OBJECT_TAGGED,则只会为每个被标记的对象调用回调。如果参数是 JVMTI_HEAP_OBJECT_UNTAGGED 那么回调将只针对未标记的对象。如果参数是 JVMTI_HEAP_OBJECT_EITHER 那么回调函数将被调用堆中的每个对象,不管它是否被标记。
在这个函数的执行过程中,堆的状态不会改变:没有对象被分配,没有对象被垃圾收集,对象的状态(包括持有的值)也没有改变。因此,执行 Java 编程语言代码的线程、尝试恢复执行 Java 编程语言代码的线程以及尝试执行 JNI 函数的线程通常会停止。
只能在直播阶段调用
111
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_tag_objects 可以设置和获取标签,如 堆类 中所述。
参数
Name Type Description
object_filter jvmtiHeapObjectFilter 指示调用回调函数的对象。
heap_object_callback jvmtiHeapObjectCallback 为匹配 object_filter 的每个对象调用的迭代器函数。
user_data const void * 用户提供的数据将传递给回调。
Agent 传入一个指针。如果 user_dataNULL ,则 NULL 作为用户提供的数据传递。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_tag_objects 能力。使用 AddCapabilities
JVMTI_ERROR_ILLEGAL_ARGUMENT object_filter 不是 jvmtiHeapObjectFilter。
JVMTI_ERROR_NULL_POINTER heap_object_callback NULL

迭代类的实例

jvmtiError
IterateOverInstancesOfClass(jvmtiEnv* env,
      jclass klass,
      jvmtiHeapObjectFilter object_filter,
      jvmtiHeapObjectCallback heap_object_callback,
      const void* user_data)
遍历堆中作为指定类实例的所有对象。这包括指定类的直接实例和指定类的所有子类的实例。这包括可到达和不可到达的对象。
object_filter 参数表示调用回调函数的对象。如果此参数为 JVMTI_HEAP_OBJECT_TAGGED,则只会为每个被标记的对象调用回调。如果参数是 JVMTI_HEAP_OBJECT_UNTAGGED 则只会为未标记的对象调用回调。如果参数是 JVMTI_HEAP_OBJECT_EITHER 那么回调函数将被调用堆中的每个对象,不管它是否被标记。
在这个函数的执行过程中,堆的状态不会改变:没有对象被分配,没有对象被垃圾收集,对象的状态(包括持有的值)也没有改变。因此,执行 Java 编程语言代码的线程、尝试恢复执行 Java 编程语言代码的线程以及尝试执行 JNI 函数的线程通常会停止。
只能在直播阶段调用
112
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_tag_objects 可以设置和获取标签,如 堆类 中所述。
参数
Name Type Description
klass jclass 仅迭代此类的对象。
object_filter jvmtiHeapObjectFilter 指示调用回调函数的对象。
heap_object_callback jvmtiHeapObjectCallback 为匹配 object_filter 的每个 klass 实例调用的迭代器函数。
user_data const void * 用户提供的数据将传递给回调。
Agent 传入一个指针。如果 user_dataNULL ,则 NULL 作为用户提供的数据传递。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_tag_objects 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_ILLEGAL_ARGUMENT object_filter 不是 jvmtiHeapObjectFilter。
JVMTI_ERROR_NULL_POINTER heap_object_callback NULL


局部变量

局部变量函数: 这些函数用于检索或设置局部变量的值。变量由包含其值的帧的深度和该帧中变量的槽号来标识。可以使用函数 GetLocalVariableTable 获得变量到槽号的映射。
GetLocalXXX 函数可用于检索包含在虚拟线程帧中的局部变量的值。 SetLocalXXX 函数可用于在断点或单步事件处挂起的虚拟线程的最顶层帧中设置局部变量的值。在其他情况下,实现可能支持设置局部变量。

获取局部变量 - 对象

jvmtiError
GetLocalObject(jvmtiEnv* env,
      jthread thread,
      jint depth,
      jint slot,
      jobject* value_ptr)
此函数可用于检索类型为 ObjectObject 的子类的局部变量的值。
指定的线程必须挂起或者必须是当前线程。
只能在直播阶段调用
21
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_access_local_variables 可以设置和获取局部变量
参数
Name Type Description
thread jthread 包含变量值的框架线程。如果 threadNULL ,则使用当前线程。
depth jint 包含变量值的帧的深度。
slot jint 变量的槽号。
value_ptr jobject* 返回时,指向变量的值。
代理传递一个指向 jobject 的指针。返回时,jobject 已设置。 value_ptr 返回的对象是 JNI 本地引用,必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_access_local_variables 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_SLOT slot 无效。
JVMTI_ERROR_TYPE_MISMATCH 变量类型不是 ObjectObject 的子类。
JVMTI_ERROR_OPAQUE_FRAME 不可见的框架
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未挂起且不是当前线程。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_ILLEGAL_ARGUMENT depth 小于零。
JVMTI_ERROR_NO_MORE_FRAMES 指定的 depth 处没有堆栈帧。
JVMTI_ERROR_NULL_POINTER value_ptr NULL

获取本地实例

jvmtiError
GetLocalInstance(jvmtiEnv* env,
      jthread thread,
      jint depth,
      jobject* value_ptr)
此函数可用于从非静态帧中检索槽 0 处的局部对象变量(“this”对象)的值。此函数可以从本机方法帧中检索“this”对象,而 GetLocalObject() 在这些情况下会返回 JVMTI_ERROR_OPAQUE_FRAME
指定的线程必须挂起或者必须是当前线程。
只能在直播阶段调用
155
1.2
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_access_local_variables 可以设置和获取局部变量
参数
Name Type Description
thread jthread 包含变量值的框架线程。如果 threadNULL ,则使用当前线程。
depth jint 包含变量值的帧的深度。
value_ptr jobject* 返回时,指向变量的值。
代理传递一个指向 jobject 的指针。返回时,jobject 已设置。 value_ptr 返回的对象是 JNI 本地引用,必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_access_local_variables 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_SLOT 如果指定的框架是静态方法框架。
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未挂起且不是当前线程。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_ILLEGAL_ARGUMENT depth 小于零。
JVMTI_ERROR_NO_MORE_FRAMES 指定的 depth 处没有堆栈帧。
JVMTI_ERROR_NULL_POINTER value_ptr NULL

获取局部变量 - Int

jvmtiError
GetLocalInt(jvmtiEnv* env,
      jthread thread,
      jint depth,
      jint slot,
      jint* value_ptr)
此函数可用于检索类型为 intshortcharbyteboolean 的局部变量的值。
指定的线程必须挂起或者必须是当前线程。
只能在直播阶段调用
22
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_access_local_variables 可以设置和获取局部变量
参数
Name Type Description
thread jthread 包含变量值的框架线程。如果 threadNULL ,则使用当前线程。
depth jint 包含变量值的帧的深度。
slot jint 变量的槽号。
value_ptr jint* 返回时,指向变量的值。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_access_local_variables 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_SLOT slot 无效。
JVMTI_ERROR_TYPE_MISMATCH 变量类型不是 intshortcharbyteboolean
JVMTI_ERROR_OPAQUE_FRAME 不可见的框架
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未挂起且不是当前线程。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_ILLEGAL_ARGUMENT depth 小于零。
JVMTI_ERROR_NO_MORE_FRAMES 指定的 depth 处没有堆栈帧。
JVMTI_ERROR_NULL_POINTER value_ptr NULL

获取局部变量 - 长

jvmtiError
GetLocalLong(jvmtiEnv* env,
      jthread thread,
      jint depth,
      jint slot,
      jlong* value_ptr)
此函数可用于检索类型为 long 的局部变量的值。
指定的线程必须挂起或者必须是当前线程。
只能在直播阶段调用
23
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_access_local_variables 可以设置和获取局部变量
参数
Name Type Description
thread jthread 包含变量值的框架线程。如果 threadNULL ,则使用当前线程。
depth jint 包含变量值的帧的深度。
slot jint 变量的槽号。
value_ptr jlong* 返回时,指向变量的值。
Agent 传递一个指向 jlong 的指针。返回时,jlong 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_access_local_variables 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_SLOT slot 无效。
JVMTI_ERROR_TYPE_MISMATCH 变量类型不是 long
JVMTI_ERROR_OPAQUE_FRAME 不可见的框架
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未挂起且不是当前线程。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_ILLEGAL_ARGUMENT depth 小于零。
JVMTI_ERROR_NO_MORE_FRAMES 指定的 depth 处没有堆栈帧。
JVMTI_ERROR_NULL_POINTER value_ptr NULL

获取局部变量 - Float

jvmtiError
GetLocalFloat(jvmtiEnv* env,
      jthread thread,
      jint depth,
      jint slot,
      jfloat* value_ptr)
此函数可用于检索类型为 float 的局部变量的值。
指定的线程必须挂起或者必须是当前线程。
只能在直播阶段调用
24
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_access_local_variables 可以设置和获取局部变量
参数
Name Type Description
thread jthread 包含变量值的框架线程。如果 threadNULL ,则使用当前线程。
depth jint 包含变量值的帧的深度。
slot jint 变量的槽号。
value_ptr jfloat* 返回时,指向变量的值。
Agent 传递一个指向 jfloat 的指针。返回时,jfloat 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_access_local_variables 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_SLOT slot 无效。
JVMTI_ERROR_TYPE_MISMATCH 变量类型不是 float
JVMTI_ERROR_OPAQUE_FRAME 不可见的框架
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未挂起且不是当前线程。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_ILLEGAL_ARGUMENT depth 小于零。
JVMTI_ERROR_NO_MORE_FRAMES 指定的 depth 处没有堆栈帧。
JVMTI_ERROR_NULL_POINTER value_ptr NULL

获取局部变量 - 双精度

jvmtiError
GetLocalDouble(jvmtiEnv* env,
      jthread thread,
      jint depth,
      jint slot,
      jdouble* value_ptr)
此函数可用于检索类型为 long 的局部变量的值。
指定的线程必须挂起或者必须是当前线程。
只能在直播阶段调用
25
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_access_local_variables 可以设置和获取局部变量
参数
Name Type Description
thread jthread 包含变量值的框架线程。如果 threadNULL ,则使用当前线程。
depth jint 包含变量值的帧的深度。
slot jint 变量的槽号。
value_ptr jdouble* 返回时,指向变量的值。
Agent 传递一个指向 jdouble 的指针。返回时,jdouble 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_access_local_variables 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_SLOT slot 无效。
JVMTI_ERROR_TYPE_MISMATCH 变量类型不是 double
JVMTI_ERROR_OPAQUE_FRAME 不可见的框架
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未挂起且不是当前线程。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_ILLEGAL_ARGUMENT depth 小于零。
JVMTI_ERROR_NO_MORE_FRAMES 指定的 depth 处没有堆栈帧。
JVMTI_ERROR_NULL_POINTER value_ptr NULL

设置局部变量 - 对象

jvmtiError
SetLocalObject(jvmtiEnv* env,
      jthread thread,
      jint depth,
      jint slot,
      jobject value)
此函数可用于设置类型为 ObjectObject 的子类的局部变量的值。
指定的线程必须挂起或者必须是当前线程。
只能在直播阶段调用
26
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_access_local_variables 可以设置和获取局部变量
参数
Name Type Description
thread jthread 包含变量值的框架线程。如果 threadNULL ,则使用当前线程。
depth jint 包含变量值的帧的深度。
slot jint 变量的槽号。
value jobject 变量的新值。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_access_local_variables 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_SLOT slot 无效。
JVMTI_ERROR_TYPE_MISMATCH 变量类型不是 ObjectObject 的子类。
JVMTI_ERROR_TYPE_MISMATCH 提供的 value 与变量类型不兼容。
JVMTI_ERROR_OPAQUE_FRAME 不可见的框架
JVMTI_ERROR_OPAQUE_FRAME 该线程是虚拟线程,实现不支持在给定深度的帧中设置局部值。参见 局部变量
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未挂起且不是当前线程。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_ILLEGAL_ARGUMENT depth 小于零。
JVMTI_ERROR_NO_MORE_FRAMES 指定的 depth 处没有堆栈帧。
JVMTI_ERROR_INVALID_OBJECT value 不是对象。

设置局部变量 - Int

jvmtiError
SetLocalInt(jvmtiEnv* env,
      jthread thread,
      jint depth,
      jint slot,
      jint value)
此函数可用于设置类型为 intshortcharbyteboolean 的局部变量的值。
指定的线程必须挂起或者必须是当前线程。
只能在直播阶段调用
27
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_access_local_variables 可以设置和获取局部变量
参数
Name Type Description
thread jthread 包含变量值的框架线程。如果 threadNULL ,则使用当前线程。
depth jint 包含变量值的帧的深度。
slot jint 变量的槽号。
value jint 变量的新值。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_access_local_variables 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_SLOT slot 无效。
JVMTI_ERROR_TYPE_MISMATCH 变量类型不是 intshortcharbyteboolean
JVMTI_ERROR_OPAQUE_FRAME 不可见的框架
JVMTI_ERROR_OPAQUE_FRAME 该线程是虚拟线程,实现不支持在给定深度的帧中设置局部值。参见 局部变量
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未挂起且不是当前线程。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_ILLEGAL_ARGUMENT depth 小于零。
JVMTI_ERROR_NO_MORE_FRAMES 指定的 depth 处没有堆栈帧。

设置局部变量 - 长

jvmtiError
SetLocalLong(jvmtiEnv* env,
      jthread thread,
      jint depth,
      jint slot,
      jlong value)
此函数可用于设置类型为 long 的局部变量的值。
指定的线程必须挂起或者必须是当前线程。
只能在直播阶段调用
28
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_access_local_variables 可以设置和获取局部变量
参数
Name Type Description
thread jthread 包含变量值的框架线程。如果 threadNULL ,则使用当前线程。
depth jint 包含变量值的帧的深度。
slot jint 变量的槽号。
value jlong 变量的新值。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_access_local_variables 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_SLOT slot 无效。
JVMTI_ERROR_TYPE_MISMATCH 变量类型不是 long
JVMTI_ERROR_OPAQUE_FRAME 不可见的框架
JVMTI_ERROR_OPAQUE_FRAME 该线程是虚拟线程,实现不支持在给定深度的帧中设置局部值。参见 局部变量
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未挂起且不是当前线程。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_ILLEGAL_ARGUMENT depth 小于零。
JVMTI_ERROR_NO_MORE_FRAMES 指定的 depth 处没有堆栈帧。

设置局部变量 - Float

jvmtiError
SetLocalFloat(jvmtiEnv* env,
      jthread thread,
      jint depth,
      jint slot,
      jfloat value)
此函数可用于设置类型为 float 的局部变量的值。
指定的线程必须挂起或者必须是当前线程。
只能在直播阶段调用
29
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_access_local_variables 可以设置和获取局部变量
参数
Name Type Description
thread jthread 包含变量值的框架线程。如果 threadNULL ,则使用当前线程。
depth jint 包含变量值的帧的深度。
slot jint 变量的槽号。
value jfloat 变量的新值。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_access_local_variables 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_SLOT slot 无效。
JVMTI_ERROR_TYPE_MISMATCH 变量类型不是 float
JVMTI_ERROR_OPAQUE_FRAME 不可见的框架
JVMTI_ERROR_OPAQUE_FRAME 该线程是虚拟线程,实现不支持在给定深度的帧中设置局部值。参见 局部变量
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未挂起且不是当前线程。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_ILLEGAL_ARGUMENT depth 小于零。
JVMTI_ERROR_NO_MORE_FRAMES 指定的 depth 处没有堆栈帧。

设置局部变量 - 双精度

jvmtiError
SetLocalDouble(jvmtiEnv* env,
      jthread thread,
      jint depth,
      jint slot,
      jdouble value)
此函数可用于设置类型为 double 的局部变量的值。
指定的线程必须挂起或者必须是当前线程。
只能在直播阶段调用
30
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_access_local_variables 可以设置和获取局部变量
参数
Name Type Description
thread jthread 包含变量值的框架线程。如果 threadNULL ,则使用当前线程。
depth jint 包含变量值的帧的深度。
slot jint 变量的槽号。
value jdouble 变量的新值。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_access_local_variables 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_SLOT slot 无效。
JVMTI_ERROR_TYPE_MISMATCH 变量类型不是 double
JVMTI_ERROR_OPAQUE_FRAME 不可见的框架
JVMTI_ERROR_OPAQUE_FRAME 该线程是虚拟线程,实现不支持在给定深度的帧中设置局部值。参见 局部变量
JVMTI_ERROR_THREAD_NOT_SUSPENDED 线程未挂起且不是当前线程。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_ILLEGAL_ARGUMENT depth 小于零。
JVMTI_ERROR_NO_MORE_FRAMES 指定的 depth 处没有堆栈帧。


断点

断点函数:

设置断点

jvmtiError
SetBreakpoint(jvmtiEnv* env,
      jmethodID method,
      jlocation location)
methodlocation 指示的指令处设置断点。一条指令只能有一个断点。
每当指定的指令即将被执行时,就会产生一个Breakpoint 事件。
只能在直播阶段调用
38
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_generate_breakpoint_events 可以 set 从而获得 Breakpoint 事件
参数
Name Type Description
method jmethodID 设置断点的方法
location jlocation 设置断点的指令的索引
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_generate_breakpoint_events 能力。使用 AddCapabilities
JVMTI_ERROR_DUPLICATE 指定的字节码已经有一个断点。
JVMTI_ERROR_INVALID_METHODID method 不是 jmethodID。
JVMTI_ERROR_INVALID_LOCATION location 不是有效位置。

清除断点

jvmtiError
ClearBreakpoint(jvmtiEnv* env,
      jmethodID method,
      jlocation location)
清除 methodlocation 指示的字节码处的断点。
只能在直播阶段调用
39
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_generate_breakpoint_events 可以 set 从而获得 Breakpoint 事件
参数
Name Type Description
method jmethodID 清除断点的方法
location jlocation 清除断点的指令的索引
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_generate_breakpoint_events 能力。使用 AddCapabilities
JVMTI_ERROR_NOT_FOUND 在指定的字节码处没有断点。
JVMTI_ERROR_INVALID_METHODID method 不是 jmethodID。
JVMTI_ERROR_INVALID_LOCATION location 不是有效位置。


看场

监视字段函数:

设置现场访问监视

jvmtiError
SetFieldAccessWatch(jvmtiEnv* env,
      jclass klass,
      jfieldID field)
klassfield指定的字段即将被访问时产生一个FieldAccess 事件。每次访问该字段都会生成一个事件,直到它被 ClearFieldAccessWatch 取消。监视来自 Java 编程语言代码或 JNI 代码的字段访问,不监视通过其他方式修改的字段。请注意,JVM TI 用户应注意,他们自己的现场访问会触发手表。一个字段只能有一个字段访问监视集。字段的修改不被视为访问——使用 SetFieldModificationWatch 来监视修改。
只能在直播阶段调用
41
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_generate_field_access_events 可以设置现场访问观察点 - SetFieldAccessWatch
参数
Name Type Description
klass jclass 包含要观看的字段的类
field jfieldID 值得关注的字段
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_generate_field_access_events 。使用 AddCapabilities
JVMTI_ERROR_DUPLICATE 已在监视指定字段的访问。
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_INVALID_FIELDID field 不是 jfieldID。

清晰的现场访问手表

jvmtiError
ClearFieldAccessWatch(jvmtiEnv* env,
      jclass klass,
      jfieldID field)
klassfield 指定的字段上取消先前由 SetFieldAccessWatch 设置的字段访问监视。
只能在直播阶段调用
42
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_generate_field_access_events 可以设置现场访问观察点 - SetFieldAccessWatch
参数
Name Type Description
klass jclass 包含要观看的字段的类
field jfieldID 值得关注的字段
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_generate_field_access_events 。使用 AddCapabilities
JVMTI_ERROR_NOT_FOUND 未监视指定字段的访问。
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_INVALID_FIELDID field 不是 jfieldID。

设置字段修改监视

jvmtiError
SetFieldModificationWatch(jvmtiEnv* env,
      jclass klass,
      jfieldID field)
当由klassfield指定的字段即将被修改时产生一个FieldModification 事件。每次修改字段都会生成一个事件,直到用 ClearFieldModificationWatch 取消。监视来自 Java 编程语言代码或 JNI 代码的字段修改,不监视通过其他方式修改的字段。请注意,JVM TI 用户应注意自己的现场修改会触发手表。一个字段只能有一个字段修改监视集。
只能在直播阶段调用
43
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_generate_field_modification_events 可以在现场修改上设置观察点 - SetFieldModificationWatch
参数
Name Type Description
klass jclass 包含要观看的字段的类
field jfieldID 值得关注的字段
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_generate_field_modification_events 。使用 AddCapabilities
JVMTI_ERROR_DUPLICATE 指定的字段已经在监视修改。
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_INVALID_FIELDID field 不是 jfieldID。

清除字段修改手表

jvmtiError
ClearFieldModificationWatch(jvmtiEnv* env,
      jclass klass,
      jfieldID field)
klassfield 指定的字段上取消先前由 SetFieldModificationWatch 设置的字段修改监视。
只能在直播阶段调用
44
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_generate_field_modification_events 可以在现场修改上设置观察点 - SetFieldModificationWatch
参数
Name Type Description
klass jclass 包含要观看的字段的类
field jfieldID 值得关注的字段
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_generate_field_modification_events 。使用 AddCapabilities
JVMTI_ERROR_NOT_FOUND 指定的字段未被监视以进行修改。
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_INVALID_FIELDID field 不是 jfieldID。


Module

模块功能:

获取所有模块

jvmtiError
GetAllModules(jvmtiEnv* env,
      jint* module_count_ptr,
      jobject** modules_ptr)
返回虚拟机中加载的所有模块的数组。该数组包括每个类加载器的未命名模块。数组中的模块数通过 module_count_ptr 返回,数组本身通过 modules_ptr 返回。
只能在直播阶段调用
3
9
能力
所需功能
参数
Name Type Description
module_count_ptr jint* 返回时,指向返回模块的数量。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
modules_ptr jobject** 返回时,指向一组引用,每个模块一个。
Agent 传递一个指向 jobject* 的指针。返回时,jobject* 指向新分配的大小为 *module_count_ptr 的数组。该数组应使用 Deallocate 释放。 modules_ptr 返回的对象是 JNI 本地引用并且必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER module_count_ptr NULL
JVMTI_ERROR_NULL_POINTER modules_ptr NULL

获取命名模块

jvmtiError
GetNamedModule(jvmtiEnv* env,
      jobject class_loader,
      const char* package_name,
      jobject* module_ptr)
返回定义给包含给定包的类加载器的命名模块的 java.lang.Module 对象。该模块通过 module_ptr 返回。
如果为类加载器定义了命名模块并且它包含包,则返回该命名模块,否则返回NULL
只能在直播阶段调用
40
9
能力
所需功能
参数
Name Type Description
class_loader jobject 一个类加载器。如果 class_loader 不是 NULLjava.lang.ClassLoader 的子类,则此函数返回 JVMTI_ERROR_ILLEGAL_ARGUMENT
如果 class_loaderNULL ,则假定引导加载程序。
package_name const char* 包的名称,编码为 修改后的 UTF-8 字符串。包名采用内部形式(JVMS 4.2.1);标识符由正斜杠而不是句点分隔。
代理传入一个 char 数组。
module_ptr jobject* 返回时,指向 java.lang.Module 对象或指向 NULL
代理传递一个指向 jobject 的指针。返回时,jobject 已设置。 module_ptr 返回的对象是 JNI 本地引用,必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_ILLEGAL_ARGUMENT 如果类加载器不是 NULL 并且不是类加载器对象。
JVMTI_ERROR_NULL_POINTER package_name NULL
JVMTI_ERROR_NULL_POINTER module_ptr NULL

添加模块读取

jvmtiError
AddModuleReads(jvmtiEnv* env,
      jobject module,
      jobject to_module)
更新模块以读取另一个模块。当 module 是未命名模块时,此函数是空操作。此函数有助于在命名模块中检测代码,其中该检测需要扩展模块读取的模块集。
只能在直播阶段调用
94
9
能力
所需功能
参数
Name Type Description
module jobject 要更新的模块。
to_module jobject 要读取的附加模块。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_MODULE 如果 module 不是模块对象。
JVMTI_ERROR_INVALID_MODULE 如果 to_module 不是模块对象。
JVMTI_ERROR_UNMODIFIABLE_MODULE 如果无法修改模块。参见 IsModifiableModule
JVMTI_ERROR_NULL_POINTER module NULL
JVMTI_ERROR_NULL_POINTER to_module NULL

添加模块导出

jvmtiError
AddModuleExports(jvmtiEnv* env,
      jobject module,
      const char* pkg_name,
      jobject to_module)
更新模块以将包导出到另一个模块。当 module 是未命名模块或打开模块时,此函数是空操作。此函数有助于在命名模块中检测代码,其中该检测需要扩展模块导出的包集。
只能在直播阶段调用
95
9
能力
所需功能
参数
Name Type Description
module jobject 要更新的模块。
pkg_name const char* 导出的包名称。
代理传入一个 char 数组。
to_module jobject 包导出到的模块。如果 to_module 不是 java.lang.Module 的子类,则此函数返回 JVMTI_ERROR_INVALID_MODULE
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_MODULE 如果 module 不是模块对象。
JVMTI_ERROR_INVALID_MODULE 如果 to_module 不是模块对象。
JVMTI_ERROR_ILLEGAL_ARGUMENT 如果包 pkg_name 不属于该模块。
JVMTI_ERROR_UNMODIFIABLE_MODULE 如果无法修改模块。参见 IsModifiableModule
JVMTI_ERROR_NULL_POINTER module NULL
JVMTI_ERROR_NULL_POINTER pkg_name NULL
JVMTI_ERROR_NULL_POINTER to_module NULL

添加模块打开

jvmtiError
AddModuleOpens(jvmtiEnv* env,
      jobject module,
      const char* pkg_name,
      jobject to_module)
更新模块以将包打开到另一个模块。当 module 是未命名模块或打开模块时,此函数是空操作。此功能有助于在模块中检测代码,其中该检测需要扩展模块向其他模块打开的包集。
只能在直播阶段调用
96
9
能力
所需功能
参数
Name Type Description
module jobject 要更新的模块。
pkg_name const char* 要打开的包的包名称。
代理传入一个 char 数组。
to_module jobject 包含要打开的包的模块。如果 to_module 不是 java.lang.Module 的子类,则此函数返回 JVMTI_ERROR_INVALID_MODULE
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_MODULE 如果 module 不是模块对象。
JVMTI_ERROR_INVALID_MODULE 如果 to_module 不是模块对象。
JVMTI_ERROR_ILLEGAL_ARGUMENT 如果包 pkg_name 不属于该模块。
JVMTI_ERROR_UNMODIFIABLE_MODULE 如果无法修改模块。参见 IsModifiableModule
JVMTI_ERROR_NULL_POINTER module NULL
JVMTI_ERROR_NULL_POINTER pkg_name NULL
JVMTI_ERROR_NULL_POINTER to_module NULL

添加模块使用

jvmtiError
AddModuleUses(jvmtiEnv* env,
      jobject module,
      jclass service)
更新模块以将服务添加到模块使用的服务集中。当模块是未命名模块时,此函数是空操作。此功能有助于在命名模块中检测代码,其中该检测需要扩展模块正在使用的服务集。
只能在直播阶段调用
97
9
能力
所需功能
参数
Name Type Description
module jobject 要更新的模块。
service jclass 要使用的服务。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_MODULE 如果 module 不是模块对象。
JVMTI_ERROR_INVALID_CLASS 如果 service 不是类对象。
JVMTI_ERROR_UNMODIFIABLE_MODULE 如果无法修改模块。参见 IsModifiableModule
JVMTI_ERROR_NULL_POINTER module NULL
JVMTI_ERROR_NULL_POINTER service NULL

添加模块提供

jvmtiError
AddModuleProvides(jvmtiEnv* env,
      jobject module,
      jclass service,
      jclass impl_class)
更新模块以将服务添加到模块提供的服务集中。当模块是未命名模块时,此函数是空操作。此功能有助于在命名模块中检测代码,其中该检测需要更改所提供的服务。
只能在直播阶段调用
98
9
能力
所需功能
参数
Name Type Description
module jobject 要更新的模块。
service jclass 要提供的服务。
impl_class jclass 所提供服务的实现类。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_MODULE 如果 module 不是模块对象。
JVMTI_ERROR_INVALID_CLASS 如果 service 不是类对象。
JVMTI_ERROR_INVALID_CLASS 如果 impl_class 不是类对象。
JVMTI_ERROR_UNMODIFIABLE_MODULE 如果无法修改模块。参见 IsModifiableModule
JVMTI_ERROR_NULL_POINTER module NULL
JVMTI_ERROR_NULL_POINTER service NULL
JVMTI_ERROR_NULL_POINTER impl_class NULL

是可修改模块

jvmtiError
IsModifiableModule(jvmtiEnv* env,
      jobject module,
      jboolean* is_modifiable_module_ptr)
确定模块是否可修改。如果模块是可修改的,则可以使用 AddModuleReads AddModuleExports AddModuleOpens AddModuleUses AddModuleProvides 更新该模块。如果模块不可修改,则无法使用这些函数更新模块。当调用此函数以确定未命名模块是否可修改时,此函数的结果始终为 JNI_TRUE
只能在直播阶段调用
99
9
能力
所需功能
参数
Name Type Description
module jobject 要查询的模块。
is_modifiable_module_ptr jboolean* 返回时,指向此函数的布尔结果。
Agent 传递一个指向 jboolean 的指针。返回时,jboolean 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_MODULE 如果 module 不是模块对象。
JVMTI_ERROR_NULL_POINTER module NULL
JVMTI_ERROR_NULL_POINTER is_modifiable_module_ptr NULL


Class

类函数: 类类型: 类标志和常量:

获取加载类

jvmtiError
GetLoadedClasses(jvmtiEnv* env,
      jint* class_count_ptr,
      jclass** classes_ptr)
返回虚拟机中加载的所有类的数组。数组中类的数量通过 class_count_ptr 返回,数组本身通过 classes_ptr 返回。
类或接口的创建可以由以下之一触发:
数组类由 Java 虚拟机直接创建。创建可以通过使用类加载器或通过调用某些 Java SE 平台 API 中的方法(例如反射)来触发。
返回的列表包括所有类和接口,包括 隐藏类或接口 ,以及所有类型的数组类(包括原始类型数组)。原始类(例如 java.lang.Integer.TYPE )是不是包含在返回列表中。
只能在直播阶段调用
78
1.0
能力
所需功能
参数
Name Type Description
class_count_ptr jint* 返回时,指向类的数量。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
classes_ptr jclass** 返回时,指向一组引用,每个类一个。
Agent 传递一个指向 jclass* 的指针。返回时,jclass* 指向新分配的大小为 *class_count_ptr 的数组。该数组应使用 Deallocate 释放。 classes_ptr 返回的对象是 JNI 本地引用,必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER class_count_ptr NULL
JVMTI_ERROR_NULL_POINTER classes_ptr NULL

获取类加载器类

jvmtiError
GetClassLoaderClasses(jvmtiEnv* env,
      jobject initiating_loader,
      jint* class_count_ptr,
      jclass** classes_ptr)
返回此类加载器可以通过名称通过 ClassLoader::loadClassClass::forName 和字节码链接找到的所有类的数组。也就是说,initiating_loader 已被记录为初始加载程序的所有类。返回数组中的每个类都是由此类加载器创建的,可以直接定义它,也可以委托给另一个类加载器。看Java™ 虚拟机规范,第 5.3 章.
返回的列表不包括元素类型为隐藏类或接口的 隐藏类或接口 或数组类,因为它们无法被任何类加载器发现。
数组中类的数量通过 class_count_ptr 返回,数组本身通过 classes_ptr 返回。
参见 Lookup::defineHiddenClass
只能在直播阶段调用
79
1.0
能力
所需功能
参数
Name Type Description
initiating_loader jobject 启动类加载器。
如果 initiating_loaderNULL ,将返回引导加载程序启动的类。
class_count_ptr jint* 返回时,指向类的数量。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
classes_ptr jclass** 返回时,指向一组引用,每个类一个。
Agent 传递一个指向 jclass* 的指针。返回时,jclass* 指向新分配的大小为 *class_count_ptr 的数组。该数组应使用 Deallocate 释放。 classes_ptr 返回的对象是 JNI 本地引用,必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER class_count_ptr NULL
JVMTI_ERROR_NULL_POINTER classes_ptr NULL

获取类签名

jvmtiError
GetClassSignature(jvmtiEnv* env,
      jclass klass,
      char** signature_ptr,
      char** generic_ptr)
返回 klass 指示的类的名称和通用签名。
如果该类是类或接口,则:
如果 klass 指示的类表示数组类,则返回的名称是由一个或多个“[”字符组成的字符串,表示数组嵌套的深度,后跟元素类型的类签名。例如 java.lang.String[] 的类签名是“[Ljava/lang/String;”而 int[] 的是“[I”。
如果 klass 指示的类表示原始类型或 void ,则返回的名称是 相应原始类型的类型签名字符 。例如,java.lang.Integer.TYPE 是“I”。
只能在开始或直播阶段调用
48
1.0
能力
所需功能
参数
Name Type Description
klass jclass 要查询的类。
signature_ptr char ** 返回时,指向类的 JNI 类型签名,编码为 修改后的 UTF-8 字符串。
Agent 传递一个指向 char* 的指针。返回时,char* 指向一个新分配的数组。该数组应使用 Deallocate 释放。如果 signature_ptrNULL ,则不返回签名。
generic_ptr char ** 返回时,指向类的通用签名,编码为 修改后的 UTF-8 字符串。如果该类没有通用签名属性,则返回时指向 NULL
Agent 传递一个指向 char* 的指针。返回时,char* 指向一个新分配的数组。该数组应使用 Deallocate 释放。如果 generic_ptrNULL ,则不返回通用签名。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。

获取类状态

jvmtiError
GetClassStatus(jvmtiEnv* env,
      jclass klass,
      jint* status_ptr)
获取类的状态。可以设置零个或多个以下位。
类状态标志
持续的 Value Description
JVMTI_CLASS_STATUS_VERIFIED 1 类字节码已经过验证
JVMTI_CLASS_STATUS_PREPARED 2 备课完成
JVMTI_CLASS_STATUS_INITIALIZED 4 类初始化完成。静态初始化程序已运行。
JVMTI_CLASS_STATUS_ERROR 8 初始化期间的错误使类无法使用
JVMTI_CLASS_STATUS_ARRAY 16 类是一个数组。如果设置,所有其他位都为零。
JVMTI_CLASS_STATUS_PRIMITIVE 32 类是原始类(例如 java.lang.Integer.TYPE )。如果设置,所有其他位都为零。
只能在开始或直播阶段调用
49
1.0
能力
所需功能
参数
Name Type Description
klass jclass 要查询的类。
status_ptr jint* 返回时,指向此类的当前状态作为 类状态标志 中的一个或多个。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_NULL_POINTER status_ptr NULL

获取源文件名

jvmtiError
GetSourceFileName(jvmtiEnv* env,
      jclass klass,
      char** source_name_ptr)
对于 klass 指示的类,通过 source_name_ptr 返回源文件名。返回的字符串只是一个文件名,从不包含目录名。
对于原始类(例如 java.lang.Integer.TYPE )和数组,此函数返回 JVMTI_ERROR_ABSENT_INFORMATION
只能在开始或直播阶段调用
50
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_get_source_file_name 可以得到一个类的源文件名
参数
Name Type Description
klass jclass 要查询的类。
source_name_ptr char** 返回时,指向类的源文件名,编码为 修改后的 UTF-8 字符串。
Agent 传递一个指向 char* 的指针。返回时,char* 指向一个新分配的数组。该数组应使用 Deallocate 释放。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_get_source_file_name 。使用 AddCapabilities
JVMTI_ERROR_ABSENT_INFORMATION 类信息不包括源文件名。这包括类是数组类或原始类的情况。
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_NULL_POINTER source_name_ptr NULL

获取类修饰符

jvmtiError
GetClassModifiers(jvmtiEnv* env,
      jclass klass,
      jint* modifiers_ptr)
对于 klass 指示的类,通过 modifiers_ptr 返回访问标志。访问标志定义在Java™ 虚拟机规范,第 4 章.
如果该类是数组类,那么它的public、private 和protected 修饰符与它的组件类型相同。对于基元数组,此组件类型由基元类之一(例如 java.lang.Integer.TYPE )表示。
如果该类是原始类,它的 public 修饰符总是 true,它的 protected 和 private修饰符总是 false。
如果该类是数组类或原始类,则其最终修饰符始终为真,其接口修饰符始终为假。它的其他修饰符的值不由本规范确定。
只能在开始或直播阶段调用
51
1.0
能力
所需功能
参数
Name Type Description
klass jclass 要查询的类。
modifiers_ptr jint* 返回时,指向此类的当前访问标志。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_NULL_POINTER modifiers_ptr NULL

获取类方法

jvmtiError
GetClassMethods(jvmtiEnv* env,
      jclass klass,
      jint* method_count_ptr,
      jmethodID** methods_ptr)
对于 klass 指示的类,通过 method_count_ptr 返回方法计数,通过 methods_ptr 返回方法 ID 列表。方法列表包含构造函数和静态初始值设定项以及真正的方法。仅返回直接声明的方法(不返回继承的方法)。为数组类和基本类(例如 java.lang.Integer.TYPE )返回一个空方法列表。
只能在开始或直播阶段调用
52
1.0
能力
所需功能
可选功能
能力 影响
can_maintain_original_method_order 可以按照它们在类文件中出现的顺序返回方法
参数
Name Type Description
klass jclass 要查询的类。
method_count_ptr jint* 返回时,指向此类中声明的方法数。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
methods_ptr jmethodID** 返回时,指向方法 ID 数组。
Agent 传递一个指向 jmethodID* 的指针。返回时,jmethodID* 指向新分配的大小为 *method_count_ptr 的数组。该数组应使用 Deallocate 释放。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_CLASS_NOT_PREPARED klass 没有准备好。
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_NULL_POINTER method_count_ptr NULL
JVMTI_ERROR_NULL_POINTER methods_ptr NULL

获取类字段

jvmtiError
GetClassFields(jvmtiEnv* env,
      jclass klass,
      jint* field_count_ptr,
      jfieldID** fields_ptr)
对于 klass 指示的类,通过 field_count_ptr 返回字段计数,通过 fields_ptr 返回字段 ID 列表。仅返回直接声明的字段(不返回继承的字段)。字段按照它们在类文件中出现的顺序返回。为数组类和原始类(例如 java.lang.Integer.TYPE )返回一个空字段列表。使用 JNI 确定数组的长度。
只能在开始或直播阶段调用
53
1.0
能力
所需功能
参数
Name Type Description
klass jclass 要查询的类。
field_count_ptr jint* 返回时,指向此类中声明的字段数。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
fields_ptr jfieldID** 返回时,指向字段 ID 数组。
Agent 传递一个指向 jfieldID* 的指针。返回时,jfieldID* 指向新分配的大小为 *field_count_ptr 的数组。该数组应使用 Deallocate 释放。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_CLASS_NOT_PREPARED klass 没有准备好。
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_NULL_POINTER field_count_ptr NULL
JVMTI_ERROR_NULL_POINTER fields_ptr NULL

获取已实现的接口

jvmtiError
GetImplementedInterfaces(jvmtiEnv* env,
      jclass klass,
      jint* interface_count_ptr,
      jclass** interfaces_ptr)
返回此类的直接超级接口。对于类,此函数返回在其 implements 子句中声明的接口。对于接口,此函数返回在其 extends 子句中声明的接口。为数组类和原始类(例如 java.lang.Integer.TYPE )返回一个空接口列表。
只能在开始或直播阶段调用
54
1.0
能力
所需功能
参数
Name Type Description
klass jclass 要查询的类。
interface_count_ptr jint* 返回时,指向接口的数量。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
interfaces_ptr jclass** 返回时,指向接口数组。
Agent 传递一个指向 jclass* 的指针。返回时,jclass* 指向新分配的大小为 *interface_count_ptr 的数组。该数组应使用 Deallocate 释放。 interfaces_ptr 返回的对象是 JNI 本地引用,必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_CLASS_NOT_PREPARED klass 没有准备好。
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_NULL_POINTER interface_count_ptr NULL
JVMTI_ERROR_NULL_POINTER interfaces_ptr NULL

获取类版本号

jvmtiError
GetClassVersionNumbers(jvmtiEnv* env,
      jclass klass,
      jint* minor_version_ptr,
      jint* major_version_ptr)
对于 klass 指示的类,返回次要和主要版本号,如中所定义Java™ 虚拟机规范,第 4 章.
只能在开始或直播阶段调用
145
1.1
能力
所需功能
参数
Name Type Description
klass jclass 要查询的类。
minor_version_ptr jint* 返回时,指向类文件格式的 minor_version 项的值。注意:为了与Class File Format保持一致,次版本号为第一个参数。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
major_version_ptr jint* 返回时,指向类文件格式的major_version 项的值。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_ABSENT_INFORMATION 该类是原始类或数组类。
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_NULL_POINTER minor_version_ptr NULL
JVMTI_ERROR_NULL_POINTER major_version_ptr NULL

获取常量池

jvmtiError
GetConstantPool(jvmtiEnv* env,
      jclass klass,
      jint* constant_pool_count_ptr,
      jint* constant_pool_byte_count_ptr,
      unsigned char** constant_pool_bytes_ptr)
对于klass指示的类,以constant_pool项的格式返回常量池的原始字节Java™ 虚拟机规范,第 4 章.常量池的格式可能因类文件格式的版本而异,因此,应检查 次要和主要类版本号 的兼容性。
返回的常量池可能与定义类文件中的常量池具有不同的布局或内容。 GetConstantPool() 返回的常量池可能比定义的常量池具有更多或更少的条目。条目的顺序可能不同。 GetConstantPool() 返回的常量池将匹配 GetBytecodes() 使用的常量池。也就是说,GetBytecodes() 返回的字节码将具有常量池索引,这些索引引用 GetConstantPool() 返回的常量池条目。注意,由于RetransformClasses RedefineClasses 可以改变常量池,所以这个函数返回的常量池也可以随之改变。因此,如果存在中间类重新转换或重新定义,则 GetConstantPool() 和 GetBytecodes() 之间的对应关系不成立。给定字节码使用的常量池条目的值将与定义类文件的值匹配(即使索引不匹配)。不被字节码直接或间接使用的常量池条目(例如,与注释关联的 UTF-8 字符串)不需要存在于返回的常量池中。
只能在开始或直播阶段调用
146
1.1
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_get_constant_pool 可以拿到一个类的常量池-GetConstantPool
参数
Name Type Description
klass jclass 要查询的类。
constant_pool_count_ptr jint* 返回时,指向常量池表中的条目数加一。这对应于类文件格式的constant_pool_count项。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
constant_pool_byte_count_ptr jint* 返回时,指向返回的原始常量池中的字节数。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
constant_pool_bytes_ptr unsigned char** 返回时,指向原始常量池,即类文件格式的 constant_pool 项定义的字节
Agent 传递一个指向 unsigned char* 的指针。返回时,unsigned char* 指向新分配的大小为 *constant_pool_byte_count_ptr 的数组。该数组应使用 Deallocate 释放。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_get_constant_pool 。使用 AddCapabilities
JVMTI_ERROR_ABSENT_INFORMATION 该类是原始类或数组类。
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_NULL_POINTER constant_pool_count_ptr NULL
JVMTI_ERROR_NULL_POINTER constant_pool_byte_count_ptr NULL
JVMTI_ERROR_NULL_POINTER constant_pool_bytes_ptr NULL

是接口

jvmtiError
IsInterface(jvmtiEnv* env,
      jclass klass,
      jboolean* is_interface_ptr)
确定类对象引用是否表示接口。如果“类”实际上是一个接口,则 jboolean 结果为 JNI_TRUE,否则为 JNI_FALSE
只能在开始或直播阶段调用
55
1.0
能力
所需功能
参数
Name Type Description
klass jclass 要查询的类。
is_interface_ptr jboolean* 返回时,指向此函数的布尔结果。
Agent 传递一个指向 jboolean 的指针。返回时,jboolean 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_NULL_POINTER is_interface_ptr NULL

是数组类

jvmtiError
IsArrayClass(jvmtiEnv* env,
      jclass klass,
      jboolean* is_array_class_ptr)
确定类对象引用是否表示数组。如果类是数组,则 jboolean 结果为 JNI_TRUE,否则为 JNI_FALSE
只能在开始或直播阶段调用
56
1.0
能力
所需功能
参数
Name Type Description
klass jclass 要查询的类。
is_array_class_ptr jboolean* 返回时,指向此函数的布尔结果。
Agent 传递一个指向 jboolean 的指针。返回时,jboolean 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_NULL_POINTER is_array_class_ptr NULL

是可修改类

jvmtiError
IsModifiableClass(jvmtiEnv* env,
      jclass klass,
      jboolean* is_modifiable_class_ptr)
确定类是否可修改。如果类是可修改的(is_modifiable_class_ptr 返回 JNI_TRUE ),则可以使用 RedefineClasses 重新定义该类(假设代理拥有 can_redefine_classes 能力)或使用 RetransformClasses 重新转换(假设代理拥有 can_retransform_classes 能力)。如果类不可修改(is_modifiable_class_ptr 返回 JNI_FALSE),则该类既不能重新定义也不能重新转换。
原始类(例如 java.lang.Integer.TYPE )、数组类和一些实现定义的类永远不可修改。
只能在开始或直播阶段调用
45
1.1
能力
所需功能
可选功能
能力 影响
can_redefine_any_class 如果拥有,则所有类(原始类、数组和一些实现定义的类除外)都可以使用 RedefineClasses 进行修改。
can_retransform_any_class 如果拥有,则所有类(原始类、数组和一些实现定义的类除外)都可以使用 RetransformClasses 进行修改。
can_redefine_classes 对函数的结果没有影响。但必须另外具备用RedefineClasses 修饰类。
can_retransform_classes 对函数的结果没有影响。但必须另外具备用RetransformClasses 修饰类。
参数
Name Type Description
klass jclass 要查询的类。
is_modifiable_class_ptr jboolean* 返回时,指向此函数的布尔结果。
Agent 传递一个指向 jboolean 的指针。返回时,jboolean 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_NULL_POINTER is_modifiable_class_ptr NULL

获取类加载器

jvmtiError
GetClassLoader(jvmtiEnv* env,
      jclass klass,
      jobject* classloader_ptr)
对于 klass 指示的类,通过 classloader_ptr 返回对该类的类加载器的引用。
只能在开始或直播阶段调用
57
1.0
能力
所需功能
参数
Name Type Description
klass jclass 要查询的类。
classloader_ptr jobject* 返回时,指向加载此类的类加载器。如果类不是由类加载器创建的,或者如果类加载器是引导类加载器,则指向 NULL
代理传递一个指向 jobject 的指针。返回时,jobject 已设置。 classloader_ptr 返回的对象是 JNI 本地引用,必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_NULL_POINTER classloader_ptr NULL

获取源调试扩展

jvmtiError
GetSourceDebugExtension(jvmtiEnv* env,
      jclass klass,
      char** source_debug_extension_ptr)
对于 klass 指示的类,通过 source_debug_extension_ptr 返回调试扩展。返回的字符串恰好包含 klass 的类文件中存在的调试扩展信息。
只能在开始或直播阶段调用
90
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_get_source_debug_extension 可以获得一个类的源码调试扩展
参数
Name Type Description
klass jclass 要查询的类。
source_debug_extension_ptr char** 返回时,指向类的调试扩展,编码为 修改后的 UTF-8 字符串。
Agent 传递一个指向 char* 的指针。返回时,char* 指向一个新分配的数组。该数组应使用 Deallocate 释放。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_get_source_debug_extension 能力。使用 AddCapabilities
JVMTI_ERROR_ABSENT_INFORMATION 类信息不包括调试扩展。
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_NULL_POINTER source_debug_extension_ptr NULL

重新转换类

jvmtiError
RetransformClasses(jvmtiEnv* env,
      jint class_count,
      const jclass* classes)
此功能有助于 字节码检测 已加载的类。要在不引用现有字节码的情况下替换类定义,就像从源代码重新编译以进行修复并继续调试时可能会做的那样,应该使用 RedefineClasses 函数。
当最初加载类或它们是 redefined 时,可以使用 ClassFileLoadHook 事件转换初始类文件字节。此函数重新运行转换过程(无论之前是否发生过转换)。此重新转换遵循以下步骤: 有关详细信息,请参阅 ClassFileLoadHook 事件。
初始类文件字节表示传递给 ClassLoader.defineClassRedefineClasses 的字节(在应用任何转换之前),但是它们可能不完全匹配。常量池可能在 GetConstantPool 中描述的方式有所不同。方法字节码中的常量池索引将对应。某些属性可能不存在。如果顺序没有意义,例如方法的顺序,则可能不会保留顺序。
重新转换可能导致安装新版本的方法。旧方法版本可能变为 obsolete 新方法版本将用于新调用。如果一个方法有活跃的堆栈帧,那些活跃的帧继续运行原始方法版本的字节码。
这个函数不会导致任何初始化,除非在通常的 JVM 语义下会发生初始化。换句话说,重新转换类不会导致其初始化程序运行。静态字段的值将保持在调用之前的状态。
线程不需要暂停。
清除类中的所有断点。
所有属性都已更新。
重新转换类的实例不受影响——字段保留它们以前的值。实例上的 标签 也不受影响。
为响应此调用,将发送 ClassFileLoadHook 事件以外的任何事件。
重新转换可能会更改方法体、常量池和属性(除非明确禁止)。重新转换不得添加、删除或重命名字段或方法、更改方法的签名、更改修饰符或更改继承。重新转换不得更改 NestHostNestMembersRecordPermittedSubclasses 属性。这些限制可能会在未来的版本中取消。如果尝试进行不受支持的重新转换,请参阅下面的错误返回说明,了解有关返回的错误代码的信息。类文件字节在通过 ClassFileLoadHook 事件链之前不会被验证或安装,因此返回的错误代码反映了转换的结果。如果返回 JVMTI_ERROR_NONE 以外的任何错误代码,则所有要重新转换的类都不会安装新定义。当此函数返回时(错误代码为 JVMTI_ERROR_NONE ),所有要重新转换的类都将安装其新定义。
只能在直播阶段调用
152
1.1
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_retransform_classes 可以使用 RetransformClasses 重新转换类。除了具体实现对该能力施加的限制外(参见能力部分),必须在该环境中首次启用ClassFileLoadHook 事件之前设置该能力。在第一次启用 ClassFileLoadHook 时拥有此功能的环境被称为再转化能力.在第一次启用 ClassFileLoadHook 时不具备此功能的环境被称为无法再改造.
可选功能
can_retransform_any_class RetransformClasses 可以在任何可修改的类上调用。参见 IsModifiableClass 。 (can_retransform_classes 也必须设置)
参数
Name Type Description
class_count jint 要重新转换的类数。
classes const jclass* 要重新转换的类数组。
代理传入 jclassclass_count 个元素的数组。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_retransform_classes 。使用 AddCapabilities
JVMTI_ERROR_UNMODIFIABLE_CLASS classes 之一无法修改。参见 IsModifiableClass
JVMTI_ERROR_INVALID_CLASS classes 之一不是有效的类。
JVMTI_ERROR_UNSUPPORTED_VERSION 重新转换的类文件具有此 VM 不支持的版本号。
JVMTI_ERROR_INVALID_CLASS_FORMAT 重新转换的类文件格式错误(VM 将返回 ClassFormatError )。
JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION 重新转换的类文件定义将导致循环定义(VM 将返回 ClassCircularityError )。
JVMTI_ERROR_FAILS_VERIFICATION 重新转换的类文件字节验证失败。
JVMTI_ERROR_NAMES_DONT_MATCH 重新转换的类文件中定义的类名与旧类对象中的名称不同。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED 重新转换的类文件需要添加一个方法。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED 重新转换的类文件更改字段。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED 重新转换的类文件的直接超类不同,或者直接实现的接口集不同。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED 重新转换的类文件不声明在旧类版本中声明的方法。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED 重新转换的类文件在类属性中存在不受支持的差异。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED 重新转换的类文件具有不同的类修饰符。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED 重新转换的类文件中的方法与旧类版本中的对应方法具有不同的修饰符。
JVMTI_ERROR_ILLEGAL_ARGUMENT class_count 小于 0
JVMTI_ERROR_NULL_POINTER classes NULL

重新定义类

typedef struct {
  jclass klass;
  jint class_byte_count;
  const unsigned char* class_bytes;
} jvmtiClassDefinition;
jvmtiError
RedefineClasses(jvmtiEnv* env,
      jint class_count,
      const jvmtiClassDefinition* class_definitions)
根据提供的定义重新定义所有给定的类。此函数用于用新定义替换类的定义,这在修复并继续调试中可能需要。在要转换现有类文件字节的地方,例如在 字节码检测 中,应使用 RetransformClasses
重新定义可能导致安装新版本的方法。旧方法版本可能变为 obsolete 新方法版本将用于新调用。如果一个方法有活跃的堆栈帧,那些活跃的帧继续运行原始方法版本的字节码。如果需要重置堆栈帧,请使用 PopFrame 弹出具有过时方法版本的帧。
这个函数不会导致任何初始化,除非在通常的 JVM 语义下会发生初始化。换句话说,重新定义一个类不会导致其初始化程序运行。静态字段的值将保持在调用之前的状态。
线程不需要暂停。
清除类中的所有断点。
所有属性都已更新。
重新定义类的实例不受影响——字段保留它们以前的值。实例上的 标签 也不受影响。
为了响应这个号召,JVM 将发送 TI 事件 类文件加载挂钩(如果启用),但不会发送其他 JVM 将发送 TI 事件。
重新定义可能会改变方法体、常量池和属性(除非明确禁止)。重新定义不得添加、删除或重命名字段或方法、更改方法的签名、更改修饰符或更改继承。重新定义不得更改 NestHostNestMembersRecordPermittedSubclasses 属性。这些限制可能会在未来的版本中取消。如果尝试进行不受支持的重新定义,请参阅下面的错误返回说明,了解有关返回的错误代码的信息。类文件字节在通过 ClassFileLoadHook 事件链之前不会被验证或安装,因此返回的错误代码反映了应用于传递到 class_definitions 的字节的转换结果。如果返回 JVMTI_ERROR_NONE 以外的任何错误代码,则将不会安装任何要重新定义的类的新定义。当此函数返回时(错误代码为 JVMTI_ERROR_NONE ),将安装所有要重新定义的类的新定义。
只能在直播阶段调用
87
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_redefine_classes 可以使用 RedefineClasses 重新定义类。
可选功能
can_redefine_any_class RedefineClasses 可以在任何可修改的类上调用。参见 IsModifiableClass 。 (can_redefine_classes 也必须设置)

jvmtiClassDefinition - 类重定义说明
Field Type Description
klass jclass 此类的类对象
class_byte_count jint 定义类的字节数(下)
class_bytes const unsigned char* 定义类的字节(在Java™ 虚拟机规范,第 4 章)
参数
Name Type Description
class_count jint class_definitions中指定的类数
class_definitions const jvmtiClassDefinition* 新类定义的数组
代理传入 jvmtiClassDefinitionclass_count 个元素的数组。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_redefine_classes 能力。使用 AddCapabilities
JVMTI_ERROR_NULL_POINTER class_bytes 之一是 NULL
JVMTI_ERROR_UNMODIFIABLE_CLASS 无法修改 class_definitions 的元素。参见 IsModifiableClass
JVMTI_ERROR_INVALID_CLASS class_definitions 的元素不是有效类。
JVMTI_ERROR_UNSUPPORTED_VERSION 此 VM 不支持新类文件的版本号。
JVMTI_ERROR_INVALID_CLASS_FORMAT 新的类文件格式错误(VM 将返回 ClassFormatError )。
JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION 新的类文件定义将导致循环定义(VM 将返回 ClassCircularityError )。
JVMTI_ERROR_FAILS_VERIFICATION 类字节验证失败。
JVMTI_ERROR_NAMES_DONT_MATCH 新类文件中定义的类名与旧类对象中的名称不同。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED 一个新的类文件需要添加一个方法。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED 新的类版本更改了一个字段。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED 新类版本的直接超类不同,或者直接实现的接口集不同。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED 新类版本不声明在旧类版本中声明的方法。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED 新类版本在类属性方面存在不受支持的差异。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED 新的类版本具有不同的修饰符。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED 新类版本中的方法与旧类版本中的对应方法具有不同的修饰符。
JVMTI_ERROR_UNMODIFIABLE_MODULE 无法修改模块。参见 IsModifiableModule
JVMTI_ERROR_ILLEGAL_ARGUMENT class_count 小于 0
JVMTI_ERROR_NULL_POINTER class_definitions NULL


Object

对象函数: 对象类型:

获取对象大小

jvmtiError
GetObjectSize(jvmtiEnv* env,
      jobject object,
      jlong* size_ptr)
对于 object 指示的对象,通过 size_ptr 返回对象的大小。此大小是此对象消耗的存储量的特定于实现的近似值。它可能包括对象的部分或全部开销,因此对于实现内的比较很有用,但对实现之间的比较没有用。估计值可能会在 JVM 的单次调用期间发生变化。
只能在开始或直播阶段调用
154
1.0
能力
所需功能
参数
Name Type Description
object jobject 要查询的对象。
size_ptr jlong* 返回时,指向对象的字节大小。
Agent 传递一个指向 jlong 的指针。返回时,jlong 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_OBJECT object 不是对象。
JVMTI_ERROR_NULL_POINTER size_ptr NULL

获取对象哈希码

jvmtiError
GetObjectHashCode(jvmtiEnv* env,
      jobject object,
      jint* hash_code_ptr)
对于 object 指示的对象,通过 hash_code_ptr 返回一个哈希码。此哈希码可用于维护对象引用的哈希表,但是,在某些实现中,这可能会对性能产生重大影响——在大多数情况下,标签 将是将信息与对象相关联的更有效方法。此函数保证特定对象在其整个生命周期中具有相同的哈希码值
只能在开始或直播阶段调用
58
1.0
能力
所需功能
参数
Name Type Description
object jobject 要查询的对象。
hash_code_ptr jint* 返回时,指向对象的哈希码。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_OBJECT object 不是对象。
JVMTI_ERROR_NULL_POINTER hash_code_ptr NULL

获取对象监视器使用情况

typedef struct {
  jthread owner;
  jint entry_count;
  jint waiter_count;
  jthread* waiters;
  jint notify_waiter_count;
  jthread* notify_waiters;
} jvmtiMonitorUsage;
jvmtiError
GetObjectMonitorUsage(jvmtiEnv* env,
      jobject object,
      jvmtiMonitorUsage* info_ptr)
获取有关对象监视器的信息。 jvmtiMonitorUsage 结构的字段填充了有关监视器使用情况的信息。
只能在直播阶段调用
59
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_get_monitor_info 可以GetObjectMonitorUsage

jvmtiMonitorUsage - 对象监视器使用信息
Field Type Description
owner jthread 拥有此监视器的线程,如果未使用则为 NULL
entry_count jint 所属线程进入管程的次数
waiter_count jint 等待拥有此监视器的线程数
waiters jthread* waiter_count 等待线程
notify_waiter_count jint 等待此监视器通知的线程数
notify_waiters jthread* 等待通知的 notify_waiter_count 个线程
参数
Name Type Description
object jobject 要查询的对象。
info_ptr jvmtiMonitorUsage* 返回时,填充指定对象的监视器信息。
Agent 传递一个指向 jvmtiMonitorUsage 的指针。返回时,jvmtiMonitorUsage 已设置。 jvmtiMonitorUsageowner 字段返回的对象是 JNI 本地引用,必须是 管理jvmtiMonitorUsage的字段waiters返回的指针是一个新分配的数组。该数组应使用 Deallocate 释放。 jvmtiMonitorUsagewaiters 字段中返回的对象是 JNI 本地引用,必须是 管理jvmtiMonitorUsage的字段notify_waiters返回的指针是一个新分配的数组。该数组应使用 Deallocate 释放。 jvmtiMonitorUsagenotify_waiters 字段中返回的对象是 JNI 本地引用,必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_get_monitor_info 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_OBJECT object 不是对象。
JVMTI_ERROR_NULL_POINTER info_ptr NULL


Field

现场功能:

获取字段名称(和签名)

jvmtiError
GetFieldName(jvmtiEnv* env,
      jclass klass,
      jfieldID field,
      char** name_ptr,
      char** signature_ptr,
      char** generic_ptr)
对于 klass field 指示的字段,通过 name_ptr 返回字段名称,通过 signature_ptr 返回字段签名。
字段签名在 JNI规范 中定义,在中称为 field descriptorsJava™ 虚拟机规范,第 4.3.2 章.
只能在开始或直播阶段调用
60
1.0
能力
所需功能
参数
Name Type Description
klass jclass 要查询的字段的类。
field jfieldID 要查询的字段。
name_ptr char ** 返回时,指向字段名称,编码为 修改后的 UTF-8 字符串。
Agent 传递一个指向 char* 的指针。返回时,char* 指向一个新分配的数组。该数组应使用 Deallocate 释放。如果 name_ptrNULL ,则不返回名称。
signature_ptr char ** 返回时,指向字段签名,编码为 修改后的 UTF-8 字符串。
Agent 传递一个指向 char* 的指针。返回时,char* 指向一个新分配的数组。该数组应使用 Deallocate 释放。如果 signature_ptrNULL ,则不返回签名。
generic_ptr char ** 返回时,指向字段的通用签名,编码为 修改后的 UTF-8 字符串。如果该字段没有通用签名属性,则在返回时指向 NULL
Agent 传递一个指向 char* 的指针。返回时,char* 指向一个新分配的数组。该数组应使用 Deallocate 释放。如果 generic_ptrNULL ,则不返回通用签名。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_INVALID_FIELDID field 不是 jfieldID。

获取字段声明类

jvmtiError
GetFieldDeclaringClass(jvmtiEnv* env,
      jclass klass,
      jfieldID field,
      jclass* declaring_class_ptr)
对于 klassfield 指示的字段,返回通过 declaring_class_ptr 定义它的类。声明类将是 klass 、超类或已实现的接口。
只能在开始或直播阶段调用
61
1.0
能力
所需功能
参数
Name Type Description
klass jclass 要查询的类。
field jfieldID 要查询的字段。
declaring_class_ptr jclass* 返回时,指向声明类
代理将指针传递给 jclass 。返回时,jclass 已设置。 declaring_class_ptr 返回的对象是 JNI 本地引用,必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_INVALID_FIELDID field 不是 jfieldID。
JVMTI_ERROR_NULL_POINTER declaring_class_ptr NULL

获取字段修饰符

jvmtiError
GetFieldModifiers(jvmtiEnv* env,
      jclass klass,
      jfieldID field,
      jint* modifiers_ptr)
对于 klassfield 指示的字段,通过 modifiers_ptr 返回访问标志。访问标志定义在Java™ 虚拟机规范,第 4 章.
只能在开始或直播阶段调用
62
1.0
能力
所需功能
参数
Name Type Description
klass jclass 要查询的类。
field jfieldID 要查询的字段。
modifiers_ptr jint* 返回时,指向访问标志。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_INVALID_FIELDID field 不是 jfieldID。
JVMTI_ERROR_NULL_POINTER modifiers_ptr NULL

是场合成

jvmtiError
IsFieldSynthetic(jvmtiEnv* env,
      jclass klass,
      jfieldID field,
      jboolean* is_synthetic_ptr)
对于 klassfield 指示的字段,返回一个值,指示该字段是否是通过 is_synthetic_ptr 合成的。合成字段由编译器生成,但不存在于原始源代码中。
只能在开始或直播阶段调用
63
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_get_synthetic_attribute 可以测试字段或方法是否是合成的 - IsFieldSynthetic IsMethodSynthetic
参数
Name Type Description
klass jclass 要查询的字段的类。
field jfieldID 要查询的字段。
is_synthetic_ptr jboolean* 返回时,指向此函数的布尔结果。
Agent 传递一个指向 jboolean 的指针。返回时,jboolean 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_get_synthetic_attribute 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_CLASS klass 不是类对象或类已被卸载。
JVMTI_ERROR_INVALID_FIELDID field 不是 jfieldID。
JVMTI_ERROR_NULL_POINTER is_synthetic_ptr NULL


Method

方法功能: 方法类型: 这些函数提供有关方法的信息(表示为 jmethodID )并设置方法的处理方式。

过时的方法

RetransformClasses RedefineClasses 函数可以导致安装新版本的方法。在以下情况下,方法的原始版本被认为等同于新版本: 与新方法版本不等同的原始方法版本称为过时的,并分配一个新的方法ID;原始方法 ID 现在指的是新方法版本。可以使用 IsMethodObsolete 测试方法 ID 是否过时。

获取方法名称(和签名)

jvmtiError
GetMethodName(jvmtiEnv* env,
      jmethodID method,
      char** name_ptr,
      char** signature_ptr,
      char** generic_ptr)
对于method指示的方法,通过name_ptr返回方法名,通过signature_ptr返回方法签名。
方法签名在 JNI规范 中定义,在中称为 method descriptorsJava™ 虚拟机规范,第 4.3.3 章.请注意,这与定义在Java 语言规范.
只能在开始或直播阶段调用
64
1.0
能力
所需功能
参数
Name Type Description
method jmethodID 查询的方法。
name_ptr char ** 返回时,指向方法名称,编码为 修改后的 UTF-8 字符串。
Agent 传递一个指向 char* 的指针。返回时,char* 指向一个新分配的数组。该数组应使用 Deallocate 释放。如果 name_ptrNULL ,则不返回名称。
signature_ptr char ** 返回时,指向方法签名,编码为 修改后的 UTF-8 字符串。
Agent 传递一个指向 char* 的指针。返回时,char* 指向一个新分配的数组。该数组应使用 Deallocate 释放。如果 signature_ptrNULL ,则不返回签名。
generic_ptr char ** 返回时,指向方法的通用签名,编码为 修改后的 UTF-8 字符串。如果该方法没有通用签名属性,则在返回时指向 NULL
Agent 传递一个指向 char* 的指针。返回时,char* 指向一个新分配的数组。该数组应使用 Deallocate 释放。如果 generic_ptrNULL ,则不返回通用签名。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_METHODID method 不是 jmethodID。

获取方法声明类

jvmtiError
GetMethodDeclaringClass(jvmtiEnv* env,
      jmethodID method,
      jclass* declaring_class_ptr)
对于 method 指示的方法,通过 declaring_class_ptr 返回定义它的类。
只能在开始或直播阶段调用
65
1.0
能力
所需功能
参数
Name Type Description
method jmethodID 查询的方法。
declaring_class_ptr jclass* 返回时,指向声明类
代理将指针传递给 jclass 。返回时,jclass 已设置。 declaring_class_ptr 返回的对象是 JNI 本地引用,必须是 管理
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_METHODID method 不是 jmethodID。
JVMTI_ERROR_NULL_POINTER declaring_class_ptr NULL

获取方法修饰符

jvmtiError
GetMethodModifiers(jvmtiEnv* env,
      jmethodID method,
      jint* modifiers_ptr)
对于 method 指示的方法,通过 modifiers_ptr 返回访问标志。访问标志定义在Java™ 虚拟机规范,第 4 章.
只能在开始或直播阶段调用
66
1.0
能力
所需功能
参数
Name Type Description
method jmethodID 查询的方法。
modifiers_ptr jint* 返回时,指向访问标志。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_METHODID method 不是 jmethodID。
JVMTI_ERROR_NULL_POINTER modifiers_ptr NULL

获得最大当地人

jvmtiError
GetMaxLocals(jvmtiEnv* env,
      jmethodID method,
      jint* max_ptr)
对于 method 指示的方法,返回该方法使用的局部变量槽的数量,包括调用时用于向方法传递参数的局部变量。
参见 max_localsJava™ 虚拟机规范,第 4.7.3 章.
只能在开始或直播阶段调用
68
1.0
能力
所需功能
参数
Name Type Description
method jmethodID 查询的方法。
max_ptr jint* 返回时,指向本地插槽的最大数量
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_METHODID method 不是 jmethodID。
JVMTI_ERROR_NATIVE_METHOD method 是本地方法。
JVMTI_ERROR_NULL_POINTER max_ptr NULL

获取参数大小

jvmtiError
GetArgumentsSize(jvmtiEnv* env,
      jmethodID method,
      jint* size_ptr)
对于 method 指示的方法,通过 max_ptr 返回方法参数使用的局部变量槽的数量。请注意,双词参数使用两个槽。
只能在开始或直播阶段调用
69
1.0
能力
所需功能
参数
Name Type Description
method jmethodID 查询的方法。
size_ptr jint* 返回时,指向参数槽的数量
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_METHODID method 不是 jmethodID。
JVMTI_ERROR_NATIVE_METHOD method 是本地方法。
JVMTI_ERROR_NULL_POINTER size_ptr NULL

获取行号表

typedef struct {
  jlocation start_location;
  jint line_number;
} jvmtiLineNumberEntry;
jvmtiError
GetLineNumberTable(jvmtiEnv* env,
      jmethodID method,
      jint* entry_count_ptr,
      jvmtiLineNumberEntry** table_ptr)
对于 method 指示的方法,返回源行号条目表。表的大小通过 entry_count_ptr 返回,表本身通过 table_ptr 返回。
只能在开始或直播阶段调用
70
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_get_line_numbers 可以得到一个方法的行号表

jvmtiLineNumberEntry - 行号表条目
Field Type Description
start_location jlocation 该行开始的 jlocation
line_number jint 行号
参数
Name Type Description
method jmethodID 查询的方法。
entry_count_ptr jint* 返回时,指向表中的条目数
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
table_ptr jvmtiLineNumberEntry** 返回时,指向行号表指针。
Agent 传递一个指向 jvmtiLineNumberEntry* 的指针。返回时,jvmtiLineNumberEntry* 指向新分配的大小为 *entry_count_ptr 的数组。该数组应使用 Deallocate 释放。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_get_line_numbers 。使用 AddCapabilities
JVMTI_ERROR_ABSENT_INFORMATION 类信息不包括行号。
JVMTI_ERROR_INVALID_METHODID method 不是 jmethodID。
JVMTI_ERROR_NATIVE_METHOD method 是本地方法。
JVMTI_ERROR_NULL_POINTER entry_count_ptr NULL
JVMTI_ERROR_NULL_POINTER table_ptr NULL

获取方法位置

jvmtiError
GetMethodLocation(jvmtiEnv* env,
      jmethodID method,
      jlocation* start_location_ptr,
      jlocation* end_location_ptr)
对于method表示的方法,通过start_location_ptrend_location_ptr返回起止地址。在传统的字节码索引方案中,start_location_ptr 将始终指向零,end_location_ptr 将始终指向字节码计数减一。
只能在开始或直播阶段调用
71
1.0
能力
所需功能
参数
Name Type Description
method jmethodID 查询的方法。
start_location_ptr jlocation* 返回时,指向第一个位置,如果位置信息不可用,则指向 -1。如果信息可用并且 GetJLocationFormat 返回 JVMTI_JLOCATION_JVMBCI 那么这将始终为零。
代理将指针传递给 jlocation 。返回时,jlocation 已设置。
end_location_ptr jlocation* 返回时,指向最后一个位置,如果位置信息不可用,则指向 -1
代理将指针传递给 jlocation 。返回时,jlocation 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_ABSENT_INFORMATION 类信息不包括方法大小。
JVMTI_ERROR_INVALID_METHODID method 不是 jmethodID。
JVMTI_ERROR_NATIVE_METHOD method 是本地方法。
JVMTI_ERROR_NULL_POINTER start_location_ptr NULL
JVMTI_ERROR_NULL_POINTER end_location_ptr NULL

获取局部变量表

typedef struct {
  jlocation start_location;
  jint length;
  char* name;
  char* signature;
  char* generic_signature;
  jint slot;
} jvmtiLocalVariableEntry;
jvmtiError
GetLocalVariableTable(jvmtiEnv* env,
      jmethodID method,
      jint* entry_count_ptr,
      jvmtiLocalVariableEntry** table_ptr)
返回局部变量信息。
只能在直播阶段调用
72
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_access_local_variables 可以设置和获取局部变量

jvmtiLocalVariableEntry - 局部变量表条目
Field Type Description
start_location jlocation 局部变量首先有效的代码数组索引(即必须有值的位置)。
length jint 此局部变量的有效部分的长度。局部变量有效的最后一个代码数组索引是 start_location + length
name char* 局部变量名称,编码为 修改后的 UTF-8 字符串。
signature char* 局部变量的类型签名,编码为 修改后的 UTF-8 字符串。签名格式与定义的相同Java™ 虚拟机规范,第 4.3.2 章.
generic_signature char* 局部变量的通用签名,编码为 修改后的 UTF-8 字符串。对于没有通用类型的任何局部变量,此字段的值将为 NULL
slot jint 局部变量的槽。参见 局部变量
参数
Name Type Description
method jmethodID 查询的方法。
entry_count_ptr jint* 返回时,指向表中的条目数
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
table_ptr jvmtiLocalVariableEntry** 返回时,指向局部变量表条目的数组。
Agent 传递一个指向 jvmtiLocalVariableEntry* 的指针。返回时,jvmtiLocalVariableEntry* 指向新分配的大小为 *entry_count_ptr 的数组。该数组应使用 Deallocate 释放。 jvmtiLocalVariableEntryname 字段中返回的指针是新分配的数组。应使用 Deallocate 释放数组。 jvmtiLocalVariableEntrysignature 字段中返回的指针是新分配的数组。应使用 Deallocate 释放数组。 jvmtiLocalVariableEntrygeneric_signature 字段中返回的指针是新分配的数组。应使用 Deallocate 释放数组。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_access_local_variables 能力。使用 AddCapabilities
JVMTI_ERROR_ABSENT_INFORMATION 类信息不包括局部变量信息。
JVMTI_ERROR_INVALID_METHODID method 不是 jmethodID。
JVMTI_ERROR_NATIVE_METHOD method 是本地方法。
JVMTI_ERROR_NULL_POINTER entry_count_ptr NULL
JVMTI_ERROR_NULL_POINTER table_ptr NULL

获取字节码

jvmtiError
GetBytecodes(jvmtiEnv* env,
      jmethodID method,
      jint* bytecode_count_ptr,
      unsigned char** bytecodes_ptr)
对于 method 指示的方法,返回实现该方法的字节码。字节码的数量通过 bytecode_count_ptr 返回。字节码本身通过 bytecodes_ptr 返回。
只能在开始或直播阶段调用
75
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_get_bytecodes 可以获得方法的字节码GetBytecodes
参数
Name Type Description
method jmethodID 查询的方法。
bytecode_count_ptr jint* 返回时,指向字节码数组的长度
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
bytecodes_ptr unsigned char** 返回时,指向字节码数组的指针
Agent 传递一个指向 unsigned char* 的指针。返回时,unsigned char* 指向新分配的大小为 *bytecode_count_ptr 的数组。该数组应使用 Deallocate 释放。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_get_bytecodes 。使用 AddCapabilities
JVMTI_ERROR_INVALID_METHODID method 不是 jmethodID。
JVMTI_ERROR_NATIVE_METHOD method 是本地方法。
JVMTI_ERROR_NULL_POINTER bytecode_count_ptr NULL
JVMTI_ERROR_NULL_POINTER bytecodes_ptr NULL

是本地方法

jvmtiError
IsMethodNative(jvmtiEnv* env,
      jmethodID method,
      jboolean* is_native_ptr)
对于method表示的方法,通过is_native_ptr返回一个值表示该方法是否是native
只能在开始或直播阶段调用
76
1.0
能力
所需功能
参数
Name Type Description
method jmethodID 查询的方法。
is_native_ptr jboolean* 返回时,指向此函数的布尔结果。
Agent 传递一个指向 jboolean 的指针。返回时,jboolean 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_METHODID method 不是 jmethodID。
JVMTI_ERROR_NULL_POINTER is_native_ptr NULL

方法是合成的

jvmtiError
IsMethodSynthetic(jvmtiEnv* env,
      jmethodID method,
      jboolean* is_synthetic_ptr)
对于 method 指示的方法,返回一个值表示该方法是否是通过 is_synthetic_ptr 合成的。合成方法由编译器生成,但不存在于原始源代码中。
只能在开始或直播阶段调用
77
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_get_synthetic_attribute 可以测试字段或方法是否是合成的 - IsFieldSynthetic IsMethodSynthetic
参数
Name Type Description
method jmethodID 查询的方法。
is_synthetic_ptr jboolean* 返回时,指向此函数的布尔结果。
Agent 传递一个指向 jboolean 的指针。返回时,jboolean 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_get_synthetic_attribute 能力。使用 AddCapabilities
JVMTI_ERROR_INVALID_METHODID method 不是 jmethodID。
JVMTI_ERROR_NULL_POINTER is_synthetic_ptr NULL

方法是否过时

jvmtiError
IsMethodObsolete(jvmtiEnv* env,
      jmethodID method,
      jboolean* is_obsolete_ptr)
确定方法 ID 是否引用 obsolete 方法版本。
只能在开始或直播阶段调用
91
1.0
能力
所需功能
参数
Name Type Description
method jmethodID 要查询的方法 ID。
is_obsolete_ptr jboolean* 返回时,指向此函数的布尔结果。
Agent 传递一个指向 jboolean 的指针。返回时,jboolean 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_METHODID method 不是 jmethodID。
JVMTI_ERROR_NULL_POINTER is_obsolete_ptr NULL

设置本机方法前缀

jvmtiError
SetNativeMethodPrefix(jvmtiEnv* env,
      const char* prefix)
此函数通过允许使用应用于名称的前缀重试来修改本地方法解析的失败处理。当与 ClassFileLoadHook 事件 一起使用时,它使本机方法成为 instrumented
由于不能直接检测本地方法(它们没有字节码),因此必须用可以检测的非本地方法包装它们。例如,如果我们有:
native boolean foo(int x);
我们可以转换类文件(使用 ClassFileLoadHook 事件),使其变为:
          boolean foo(int x) {
 ... record entry to foo ...
 return wrapped_foo(x);
}

native boolean wrapped_foo(int x);
        
其中 foo 成为带有附加前缀“wrapped_”的实际本地方法的包装器。请注意,“wrapped_”是一个糟糕的前缀选择,因为它可能构成现有方法的名称,因此类似“$$$MyAgentWrapped$$$_”的名称会更好,但会使这些示例的可读性降低。
包装器将允许在本地方法调用时收集数据,但现在问题变成了将包装方法与本地实现链接起来。也就是说,方法 wrapped_foo 需要解析为 foo 的本机实现,它可能是:
Java_somePackage_someClass_foo(JNIEnv* env, jint x)
此函数允许指定前缀并进行正确的解析。具体来说,当标准解析失败时,将考虑前缀重试解析。解析有两种方式,使用 JNI 函数 RegisterNatives 的显式解析和正常的自动解析。对于 RegisterNatives ,VM 将尝试此关联:
method(foo) -> nativeImplementation(foo)
如果失败,将在方法名称前加上指定的前缀重试解析,从而产生正确的解析:
method(wrapped_foo) -> nativeImplementation(foo)
对于自动解析,VM 将尝试:
method(wrapped_foo) -> nativeImplementation(wrapped_foo)
如果失败,将使用从实现名称中删除的指定前缀重试解析,从而产生正确的解析:
method(wrapped_foo) -> nativeImplementation(foo)
请注意,由于前缀仅在标准解析失败时使用,因此可以选择性地包装本地方法。
由于每个 JVM TI 环境是独立的,可以自己转换字节码,可以应用不止一层的包装器。因此每个环境都需要自己的前缀。由于转换是按顺序应用的,因此前缀(如果应用)将以相同的顺序应用。 ClassFileLoadHook 事件中描述了转换应用程序的顺序。因此,如果三个环境应用了包装器,foo 可能会变成 $env3_$env2_$env1_foo。但是,比方说,如果第二个环境没有对 foo 应用包装器,它就只是 $env3_$env1_foo 。为了能够有效地确定前缀序列,只有在存在非本地包装器时才应用中间前缀。因此,在最后一个示例中,即使 $env1_foo 不是本机方法,也会应用 $env1_ 前缀,因为 $env1_foo 存在。
由于前缀是在解析时使用的,并且解析可能会被任意延迟,因此只要存在相应的带前缀的本机方法,本机方法前缀就必须保持设置。
可以在任何阶段调用
73
1.1
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_set_native_method_prefix 可以设置在本地方法无法解析时应用的前缀 - SetNativeMethodPrefix SetNativeMethodPrefixes
参数
Name Type Description
prefix const char * 要应用的前缀,编码为 修改后的 UTF-8 字符串。
代理传入一个 char 数组。如果 prefixNULL,则取消此环境中的任何现有前缀。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_set_native_method_prefix 能力。使用 AddCapabilities

设置本机方法前缀

jvmtiError
SetNativeMethodPrefixes(jvmtiEnv* env,
      jint prefix_count,
      char** prefixes)
对于普通代理,SetNativeMethodPrefix 将提供所有需要的本地方法前缀。对于执行多个独立类文件转换的元代理(例如,作为另一层代理的代理),此函数允许每个转换都有自己的前缀。前缀按照提供的顺序应用,并按照与从多个 JVM 应用前缀所描述的相同方式进行处理 SetNativeMethodPrefix 中的 TI 环境。
任何先前的前缀都将被替换。因此,使用 prefix_count of 0 调用此函数会禁用此环境中的前缀。
SetNativeMethodPrefix 和这个函数是设置前缀的两种方式。使用前缀调用 SetNativeMethodPrefix 与使用 1prefix_count 调用此函数相同。用 NULL 调用 SetNativeMethodPrefix 与用 0prefix_count 调用这个函数是一样的。
可以在任何阶段调用
74
1.1
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_set_native_method_prefix 可以设置在本地方法无法解析时应用的前缀 - SetNativeMethodPrefix SetNativeMethodPrefixes
参数
Name Type Description
prefix_count jint 要应用的前缀数。
prefixes char ** 应用于此环境的前缀,每个都编码为 修改后的 UTF-8 字符串。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_set_native_method_prefix 能力。使用 AddCapabilities
JVMTI_ERROR_ILLEGAL_ARGUMENT prefix_count 小于 0
JVMTI_ERROR_NULL_POINTER prefixes NULL


原始监视器

原始监视器功能:

创建原始监视器

jvmtiError
CreateRawMonitor(jvmtiEnv* env,
      const char* name,
      jrawMonitorID* monitor_ptr)
创建一个原始监视器。
只能在 OnLoad 或 live 阶段调用
此函数可以从回调到 迭代函数,或从 GarbageCollectionStart GarbageCollectionFinish ObjectFree 事件的事件处理程序调用。
31
1.0
能力
所需功能
参数
Name Type Description
name const char* 标识监视器的名称,编码为 修改后的 UTF-8 字符串。
代理传入一个 char 数组。
monitor_ptr jrawMonitorID* 返回时,指向创建的监视器。
Agent 传递一个指向 jrawMonitorID 的指针。返回时,jrawMonitorID 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER name NULL
JVMTI_ERROR_NULL_POINTER monitor_ptr NULL

销毁原始监视器

jvmtiError
DestroyRawMonitor(jvmtiEnv* env,
      jrawMonitorID monitor)
销毁原始监视器。如果被销毁的monitor已经被该线程进入过,则在销毁前先退出。如果被销毁的monitor已经被其他线程进入,则返回错误,monitor不会被销毁。
只能在 OnLoad 或 live 阶段调用
此函数可以从回调到 迭代函数,或从 GarbageCollectionStart GarbageCollectionFinish ObjectFree 事件的事件处理程序调用。
32
1.0
能力
所需功能
参数
Name Type Description
monitor jrawMonitorID 显示器
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NOT_MONITOR_OWNER 不监视所有者
JVMTI_ERROR_INVALID_MONITOR monitor 不是 jrawMonitorID。

原始监视器输入

jvmtiError
RawMonitorEnter(jvmtiEnv* env,
      jrawMonitorID monitor)
获得原始监视器的独家所有权。同一个线程可能会多次进入监视器。线程必须 exit 监视与输入相同的次数。如果在 OnLoad 期间(在附加线程存在之前)进入监视器并且在附加线程存在时没有退出,则认为进入发生在主线程上。
可以在任何阶段调用
此函数可以从回调到 迭代函数,或从 GarbageCollectionStart GarbageCollectionFinish ObjectFree 事件的事件处理程序调用。
33
1.0
能力
所需功能
参数
Name Type Description
monitor jrawMonitorID 显示器
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_MONITOR monitor 不是 jrawMonitorID。

原始监视器退出

jvmtiError
RawMonitorExit(jvmtiEnv* env,
      jrawMonitorID monitor)
释放原始监视器的独占所有权。
可以在任何阶段调用
此函数可以从回调到 迭代函数,或从 GarbageCollectionStart GarbageCollectionFinish ObjectFree 事件的事件处理程序调用。
34
1.0
能力
所需功能
参数
Name Type Description
monitor jrawMonitorID 显示器
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NOT_MONITOR_OWNER 不监视所有者
JVMTI_ERROR_INVALID_MONITOR monitor 不是 jrawMonitorID。

原始监视器等待

jvmtiError
RawMonitorWait(jvmtiEnv* env,
      jrawMonitorID monitor,
      jlong millis)
等待原始监视器的通知。
导致当前线程等待,直到另一个线程为指定的原始监视器调用 RawMonitorNotify RawMonitorNotifyAll ,或者指定的 timeout 已经过去。
可以在任何阶段调用
此函数可以从回调到 迭代函数,或从 GarbageCollectionStart GarbageCollectionFinish ObjectFree 事件的事件处理程序调用。
35
1.0
能力
所需功能
参数
Name Type Description
monitor jrawMonitorID 显示器
millis jlong 超时时间,以毫秒为单位。如果超时为零,则不考虑实时,线程只是等待直到收到通知。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NOT_MONITOR_OWNER 不监视所有者
JVMTI_ERROR_INTERRUPT 等待被打断,重试
JVMTI_ERROR_INVALID_MONITOR monitor 不是 jrawMonitorID。

原始监视器通知

jvmtiError
RawMonitorNotify(jvmtiEnv* env,
      jrawMonitorID monitor)
通知在原始监视器上等待的单个线程。
可以在任何阶段调用
此函数可以从回调到 迭代函数,或从 GarbageCollectionStart GarbageCollectionFinish ObjectFree 事件的事件处理程序调用。
36
1.0
能力
所需功能
参数
Name Type Description
monitor jrawMonitorID 显示器
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NOT_MONITOR_OWNER 不监视所有者
JVMTI_ERROR_INVALID_MONITOR monitor 不是 jrawMonitorID。

原始监视器通知所有

jvmtiError
RawMonitorNotifyAll(jvmtiEnv* env,
      jrawMonitorID monitor)
通知在原始监视器上等待的所有线程。
可以在任何阶段调用
此函数可以从回调到 迭代函数,或从 GarbageCollectionStart GarbageCollectionFinish ObjectFree 事件的事件处理程序调用。
37
1.0
能力
所需功能
参数
Name Type Description
monitor jrawMonitorID 显示器
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NOT_MONITOR_OWNER 不监视所有者
JVMTI_ERROR_INVALID_MONITOR monitor 不是 jrawMonitorID。


JNI 函数拦截

JNI 函数拦截函数: 通过操纵 JNI 函数表提供拦截和重新发送 Java 本机接口 (JNI) 函数调用的能力。请参阅 JNI 函数Java 本机接口规范.
以下示例说明拦截 NewGlobalRef JNI 调用以计算引用创建。
JNIEnv original_jni_Functions;
JNIEnv redirected_jni_Functions;
int my_global_ref_count = 0;

jobject
MyNewGlobalRef(JNIEnv *jni_env, jobject lobj) {
  ++my_global_ref_count;
  return originalJNIFunctions->NewGlobalRef(env, lobj);
}

void
myInit() {
  jvmtiError err;

  err = (*jvmti_env)->GetJNIFunctionTable(jvmti_env, &original_jni_Functions);
  if (err != JVMTI_ERROR_NONE) {
   die();
  }
  err = (*jvmti_env)->GetJNIFunctionTable(jvmti_env, &redirected_jni_Functions);
  if (err != JVMTI_ERROR_NONE) {
   die();
  }
  redirectedJNIFunctions->NewGlobalRef = MyNewGlobalRef;
   err = (*jvmti_env)->SetJNIFunctionTable(jvmti_env, redirected_jni_Functions);
  if (err != JVMTI_ERROR_NONE) {
   die();
  }
}
   
myInit 被调用后的某个时间,用户的 JNI 代码被执行,这使得调用创建一个新的全局引用。调用转到 myNewGlobalRef 而不是转到正常的 JNI 实现。请注意,保留原始函数表的副本,以便在收集数据后可以调用正常的 JNI 函数。另请注意,任何未被覆盖的 JNI 函数都将正常运行。

设置 JNI 函数表

jvmtiError
SetJNIFunctionTable(jvmtiEnv* env,
      const jniNativeInterface* function_table)
在所有当前和未来的 JNI 环境中设置 JNI 函数表。因此,所有未来的 JNI 调用都指向指定的函数。使用 GetJNIFunctionTable 获取要传递给此函数的函数表。要使此功能生效,JNI 客户端必须使用更新的表条目。由于该表是const定义的,一些编译器可能会优化对表的访问,从而阻止该函数生效。表已复制——对表的本地副本所做的更改无效。此功能仅影响功能表,环境的所有其他方面均不受影响。请参阅示例 多于
只能在开始或直播阶段调用
120
1.0
能力
所需功能
参数
Name Type Description
function_table const jniNativeInterface * 指向新的 JNI 函数表。
Agent 传入一个指向 jniNativeInterface 的指针。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER function_table NULL

获取 JNI 函数表

jvmtiError
GetJNIFunctionTable(jvmtiEnv* env,
      jniNativeInterface** function_table)
获取 JNI 函数表。 JNI 函数表被复制到分配的内存中。如果调用了SetJNIFunctionTable ,则返回修改后的(不是原来的)函数表。仅复制功能表,不复制环境的其他方面。请参阅示例 多于
只能在开始或直播阶段调用
121
1.0
能力
所需功能
参数
Name Type Description
function_table jniNativeInterface ** 返回时,*function_table 指向新分配的 JNI 函数表副本。
Agent 传递一个指向 jniNativeInterface* 的指针。返回时,jniNativeInterface* 指向一个新分配的数组。该数组应使用 Deallocate 释放。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER function_table NULL


事件管理

事件管理功能: 事件管理类型:

设置事件回调

jvmtiError
SetEventCallbacks(jvmtiEnv* env,
      const jvmtiEventCallbacks* callbacks,
      jint size_of_callbacks)
设置为每个事件调用的函数。回调是通过提供替换函数表来指定的。函数表被复制——对表的本地副本的更改无效。这是一个原子操作,所有回调都是一次性设置的。在调用此函数之前不发送任何事件。当条目为 NULL 或事件超出 size_of_callbacks 时,不会发送任何事件。有关事件的详细信息在本文档中描述之后。事件必须启用并具有回调才能发送——调用此函数和 SetEventNotificationMode 的顺序不会影响结果。
只能在 OnLoad 或 live 阶段调用
122
1.0
能力
所需功能
参数
Name Type Description
callbacks const jvmtiEventCallbacks * 新的事件回调。
Agent 传入一个指向 jvmtiEventCallbacks 的指针。如果 callbacksNULL ,删除现有的回调。
size_of_callbacks jint sizeof(jvmtiEventCallbacks) --为了版本兼容性。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_ILLEGAL_ARGUMENT size_of_callbacks 小于 0

设置事件通知模式

typedef enum {
  JVMTI_ENABLE = 1,
  JVMTI_DISABLE = 0
} jvmtiEventMode;
jvmtiError
SetEventNotificationMode(jvmtiEnv* env,
      jvmtiEventMode mode,
      jvmtiEvent event_type,
      jthread event_thread,
       ...)
控制事件的产生。
事件启用/禁用 (jvmtiEventMode)
持续的 Value Description
JVMTI_ENABLE 1 如果 mode JVMTI_ENABLE ,事件 event_type 将被启用
JVMTI_DISABLE 0 如果 mode JVMTI_DISABLE ,事件 event_type 将被禁用
如果 event_threadNULL ,则全局启用或禁用该事件;否则,它为特定线程启用或禁用。如果在线程或全局级别启用特定线程,则会为该线程生成一个事件。
有关特定事件的信息,请参阅 以下
以下事件无法通过此函数在线程级别进行控制。
最初,在线程级别或全局级别均未启用任何事件。
在调用此函数之前,必须具备任何所需的能力(请参阅下面的事件启用能力)。
以下 描述了有关事件的详细信息。
只能在 OnLoad 或 live 阶段调用
2
1.0
能力
所需功能
事件支持能力
能力 事件
can_generate_field_modification_events FieldModification
can_generate_field_access_events FieldAccess
can_generate_single_step_events SingleStep
can_generate_exception_events Exception
ExceptionCatch
can_generate_frame_pop_events FramePop
can_generate_breakpoint_events Breakpoint
can_generate_method_entry_events MethodEntry
can_generate_method_exit_events MethodExit
can_generate_compiled_method_load_events CompiledMethodLoad
CompiledMethodUnload
can_generate_monitor_events MonitorContendedEnter
MonitorContendedEntered
MonitorWait
MonitorWaited
can_generate_vm_object_alloc_events VMObjectAlloc
can_generate_native_method_bind_events NativeMethodBind
can_generate_garbage_collection_events GarbageCollectionStart
GarbageCollectionFinish
can_generate_object_free_events ObjectFree
can_generate_sampled_object_alloc_events SampledObjectAlloc
can_support_virtual_threads VirtualThreadStart
VirtualThreadEnd
参数
Name Type Description
mode jvmtiEventMode JVMTI_ENABLEJVMTI_DISABLE
event_type jvmtiEvent 要控制的事件
event_thread jthread 要控制的线程
如果 event_threadNULL ,则事件在全局级别进行控制。
... ... 为将来扩展
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_INVALID_THREAD event_thread 是非 NULL 并且不是有效线程。
JVMTI_ERROR_THREAD_NOT_ALIVE event_thread 是非 NULL 并且不存在(尚未启动或已终止)。
JVMTI_ERROR_ILLEGAL_ARGUMENT 试图对不允许线程级控制的事件进行线程级控制。
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 不具备必需的事件启用能力。
JVMTI_ERROR_ILLEGAL_ARGUMENT mode 不是 jvmtiEventMode。
JVMTI_ERROR_INVALID_EVENT_TYPE event_type 不是 jvmtiEvent。

生成事件

jvmtiError
GenerateEvents(jvmtiEnv* env,
      jvmtiEvent event_type)
生成事件以表示 VM 的当前状态。例如,如果 event_type JVMTI_EVENT_COMPILED_METHOD_LOAD ,将为每个当前编译的方法发送一个 CompiledMethodLoad 事件。不会发送已加载和现在已卸载的方法。之前发送的事件的历史不会影响此函数发送的事件——例如,每次调用此函数时将发送所有当前编译的方法。
当程序执行开始后由于代理附加而可能错过事件时,此功能很有用;此函数生成错过的事件。
尝试执行 Java 编程语言代码或 JNI 函数可能会暂停,直到此函数返回 - 因此不应从发送事件的线程调用它们。只有在发送、处理并返回错过的事件后,此函数才会返回。事件可能在与事件发生所在的线程不同的线程上发送。必须使用 SetEventCallbacks 设置事件的回调,并且必须使用 SetEventNotificationMode 启用事件,否则事件将不会发生。如果 VM 不再具有生成部分或全部请求事件的信息,则不会发送这些事件 - 不会返回任何错误。
仅支持以下事件:
只能在直播阶段调用
123
1.0
能力
所需功能
可选功能
能力 影响
can_generate_compiled_method_load_events 可以在编译或卸载方法时生成事件
参数
Name Type Description
event_type jvmtiEvent 要生成的事件类型。必须是其中之一:
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY event_type JVMTI_EVENT_COMPILED_METHOD_LOAD can_generate_compiled_method_load_events false
JVMTI_ERROR_ILLEGAL_ARGUMENT event_type 不同于 JVMTI_EVENT_COMPILED_METHOD_LOAD JVMTI_EVENT_DYNAMIC_CODE_GENERATED
JVMTI_ERROR_INVALID_EVENT_TYPE event_type 不是 jvmtiEvent。


扩展机制

扩展机制功能: 扩展机制功能类型: 扩展机制类型: 这些函数允许 JVM TI 实现提供超出本规范中定义的功能和事件。
扩展函数和扩展事件都有参数,每个参数都有从下表中选择的“类型”和“种类”:
扩展函数/事件参数类型 (jvmtiParamTypes)
持续的 Value Description
JVMTI_TYPE_JBYTE 101 Java 编程语言原始类型 - byte。 JNI 类型 jbyte
JVMTI_TYPE_JCHAR 102 Java 编程语言原始类型 - char。 JNI 类型 jchar
JVMTI_TYPE_JSHORT 103 Java 编程语言原始类型 - short。 JNI 类型 jshort
JVMTI_TYPE_JINT 104 Java 编程语言原始类型 - int。 JNI 类型 jint
JVMTI_TYPE_JLONG 105 Java 编程语言原始类型 - long。 JNI 类型 jlong
JVMTI_TYPE_JFLOAT 106 Java 编程语言原始类型 - float。 JNI 类型 jfloat
JVMTI_TYPE_JDOUBLE 107 Java 编程语言原始类型 - double。 JNI 类型 jdouble
JVMTI_TYPE_JBOOLEAN 108 Java 编程语言原始类型 - boolean。 JNI 类型 jboolean
JVMTI_TYPE_JOBJECT 109 Java 编程语言对象类型 - java.lang.Object。 JNI 类型 jobject 。返回值是 JNI 本地引用,必须进行管理。
JVMTI_TYPE_JTHREAD 110 Java 编程语言对象类型 - java.lang.Thread。虚拟机 TI 类型 jthread 。返回值是 JNI 本地引用,必须进行管理。
JVMTI_TYPE_JCLASS 111 Java 编程语言对象类型 - java.lang.Class。 JNI 类型 jclass 。返回值是 JNI 本地引用,必须进行管理。
JVMTI_TYPE_JVALUE 112 所有 Java 编程语言原始类型和对象类型的联合 - JNI 类型 jvalue 。表示对象类型的返回值是 JNI 本地引用,必须进行管理。
JVMTI_TYPE_JFIELDID 113 Java 编程语言字段标识符 - JNI 类型 jfieldID
JVMTI_TYPE_JMETHODID 114 Java 编程语言方法标识符 - JNI 类型 jmethodID
JVMTI_TYPE_CCHAR 115 C 编程语言类型 - char
JVMTI_TYPE_CVOID 116 C 编程语言类型 - void
JVMTI_TYPE_JNIENV 117 JNI 环境 - JNIEnv。应与正确的 jvmtiParamKind 一起使用以使其成为指针类型。
扩展函数/事件参数种类 (jvmtiParamKind)
持续的 Value Description
JVMTI_KIND_IN 91 传入参数 - foo
JVMTI_KIND_IN_PTR 92 传入指针参数 - const foo*
JVMTI_KIND_IN_BUF 93 输入数组参数 - const foo*
JVMTI_KIND_ALLOC_BUF 94 传出分配数组参数 - foo**。免费使用 Deallocate
JVMTI_KIND_ALLOC_ALLOC_BUF 95 分配数组参数的传出分配数组 - foo***。免费使用 Deallocate
JVMTI_KIND_OUT 96 传出参数 - foo*
JVMTI_KIND_OUT_BUF 97 传出数组参数(由代理预先分配)- foo*。不要Deallocate

扩展函数/事件参数信息

typedef struct {
  char* name;
  jvmtiParamKind kind;
  jvmtiParamTypes base_type;
  jboolean null_ok;
} jvmtiParamInfo;
jvmtiParamInfo - 扩展功能/事件参数信息
Field Type Description
name char* 参数名称,编码为 修改后的 UTF-8 字符串
kind jvmtiParamKind 参数的种类 - 类型修饰符
base_type jvmtiParamTypes 参数的基类型——由kind修改
null_ok jboolean 允许使用 NULL 参数吗?仅适用于指针和对象类型。

扩展功能

typedef jvmtiError (JNICALL *jvmtiExtensionFunction)
  (jvmtiEnv* jvmti_env,
   ...);
这是特定于实现的扩展函数。
参数
Name Type Description
jvmti_env jvmtiEnv * 虚拟机 TI 环境是扩展功能的唯一固定参数。
... ... 扩展函数特定参数

获取扩展函数

typedef struct {
  jvmtiExtensionFunction func;
  char* id;
  char* short_description;
  jint param_count;
  jvmtiParamInfo* params;
  jint error_count;
  jvmtiError* errors;
} jvmtiExtensionFunctionInfo;
jvmtiError
GetExtensionFunctions(jvmtiEnv* env,
      jint* extension_count_ptr,
      jvmtiExtensionFunctionInfo** extensions)
返回扩展函数集。
只能在 OnLoad 或 live 阶段调用
124
1.0
能力
所需功能

jvmtiExtensionFunctionInfo - 扩展功能信息
Field Type Description
func jvmtiExtensionFunction 实际调用的函数
id char* 扩展函数的标识符,编码为 修改后的 UTF-8 字符串。使用包名称约定。例如,com.sun.hotspot.bar
short_description char* 函数的一句话描述,编码为 修改后的 UTF-8 字符串。
param_count jint 不包括jvmtiEnv *jvmti_env的参数个数
params jvmtiParamInfo * param_count 参数数组(jvmtiEnv *jvmti_env 不包括)
error_count jint 可能返回的错误数(不包括通用错误)
errors jvmtiError * error_count 个可能的错误数组
参数
Name Type Description
extension_count_ptr jint* 返回时,指向扩展函数的数量
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
extensions jvmtiExtensionFunctionInfo** 返回一组扩展函数信息,每个函数一个
Agent 传递一个指向 jvmtiExtensionFunctionInfo* 的指针。返回时,jvmtiExtensionFunctionInfo* 指向新分配的大小为 *extension_count_ptr 的数组。该数组应使用 Deallocate 释放。 jvmtiExtensionFunctionInfoid 字段中返回的指针是新分配的数组。应使用 Deallocate 释放数组。 jvmtiExtensionFunctionInfoshort_description 字段中返回的指针是新分配的数组。应使用 Deallocate 释放数组。 jvmtiExtensionFunctionInfoparams 字段中返回的指针是新分配的数组。应使用 Deallocate 释放数组。 jvmtiParamInfoname 字段中返回的指针是新分配的数组。应使用 Deallocate 释放数组。 jvmtiExtensionFunctionInfo的字段errors中返回的指针是新分配的数组。应使用 Deallocate 释放数组。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER extension_count_ptr NULL
JVMTI_ERROR_NULL_POINTER extensions NULL

获取扩展事件

typedef struct {
  jint extension_event_index;
  char* id;
  char* short_description;
  jint param_count;
  jvmtiParamInfo* params;
} jvmtiExtensionEventInfo;
jvmtiError
GetExtensionEvents(jvmtiEnv* env,
      jint* extension_count_ptr,
      jvmtiExtensionEventInfo** extensions)
返回扩展事件集。
只能在 OnLoad 或 live 阶段调用
125
1.0
能力
所需功能

jvmtiExtensionEventInfo - 扩展事件信息
Field Type Description
extension_event_index jint 事件标识索引
id char* 扩展事件的标识符,编码为 修改后的 UTF-8 字符串。使用包名称约定。例如,com.sun.hotspot.bar
short_description char* 事件的一句话描述,编码为 修改后的 UTF-8 字符串。
param_count jint 不包括jvmtiEnv *jvmti_env的参数个数
params jvmtiParamInfo * param_count 参数数组(jvmtiEnv *jvmti_env 不包括)
参数
Name Type Description
extension_count_ptr jint* 返回时,指向扩展事件的数量
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
extensions jvmtiExtensionEventInfo** 返回一组扩展事件信息,每个事件一个
Agent 传递一个指向 jvmtiExtensionEventInfo* 的指针。返回时,jvmtiExtensionEventInfo* 指向新分配的大小为 *extension_count_ptr 的数组。该数组应使用 Deallocate 释放。 jvmtiExtensionEventInfoid 字段中返回的指针是新分配的数组。应使用 Deallocate 释放数组。 jvmtiExtensionEventInfoshort_description 字段中返回的指针是新分配的数组。应使用 Deallocate 释放数组。 jvmtiExtensionEventInfoparams 字段中返回的指针是新分配的数组。应使用 Deallocate 释放数组。 jvmtiParamInfoname 字段中返回的指针是新分配的数组。应使用 Deallocate 释放数组。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER extension_count_ptr NULL
JVMTI_ERROR_NULL_POINTER extensions NULL

扩展事件

typedef void (JNICALL *jvmtiExtensionEvent)
  (jvmtiEnv* jvmti_env,
   ...);
这是特定于实现的事件。事件处理程序设置为 SetExtensionEventCallback
扩展事件的事件处理程序必须声明为可变参数以匹配此定义。如果不这样做,可能会导致调用约定不匹配和某些平台上的未定义行为。
例如,如果GetExtensionEvents 返回的jvmtiParamInfo表示有一个jint参数,则应该声明事件处理程序:
  void JNICALL myHandler(jvmtiEnv* jvmti_env, ...)
注意表示可变参数的终端“...”。需要使用 C 编程语言的 va_* 语法提取 myHandler 中的 jint 参数。
参数
Name Type Description
jvmti_env jvmtiEnv * 虚拟机 TI 环境是扩展事件的唯一固定参数。
... ... 扩展事件特定参数

设置扩展事件回调

jvmtiError
SetExtensionEventCallback(jvmtiEnv* env,
      jint extension_event_index,
      jvmtiExtensionEvent callback)
设置扩展事件的回调函数并启用该事件。或者,如果回调是 NULL ,则禁用该事件。请注意,与标准事件不同,设置回调和启用事件是一个单一的操作。
只能在 OnLoad 或 live 阶段调用
126
1.0
能力
所需功能
参数
Name Type Description
extension_event_index jint 标识要设置的回调。该索引是 jvmtiExtensionEventInfo extension_event_index 字段。
callback jvmtiExtensionEvent 如果callback不是NULL,设置callback为事件回调函数并使能事件。
如果 callbackNULL ,则禁用该事件。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_ILLEGAL_ARGUMENT extension_event_index 不是 GetExtensionEvents 返回的 extension_event_index


能力

能力函数: 能力类型: 功能函数允许您更改 JVM 可用的功能 TI--即JVM 可以调用TI函数,可以产生什么事件,这些事件和函数可以提供什么功能。
每个函数和事件的“能力”部分描述了它们关联的能力(如果有的话)。 “必需的功能”意味着它可供使用,无需添加任何功能即可使用它。 “可选功能”是指代理必须具备该能力才能使用。要拥有能力,代理必须添加功能。 “可选特性”描述了如果添加,扩展特性集的能力。
每个 JVM 的潜在可用功能 TI 实现不同。根据实现,能力: 通常,添加功能可能会导致执行速度、启动时间和/或内存占用方面的成本。请注意,使用能力的开销与拥有能力的开销完全不同。以单步执行为例。当启用单步执行时(即,当启用事件并因此主动发送事件时)在任何实现中,在每条指令上发送和处理事件的开销都是巨大的。然而,拥有能力的开销可能很小或很大,这取决于实现。此外,功能何时以及是否可能可用取决于实现。一些示例:
每个 JVM TI environment 拥有自己的一套功能。最初,该集合是空的。必须添加任何所需的功能。如果可能,应在 OnLoad 阶段添加功能。对于大多数虚拟机,某些功能需要为虚拟机进行特殊设置,并且此设置必须在虚拟机开始执行之前的 OnLoad 阶段进行。添加功能后,只有在环境明确放弃的情况下才能将其删除。
代理可以 确定此 VM 可能提供的功能添加要使用的功能释放不再需要的能力检查当前可用的功能

能力示例

例如,刚启动的代理(在 OnLoad 函数中)想要启用所有可能的功能。请注意,一般来说,这是不可取的,因为代理可能会因未使用的功能而遭受性能损失。在 C 中,代码可能如下所示:
    jvmtiCapabilities capa;
    jvmtiError err;

    err = (*jvmti)->GetPotentialCapabilities(jvmti, &capa);
    if (err == JVMTI_ERROR_NONE) {
      err = (*jvmti)->AddCapabilities(jvmti, &capa);
   
例如,如果一个代理想要检查它是否可以获取某个方法的字节码(也就是说,它想要检查它之前是否添加了此功能并且没有放弃它),代码在 C 中可能如下所示:
    jvmtiCapabilities capa;
    jvmtiError err;

    err = (*jvmti)->GetCapabilities(jvmti, &capa);
    if (err == JVMTI_ERROR_NONE) {
      if (capa.can_get_bytecodes) { ... } }
   

能力结构

此类别中的函数使用此功能结构,其中包含与每个功能相对应的布尔标志:
typedef struct {
  unsigned int can_tag_objects : 1;
  unsigned int can_generate_field_modification_events : 1;
  unsigned int can_generate_field_access_events : 1;
  unsigned int can_get_bytecodes : 1;
  unsigned int can_get_synthetic_attribute : 1;
  unsigned int can_get_owned_monitor_info : 1;
  unsigned int can_get_current_contended_monitor : 1;
  unsigned int can_get_monitor_info : 1;
  unsigned int can_pop_frame : 1;
  unsigned int can_redefine_classes : 1;
  unsigned int can_signal_thread : 1;
  unsigned int can_get_source_file_name : 1;
  unsigned int can_get_line_numbers : 1;
  unsigned int can_get_source_debug_extension : 1;
  unsigned int can_access_local_variables : 1;
  unsigned int can_maintain_original_method_order : 1;
  unsigned int can_generate_single_step_events : 1;
  unsigned int can_generate_exception_events : 1;
  unsigned int can_generate_frame_pop_events : 1;
  unsigned int can_generate_breakpoint_events : 1;
  unsigned int can_suspend : 1;
  unsigned int can_redefine_any_class : 1;
  unsigned int can_get_current_thread_cpu_time : 1;
  unsigned int can_get_thread_cpu_time : 1;
  unsigned int can_generate_method_entry_events : 1;
  unsigned int can_generate_method_exit_events : 1;
  unsigned int can_generate_all_class_hook_events : 1;
  unsigned int can_generate_compiled_method_load_events : 1;
  unsigned int can_generate_monitor_events : 1;
  unsigned int can_generate_vm_object_alloc_events : 1;
  unsigned int can_generate_native_method_bind_events : 1;
  unsigned int can_generate_garbage_collection_events : 1;
  unsigned int can_generate_object_free_events : 1;
  unsigned int can_force_early_return : 1;
  unsigned int can_get_owned_monitor_stack_depth_info : 1;
  unsigned int can_get_constant_pool : 1;
  unsigned int can_set_native_method_prefix : 1;
  unsigned int can_retransform_classes : 1;
  unsigned int can_retransform_any_class : 1;
  unsigned int can_generate_resource_exhaustion_heap_events : 1;
  unsigned int can_generate_resource_exhaustion_threads_events : 1;
  unsigned int can_generate_early_vmstart : 1;
  unsigned int can_generate_early_class_hook_events : 1;
  unsigned int can_generate_sampled_object_alloc_events : 1;
  unsigned int can_support_virtual_threads : 1;
  unsigned int : 3;
  unsigned int : 16;
  unsigned int : 16;
  unsigned int : 16;
  unsigned int : 16;
  unsigned int : 16;
} jvmtiCapabilities;
jvmtiCapabilities - 能力结构
所有类型都是unsigned int : 1
Field Description Since
can_tag_objects 可以设置和获取标签,如 堆类 中所述。 1.0
can_generate_field_modification_events 可以在现场修改上设置观察点 - SetFieldModificationWatch 1.0
can_generate_field_access_events 可以设置现场访问观察点 - SetFieldAccessWatch 1.0
can_get_bytecodes 可以获得方法的字节码GetBytecodes 1.0
can_get_synthetic_attribute 可以测试字段或方法是否是合成的 - IsFieldSynthetic IsMethodSynthetic 1.0
can_get_owned_monitor_info 可以获得有关监视器所有权的信息 - GetOwnedMonitorInfo 1.0
can_get_current_contended_monitor 可以GetCurrentContendedMonitor 1.0
can_get_monitor_info 可以GetObjectMonitorUsage 1.0
can_pop_frame 可以从堆栈中弹出帧 - PopFrame 1.0
can_redefine_classes 可以使用 RedefineClasses 重新定义类。 1.0
can_signal_thread 可以向线程发送停止或中断 1.0
can_get_source_file_name 可以得到一个类的源文件名 1.0
can_get_line_numbers 可以得到一个方法的行号表 1.0
can_get_source_debug_extension 可以获得一个类的源码调试扩展 1.0
can_access_local_variables 可以设置和获取局部变量 1.0
can_maintain_original_method_order 可以按照它们在类文件中出现的顺序返回方法 1.0
can_generate_single_step_events 可以获得一小步个事件 1.0
can_generate_exception_events 可以获得 抛出异常异常捕获 事件 1.0
can_generate_frame_pop_events 可以 set 从而获得 FramePop 事件 1.0
can_generate_breakpoint_events 可以 set 从而获得 Breakpoint 事件 1.0
can_suspend 可以暂停和恢复线程 1.0
can_redefine_any_class RedefineClasses 可以在任何可修改的类上调用。参见 IsModifiableClass 。 (can_redefine_classes 也必须设置) 1.0
can_get_current_thread_cpu_time 可以get当前线程CPU时间 1.0
can_get_thread_cpu_time 可以get线程CPU时间 1.0
can_generate
_method_entry_events
可以在进入方法时生成方法进入事件 1.0
can_generate
_method_exit_events
可以在离开方法时生成方法退出事件 1.0
can_generate
_all_class_hook_events
可以为每个加载的类生成 ClassFileLoadHook 事件。 1.0
can_generate
_compiled_method_load_events
可以在编译或卸载方法时生成事件 1.0
can_generate
_monitor_events
可以在监视器活动上生成事件 1.0
can_generate
_vm_object_alloc_events
可以在对象的 VM 分配上生成事件 1.0
can_generate
_native_method_bind_events
当本地方法绑定到它的实现时可以生成事件 1.0
can_generate
_garbage_collection_events
可以在垃圾收集开始或结束时生成事件 1.0
can_generate
_object_free_events
可以在垃圾收集器释放对象时生成事件 1.0
can_force_early_return 可以提前从方法返回,如 强制提前返回类别 中所述。 1.1
can_get_owned_monitor_stack_depth_info 可以获取有关具有堆栈深度的拥有监视器的信息 - GetOwnedMonitorStackDepthInfo 1.1
can_get_constant_pool 可以拿到一个类的常量池-GetConstantPool 1.1
can_set_native_method_prefix 可以设置在本地方法无法解析时应用的前缀 - SetNativeMethodPrefix SetNativeMethodPrefixes 1.1
can_retransform_classes 可以使用 RetransformClasses 重新转换类。除了具体实现对该能力施加的限制外(参见能力部分),必须在该环境中首次启用ClassFileLoadHook 事件之前设置该能力。在第一次启用 ClassFileLoadHook 时拥有此功能的环境被称为再转化能力.在第一次启用 ClassFileLoadHook 时不具备此功能的环境被称为无法再改造. 1.1
can_retransform_any_class RetransformClasses 可以在任何可修改的类上调用。参见 IsModifiableClass 。 (can_retransform_classes 也必须设置) 1.1
can_generate_resource_exhaustion_heap_events 可以在 VM 无法从 Java 分配内存时生成事件TM平台堆。参见 ResourceExhausted 1.1
can_generate_resource_exhaustion_threads_events 可以在 VM 无法创建线程时生成事件。参见 ResourceExhausted 1.1
can_generate_early_vmstart 可以提前生成 VMStart 事件。参见 VMStart 9
can_generate_early_class_hook_events 可以在原始阶段产生ClassFileLoadHook 事件。如果启用此功能和 can_generate_all_class_hook_events ,则可以为在原始阶段加载的类发布 ClassFileLoadHook 事件。参见 ClassFileLoadHook 9
can_generate_sampled_object_alloc_events 可以生成采样分配事件。如果启用此功能,则可以调用堆采样方法 SetHeapSamplingInterval 并生成 SampledObjectAlloc 事件。 11
can_support_virtual_threads can_support_virtual_threads 是 Java 平台的预览 API。 预览功能可能会在未来的版本中删除,或升级为 Java 平台的永久功能。
可以支持虚拟线程。如果启用此功能,则可以调用以下函数:SuspendAllVirtualThreads ResumeAllVirtualThreads ,并且可以启用以下事件:VirtualThreadStart VirtualThreadEnd
19

获得潜在能力

jvmtiError
GetPotentialCapabilities(jvmtiEnv* env,
      jvmtiCapabilities* capabilities_ptr)
通过 capabilities_ptr JVM 返回 此时此环境可能拥有的 TI 功能。返回的能力与 VM 实现的完整能力集在两种情况下不同:另一个环境拥有只能由一个环境拥有的能力,或者当前阶段是 live,某些能力只能在OnLoad阶段添加。 AddCapabilities 函数可用于设置任何或所有或这些功能。当前拥有的能力包括在内。
通常此函数用于 OnLoad 函数中。某些虚拟机可能允许在运行阶段添加一组有限的功能。在这种情况下,潜在可用功能集可能与 OnLoad 阶段集不同。
请参阅 能力示例
只能在 OnLoad 或 live 阶段调用
140
1.0
能力
所需功能
参数
Name Type Description
capabilities_ptr jvmtiCapabilities* 返回时,指向 JVM 可能添加的 TI 功能。
Agent 传递一个指向 jvmtiCapabilities 的指针。返回时,jvmtiCapabilities 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER capabilities_ptr NULL

添加功能

jvmtiError
AddCapabilities(jvmtiEnv* env,
      const jvmtiCapabilities* capabilities_ptr)
通过在 * capabilities_ptr 中添加值设置为 1 (1) 的功能来设置新功能。保留所有以前的功能。通常此函数用于 OnLoad 函数中。某些虚拟机可能允许在运行阶段添加一组有限的功能。
请参阅 能力示例
只能在 OnLoad 或 live 阶段调用
142
1.0
能力
所需功能
参数
Name Type Description
capabilities_ptr const jvmtiCapabilities* 指向 JVM 要添加的 TI 功能。
Agent 传入一个指向 jvmtiCapabilities 的指针。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NOT_AVAILABLE 所需的功能甚至可能不可用。
JVMTI_ERROR_NULL_POINTER capabilities_ptr NULL

放弃能力

jvmtiError
RelinquishCapabilities(jvmtiEnv* env,
      const jvmtiCapabilities* capabilities_ptr)
放弃 * capabilities_ptr 中值设置为一 (1 ) 的能力。一些实现可能只允许一个环境具有一种能力(参见 能力介绍 )。此功能释放功能,以便其他代理可以使用它们。保留所有其他功能。该功能将不再出现在 GetCapabilities 中。试图放弃代理不具备的能力不是错误。
只能在 OnLoad 或 live 阶段调用
143
1.0
能力
所需功能
参数
Name Type Description
capabilities_ptr const jvmtiCapabilities* 指向 JVM TI 能力放弃。
Agent 传入一个指向 jvmtiCapabilities 的指针。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER capabilities_ptr NULL

获得能力

jvmtiError
GetCapabilities(jvmtiEnv* env,
      jvmtiCapabilities* capabilities_ptr)
通过 capabilities_ptr 返回可选的 JVM 此环境当前拥有的 TI 功能。每个拥有的能力在 能力结构 的相应字段中由一个 (1) 表示。除非已使用 AddCapabilities 成功添加,否则环境不具备能力。环境只有在使用 RelinquishCapabilities 放弃时才会失去对能力的拥有。因此,此函数返回已进行的 AddCapabilitiesRelinquishCapabilities 调用的最终结果。
请参阅 能力示例
可以在任何阶段调用
89
1.0
能力
所需功能
参数
Name Type Description
capabilities_ptr jvmtiCapabilities* 返回时,指向 JVM TI 能力。
Agent 传递一个指向 jvmtiCapabilities 的指针。返回时,jvmtiCapabilities 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER capabilities_ptr NULL


计时器

定时器功能: 定时器类型: 这些函数提供计时信息。未指定更新时间的分辨率。它们提供纳秒级精度,但不一定是纳秒级精度。可以使用定时器信息函数访问有关定时器的详细信息,例如它们的最大值。

定时器信息

每个定时器的信息函数返回这个数据结构。
typedef struct {
  jlong max_value;
  jboolean may_skip_forward;
  jboolean may_skip_backward;
  jvmtiTimerKind kind;
  jlong reserved1;
  jlong reserved2;
} jvmtiTimerInfo;
jvmtiTimerInfo - 计时器信息
Field Type Description
max_value jlong 计时器可以达到的最大值。达到此值后,计时器返回到零。这是一个无符号值。如果作为 jlong(有符号值)进行测试或打印,它可能看起来是一个负数。
may_skip_forward jboolean 如果为 true,则可以从外部调整计时器并因此向前跳转。如果为 false,定时器值将永远不会比实时增加得更快。
may_skip_backward jboolean 如果为 true,则可以从外部调整计时器,从而向后跳。如果为假,定时器值将单调递增。
kind jvmtiTimerKind 定时器的那种。在不区分用户时间和系统时间的平台上,返回JVMTI_TIMER_TOTAL_CPU
reserved1 jlong 保留以供将来使用。
reserved2 jlong 保留以供将来使用。
定时器种类在哪里——
计时器种类 (jvmtiTimerKind)
持续的 Value Description
JVMTI_TIMER_USER_CPU 30 线程处于用户模式的 CPU 时间。
JVMTI_TIMER_TOTAL_CPU 31 线程处于用户或系统模式的 CPU 时间。
JVMTI_TIMER_ELAPSED 32 经过的时间。

获取当前线程 CPU 计时器信息

jvmtiError
GetCurrentThreadCpuTimerInfo(jvmtiEnv* env,
      jvmtiTimerInfo* info_ptr)
获取有关 GetCurrentThreadCpuTime 计时器的信息。 jvmtiTimerInfo 结构的字段填充了有关计时器的详细信息。此信息特定于平台和 GetCurrentThreadCpuTime 的实现,因此不会因线程而异,也不会在 VM 的特定调用期间发生变化。
请注意,GetCurrentThreadCpuTime GetThreadCpuTime 的实现可能不同,因此 GetCurrentThreadCpuTimerInfoGetThreadCpuTimerInfo 返回的值可能不同——有关更多信息,请参阅 GetCurrentThreadCpuTime
只能在开始或直播阶段调用
此函数可以从回调到 迭代函数,或从 GarbageCollectionStart GarbageCollectionFinish ObjectFree 事件的事件处理程序调用。
134
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_get_current_thread_cpu_time 可以获得当前线程的CPU时间。
参数
Name Type Description
info_ptr jvmtiTimerInfo* 返回时,填充了描述 GetCurrentThreadCpuTime 返回时间的信息。
Agent 传递一个指向 jvmtiTimerInfo 的指针。返回时,jvmtiTimerInfo 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_get_current_thread_cpu_time 。使用 AddCapabilities
JVMTI_ERROR_NULL_POINTER info_ptr NULL

获取当前线程 CPU 时间

jvmtiError
GetCurrentThreadCpuTime(jvmtiEnv* env,
      jlong* nanos_ptr)
返回当前线程使用的 CPU 时间。
请注意,GetThreadCpuTime 函数为任何线程(包括当前线程)提供 CPU 时间。 GetCurrentThreadCpuTime 的存在是为了支持无法为当前线程以外的线程提供 CPU 时间的平台,或者为当前线程提供更准确信息的平台(参见 GetCurrentThreadCpuTimerInfo GetThreadCpuTimerInfo )。当前线程可能不是虚拟线程。否则,将返回错误代码JVMTI_ERROR_UNSUPPORTED_OPERATION 。在许多平台上,此调用将等效于:
 GetThreadCpuTime(env, NULL, nanos_ptr)
只能在开始或直播阶段调用
此函数可以从回调到 迭代函数,或从 GarbageCollectionStart GarbageCollectionFinish ObjectFree 事件的事件处理程序调用。
135
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_get_current_thread_cpu_time 可以获得当前线程的CPU时间。
如果在线程启动后启用此功能,则实现可以选择任何时间(包括启用该功能的时间)作为 CPU 时间收集的开始点。
此功能必须可能在 can_get_thread_cpu_time 可能可用的任何平台上可用。
参数
Name Type Description
nanos_ptr jlong* 返回时,指向此线程使用的 CPU 时间(以纳秒为单位)。这是一个无符号值。如果作为 jlong(有符号值)进行测试或打印,它可能看起来是一个负数。
Agent 传递一个指向 jlong 的指针。返回时,jlong 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_get_current_thread_cpu_time 。使用 AddCapabilities
JVMTI_ERROR_UNSUPPORTED_OPERATION 当前线程是虚拟线程。
JVMTI_ERROR_NULL_POINTER nanos_ptr NULL

获取线程 CPU 定时器信息

jvmtiError
GetThreadCpuTimerInfo(jvmtiEnv* env,
      jvmtiTimerInfo* info_ptr)
获取有关 GetThreadCpuTime 计时器的信息。 jvmtiTimerInfo 结构的字段填充了有关计时器的详细信息。此信息特定于平台和 GetThreadCpuTime 的实现,因此不会因线程而异,也不会在 VM 的特定调用期间发生变化。
请注意,GetCurrentThreadCpuTime GetThreadCpuTime 的实现可能不同,因此 GetCurrentThreadCpuTimerInfo GetThreadCpuTimerInfo 返回的值可能不同——有关更多信息,请参阅 GetCurrentThreadCpuTime
只能在直播阶段调用
136
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_get_thread_cpu_time 可以获得线程CPU时间。
参数
Name Type Description
info_ptr jvmtiTimerInfo* 返回时,填充了描述 GetThreadCpuTime 返回时间的信息。
Agent 传递一个指向 jvmtiTimerInfo 的指针。返回时,jvmtiTimerInfo 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_get_thread_cpu_time 。使用 AddCapabilities
JVMTI_ERROR_NULL_POINTER info_ptr NULL

获取线程 CPU 时间

jvmtiError
GetThreadCpuTime(jvmtiEnv* env,
      jthread thread,
      jlong* nanos_ptr)
返回指定线程使用的 CPU 时间。
使用 GetThreadCpuTimerInfo 获取有关此计时器的信息。
只能在直播阶段调用
137
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_get_thread_cpu_time 可以获得线程CPU时间。
如果在线程启动后启用此功能,则实现可以选择任何时间(包括启用该功能的时间)作为 CPU 时间收集的开始点。
参数
Name Type Description
thread jthread 要查询的线程。 thread 可能不是虚拟线程。否则,将返回错误代码JVMTI_ERROR_UNSUPPORTED_OPERATION 。如果 threadNULL ,则使用当前线程。
nanos_ptr jlong* 返回时,指向指定线程使用的 CPU 时间(以纳秒为单位)。这是一个无符号值。如果作为 jlong(有符号值)进行测试或打印,它可能看起来是一个负数。
Agent 传递一个指向 jlong 的指针。返回时,jlong 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备能力 can_get_thread_cpu_time 。使用 AddCapabilities
JVMTI_ERROR_UNSUPPORTED_OPERATION thread 是一个虚拟线程。
JVMTI_ERROR_INVALID_THREAD thread 不是线程对象。
JVMTI_ERROR_THREAD_NOT_ALIVE thread 不存在(尚未启动或已终止)。
JVMTI_ERROR_NULL_POINTER nanos_ptr NULL

获取定时器信息

jvmtiError
GetTimerInfo(jvmtiEnv* env,
      jvmtiTimerInfo* info_ptr)
获取有关 GetTime 计时器的信息。 jvmtiTimerInfo 结构的字段填充了有关计时器的详细信息。在 VM 的特定调用期间,此信息不会更改。
可以在任何阶段调用
此函数可以从回调到 迭代函数,或从 GarbageCollectionStart GarbageCollectionFinish ObjectFree 事件的事件处理程序调用。
138
1.0
能力
所需功能
参数
Name Type Description
info_ptr jvmtiTimerInfo* 返回时,填充了描述 GetTime 返回时间的信息。
Agent 传递一个指向 jvmtiTimerInfo 的指针。返回时,jvmtiTimerInfo 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER info_ptr NULL

获取时间

jvmtiError
GetTime(jvmtiEnv* env,
      jlong* nanos_ptr)
返回系统计时器的当前值,以纳秒为单位。
返回的值表示自某个固定但任意时间以来的纳秒数(可能在未来,因此值可能为负)。此函数提供纳秒级精度,但不一定是纳秒级精度。不保证值更改的频率。
使用 GetTimerInfo 获取有关此计时器的信息。
可以在任何阶段调用
此函数可以从回调到 迭代函数,或从 GarbageCollectionStart GarbageCollectionFinish ObjectFree 事件的事件处理程序调用。
139
1.0
能力
所需功能
参数
Name Type Description
nanos_ptr jlong* 返回时,指向以纳秒为单位的时间。这是一个无符号值。如果作为 jlong(有符号值)进行测试或打印,它可能看起来是一个负数。
Agent 传递一个指向 jlong 的指针。返回时,jlong 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER nanos_ptr NULL

获取可用的处理器

jvmtiError
GetAvailableProcessors(jvmtiEnv* env,
      jint* processor_count_ptr)
返回 Java 虚拟机可用的处理器数量。
该值可能会在虚拟机的特定调用期间发生变化。因此,对可用处理器数量敏感的应用程序应偶尔轮询此属性。
可以在任何阶段调用
144
1.0
能力
所需功能
参数
Name Type Description
processor_count_ptr jint* 返回时,指向虚拟机可用的最大处理器数;永远不会小于一个。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER processor_count_ptr NULL


类加载器搜索

类加载器搜索功能: 这些函数允许代理添加到类加载器搜索类的位置。这对于在正确的类加载器下安装工具很有用。

添加到 Bootstrap 类加载器搜索

jvmtiError
AddToBootstrapClassLoaderSearch(jvmtiEnv* env,
      const char* segment)
此函数可用于使检测类由引导类加载器定义。看Java™ 虚拟机规范,第 5.3.1 章.引导类加载器搜索类失败后,也会搜索指定的平台相关搜索路径segment segment 中只能指定一个段。可以多次调用此函数来添加多个段,将按照调用此函数的顺序搜索段。
OnLoad 阶段,该函数可用于指定在引导类加载器搜索类失败后要搜索的任何依赖于平台的搜索路径段。该段通常是一个目录或 JAR 文件。
在实时阶段,segment 可用于指定任何依赖于平台的路径到 文件。代理应该注意 JAR 文件不包含任何类或资源,除了那些由引导类加载器为检测目的定义的类或资源。
Java™ 虚拟机规范指定后续尝试解析 Java 虚拟机先前未成功尝试解析的符号引用总是失败,并抛出与初始解析尝试相同的错误。因此,如果 JAR 文件包含对应于 Java 虚拟机未能成功解析引用的类的条目,则后续解析该引用的尝试将失败,并出现与初始尝试相同的错误。
只能在 OnLoad 或 live 阶段调用
149
1.0
能力
所需功能
参数
Name Type Description
segment const char* 平台相关的搜索路径段,编码为 修改后的 UTF-8 字符串。
代理传入一个 char 数组。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_ILLEGAL_ARGUMENT segment 是无效路径。在活动阶段,除现有 JAR 文件之外的任何内容都是无效路径。
JVMTI_ERROR_NULL_POINTER segment NULL

添加到系统类加载器搜索

jvmtiError
AddToSystemClassLoaderSearch(jvmtiEnv* env,
      const char* segment)
此函数可用于使检测类由系统类加载器定义。看Java™ 虚拟机规范,第 5.3.2 章.类加载器搜索类失败后,也会搜索指定的平台相关搜索路径segment segment 中只能指定一个段。可以多次调用此函数来添加多个段,将按照调用此函数的顺序搜索段。
OnLoad 阶段,该函数可用于指定在系统类加载器搜索类失败后要搜索的任何依赖于平台的搜索路径段。该段通常是一个目录或 JAR 文件。
在实时阶段,segment 是一个依赖于平台的路径,指向 文件,在系统类加载器搜索类失败后将被搜索。代理应该注意 JAR 文件不包含任何类或资源,除了那些由系统类加载器为检测目的定义的类或资源。
在实时阶段,如果系统类加载器实现了一个方法名称 appendToClassPathForInstrumentation,它接受一个类型为 java.lang.String 的参数,则系统类加载器支持添加要搜索的 JAR 文件。该方法不需要具有 public 访问权限。
Java™ 虚拟机规范指定后续尝试解析 Java 虚拟机先前未成功尝试解析的符号引用总是失败,并抛出与初始解析尝试相同的错误。因此,如果 JAR 文件包含对应于 Java 虚拟机未能成功解析引用的类的条目,则后续解析该引用的尝试将失败,并出现与初始尝试相同的错误。
只能在 OnLoad 或 live 阶段调用
151
1.1
能力
所需功能
参数
Name Type Description
segment const char* 平台相关的搜索路径段,编码为 修改后的 UTF-8 字符串。
代理传入一个 char 数组。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_ILLEGAL_ARGUMENT segment 是无效路径。在活动阶段,除现有 JAR 文件之外的任何内容都是无效路径。
JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED 系统类加载器不支持的操作。
JVMTI_ERROR_NULL_POINTER segment NULL


系统属性

系统属性函数: 这些函数获取和设置系统属性。

获取系统属性

jvmtiError
GetSystemProperties(jvmtiEnv* env,
      jint* count_ptr,
      char*** property_ptr)
返回可与 GetSystemProperty 一起使用的 VM 系统属性键列表。强烈建议虚拟机提供以下属性键: 提供对 VM 定义和使用的系统属性的访问。包括在命令行上设置的属性。这允许在 VM 甚至开始执行字节码之前获取和设置这些属性。由于这是系统属性的 VM 视图,可用属性集通常与 java.lang.System.getProperties 中的不同。 JNI 方法调用可用于访问 java.lang.System.getProperties
属性集可能会在执行期间增长。
只能在 OnLoad 或 live 阶段调用
130
1.0
能力
所需功能
参数
Name Type Description
count_ptr jint* 返回时,指向返回的属性键的数量。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
property_ptr char*** 返回时,指向属性键数组,编码为 修改后的 UTF-8 字符串。
Agent 传递一个指向 char** 的指针。返回时,char** 指向新分配的大小为 *count_ptr 的数组,其中的每个元素也是新分配的。该数组应使用 Deallocate 释放。每个元素都应该用 Deallocate 释放。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER count_ptr NULL
JVMTI_ERROR_NULL_POINTER property_ptr NULL

获取系统属性

jvmtiError
GetSystemProperty(jvmtiEnv* env,
      const char* property,
      char** value_ptr)
返回给定属性键的 VM 系统属性值。
函数 GetSystemProperties 返回可以使用的属性键集。可以检索的属性可能会在执行期间增长。
由于这是系统属性的 VM 视图,因此属性值可能与 java.lang.System.getProperty(String) 返回的值不同。典型的 VM 可能会在该类的初始化期间将 VM 系统属性的值复制到 java.lang.System 持有的 Properties 中。此后,对 VM 系统属性(使用 SetSystemProperty )或 java.lang.System 系统属性(使用 java.lang.System.setProperty(String,String) )的任何更改都将导致值出现差异。 JNI 方法调用可用于访问 java.lang.System.getProperty(String)
只能在 OnLoad 或 live 阶段调用
131
1.0
能力
所需功能
参数
Name Type Description
property const char* 要检索的属性的键,编码为 修改后的 UTF-8 字符串。
代理传入一个 char 数组。
value_ptr char** 返回时,指向属性值,编码为 修改后的 UTF-8 字符串。
Agent 传递一个指向 char* 的指针。返回时,char* 指向一个新分配的数组。该数组应使用 Deallocate 释放。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NOT_AVAILABLE 此属性不可用。使用 GetSystemProperties 查找可用属性。
JVMTI_ERROR_NULL_POINTER property NULL
JVMTI_ERROR_NULL_POINTER value_ptr NULL

设置系统属性

jvmtiError
SetSystemProperty(jvmtiEnv* env,
      const char* property,
      const char* value_ptr)
设置 VM 系统属性值。
GetSystemProperties 函数返回一组属性键,其中一些可能是可设置的。参见 GetSystemProperty
只能在 OnLoad 阶段调用
132
1.0
能力
所需功能
参数
Name Type Description
property const char* 属性的键,编码为 修改后的 UTF-8 字符串。
代理传入一个 char 数组。
value_ptr const char * 要设置的属性值,编码为 修改后的 UTF-8 字符串。
代理传入一个 char 数组。如果 value_ptrNULL ,则不设置该值,但如果属性不可写则返回 JVMTI_ERROR_NOT_AVAILABLE
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NOT_AVAILABLE 此属性不可用或不可写。
JVMTI_ERROR_NULL_POINTER property NULL


一般的

一般功能: 一般类型: 通用标志和常量:

获取阶段

typedef enum {
  JVMTI_PHASE_ONLOAD = 1,
  JVMTI_PHASE_PRIMORDIAL = 2,
  JVMTI_PHASE_START = 6,
  JVMTI_PHASE_LIVE = 4,
  JVMTI_PHASE_DEAD = 8
} jvmtiPhase;
jvmtiError
GetPhase(jvmtiEnv* env,
      jvmtiPhase* phase_ptr)
返回 VM 执行的当前阶段。这些阶段按顺序进行:
执行阶段 (jvmtiPhase)
持续的 Value Description
JVMTI_PHASE_ONLOAD 1 OnLoad 阶段:在 Agent_OnLoad 中,或者对于静态链接代理,在 Agent_OnLoad_<agent-lib-name> 函数中。
JVMTI_PHASE_PRIMORDIAL 2 原始阶段:从 Agent_OnLoadAgent_OnLoad_<agent-lib-name> 返回和 VMStart 事件之间。
JVMTI_PHASE_START 6 开始阶段:发送VMStart 事件时,直到发送VMInit事件。
JVMTI_PHASE_LIVE 4 实时阶段:发送VMInit 事件时,直到VMDeath 事件返回。
JVMTI_PHASE_DEAD 8 停滞阶段:VMDeath 事件返回后或启动失败后。
在启动失败的情况下,VM 将跳过中间阶段直接进入死阶段,并且不会发送 VMInitVMDeath 事件。
大多数 JVM TI 功能仅在实时阶段运行。以下函数在 OnLoad 或 live 阶段运行: 以下功能仅在OnLoad阶段运行: 以下功能在启动或实时阶段运行: 以下功能在任何阶段运行: JNI 函数(Invocation API 除外)只能在启动或运行阶段使用。
大多数 JVM TI 事件仅在实时阶段发送。以下事件在其他阶段运行:
可以在任何阶段调用
133
1.0
能力
所需功能
参数
Name Type Description
phase_ptr jvmtiPhase* 返回时,指向相位。
Agent 传递一个指向 jvmtiPhase 的指针。返回时,jvmtiPhase 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER phase_ptr NULL

处理环境

jvmtiError
DisposeEnvironment(jvmtiEnv* env)
关闭 JVM 使用 JNI GetEnv 创建的 TI 连接(参见 JVM TI Environments )。处理环境持有的任何资源。此调用不会恢复被此环境挂起的线程,这必须由代理显式完成。此环境通过调用 JVM 分配的内存 TI 功能未发布,这可以由代理通过调用 Deallocate 明确完成。此环境创建的原始监视器不会被销毁,这可以由代理通过调用 DestroyRawMonitor 显式完成。在此环境创建的原始监视器上等待的线程状态不受影响。
此环境的任何 本机方法前缀 都将被取消设置;在调用 dispose 之前,代理必须删除任何带前缀的本机方法。
此环境持有的任何 capabilities 都将被放弃。
此环境启用的事件将不再发送,但当前正在运行的事件处理程序将继续运行。在设计事件处理程序时必须小心谨慎,事件处理程序的环境可能会被释放,从而在执行期间变得无效。
此调用后可能无法使用此环境。此调用返回给调用者。
可以在任何阶段调用
127
1.0
能力
所需功能
参数
没有任何
错误
这个函数返回一个 普遍错误

设置环境本地存储

jvmtiError
SetEnvironmentLocalStorage(jvmtiEnv* env,
      const void* data)
VM 存储与每个环境关联的指针值。这个指针值被称为环境本地存储.这个值是NULL除非用这个函数设置。代理可以分配存储环境特定信息的内存。通过设置环境本地存储,然后可以使用 GetEnvironmentLocalStorage 访问它。
由代理调用以设置 JVM 的值 TI环境-本地存储。虚拟机 TI 向代理提供指针大小的环境本地存储,可用于记录每个环境的信息。
可以在任何阶段调用
此函数可以从回调到 迭代函数,或从 GarbageCollectionStart GarbageCollectionFinish ObjectFree 事件的事件处理程序调用。
148
1.0
能力
所需功能
参数
Name Type Description
data const void * 要输入环境本地存储的值。
Agent 传入一个指针。如果 dataNULL,则值设置为 NULL
错误
这个函数返回一个 普遍错误

获取环境本地存储

jvmtiError
GetEnvironmentLocalStorage(jvmtiEnv* env,
      void** data_ptr)
被agent调用获取JVM的值 TI环境-本地存储。
可以在任何阶段调用
此函数可以从回调到 迭代函数,或从 GarbageCollectionStart GarbageCollectionFinish ObjectFree 事件的事件处理程序调用。
147
1.0
能力
所需功能
参数
Name Type Description
data_ptr void** 返回环境本地存储值的指针。如果尚未使用 SetEnvironmentLocalStorage 设置环境本地存储,则返回的指针为 NULL
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER data_ptr NULL

获取版本号

jvmtiError
GetVersionNumber(jvmtiEnv* env,
      jint* version_ptr)
返回 JVM TI 版本来自 version_ptr。返回值是版本标识符。版本标识符包括主要版本、次要版本和微版本以及接口类型。
版本接口类型
持续的 Value Description
JVMTI_VERSION_INTERFACE_JNI 0x00000000 JNI 的 JVMTI_VERSION_MASK_INTERFACE_TYPE 值。
JVMTI_VERSION_INTERFACE_JVMTI 0x30000000 JVM 的 JVMTI_VERSION_MASK_INTERFACE_TYPE TI.
版本掩码
持续的 Value Description
JVMTI_VERSION_MASK_INTERFACE_TYPE 0x70000000 用于提取接口类型的掩码。由JVMTI_VERSION_MASK_INTERFACE_TYPE 屏蔽的此函数返回的版本值始终为JVMTI_VERSION_INTERFACE_JVMTI,因为这是一个 JVM TI 功能。
JVMTI_VERSION_MASK_MAJOR 0x0FFF0000 用于提取主版本号的掩码。
JVMTI_VERSION_MASK_MINOR 0x0000FF00 用于提取次要版本号的掩码。
JVMTI_VERSION_MASK_MICRO 0x000000FF 用于提取微版本号的掩码。
版本转换
持续的 Value Description
JVMTI_VERSION_SHIFT_MAJOR 16 Shift 以提取主要版本号。
JVMTI_VERSION_SHIFT_MINOR 8 Shift 以提取次要版本号。
JVMTI_VERSION_SHIFT_MICRO 0 Shift 提取微版本号。
可以在任何阶段调用
88
1.0
能力
所需功能
参数
Name Type Description
version_ptr jint* 返回时,指向 JVM TI 版本。
Agent 传递一个指向 jint 的指针。返回时,jint 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER version_ptr NULL

获取错误名称

jvmtiError
GetErrorName(jvmtiEnv* env,
      jvmtiError error,
      char** name_ptr)
返回 错误代码 的符号名称。
例如,GetErrorName(env, JVMTI_ERROR_NONE, &err_name) 将在 err_name 中返回字符串 "JVMTI_ERROR_NONE"
可以在任何阶段调用
128
1.0
能力
所需功能
参数
Name Type Description
error jvmtiError 错误代码。
name_ptr char** 返回时,指向错误名称。该名称被编码为 修改后的 UTF-8 字符串,但仅限于 ASCII 子集。
Agent 传递一个指向 char* 的指针。返回时,char* 指向一个新分配的数组。该数组应使用 Deallocate 释放。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_ILLEGAL_ARGUMENT error 不是 jvmtiError。
JVMTI_ERROR_NULL_POINTER name_ptr NULL

设置详细标志

typedef enum {
  JVMTI_VERBOSE_OTHER = 0,
  JVMTI_VERBOSE_GC = 1,
  JVMTI_VERBOSE_CLASS = 2,
  JVMTI_VERBOSE_JNI = 4
} jvmtiVerboseFlag;
jvmtiError
SetVerboseFlag(jvmtiEnv* env,
      jvmtiVerboseFlag flag,
      jboolean value)
详细标志枚举 (jvmtiVerboseFlag)
持续的 Value Description
JVMTI_VERBOSE_OTHER 0 除以下内容外的详细输出。
JVMTI_VERBOSE_GC 1 详细的垃圾收集器输出,就像用 -verbose:gc 指定的那样。
JVMTI_VERBOSE_CLASS 2 详细的类加载输出,就像用 -verbose:class 指定的那样。
JVMTI_VERBOSE_JNI 4 详细的 JNI 输出,就像用 -verbose:jni 指定的那样。
控制详细输出。这是通常发送到 stderr 的输出。
可以在任何阶段调用
150
1.0
能力
所需功能
参数
Name Type Description
flag jvmtiVerboseFlag 要设置哪个详细标志。
value jboolean 标志的新值。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_ILLEGAL_ARGUMENT flag 不是 jvmtiVerboseFlag。

获取 JLocation 格式

typedef enum {
  JVMTI_JLOCATION_JVMBCI = 1,
  JVMTI_JLOCATION_MACHINEPC = 2,
  JVMTI_JLOCATION_OTHER = 0
} jvmtiJlocationFormat;
jvmtiError
GetJLocationFormat(jvmtiEnv* env,
      jvmtiJlocationFormat* format_ptr)
尽管最大的功能是通过引用虚拟机字节码索引的位置信息实现的,但 jlocation 的定义有意不受约束,以允许没有此信息的 VM 实现。
此函数描述了此 VM 中使用的 jlocation 的表示。如果返回的格式为 JVMTI_JLOCATION_JVMBCI ,则 jlocation 可以用作 GetBytecodes 返回的数组的索引。
JLocation 格式枚举 (jvmtiJlocationFormat)
持续的 Value Description
JVMTI_JLOCATION_JVMBCI 1 jlocation 值表示虚拟机字节码索引——即方法的虚拟机代码中的偏移量。
JVMTI_JLOCATION_MACHINEPC 2 jlocation 值表示本机机器程序计数器值。
JVMTI_JLOCATION_OTHER 0 jlocation 值有一些其他的表示。
可以在任何阶段调用
129
1.0
能力
所需功能
参数
Name Type Description
format_ptr jvmtiJlocationFormat* 返回时,指向 jlocation 值的格式标识符。
Agent 传递一个指向 jvmtiJlocationFormat 的指针。返回时,jvmtiJlocationFormat 已设置。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_NULL_POINTER format_ptr NULL


堆监控

堆监控功能:

设置堆采样间隔

jvmtiError
SetHeapSamplingInterval(jvmtiEnv* env,
      jint sampling_interval)
分配对象时生成 SampledObjectAlloc 事件。每个线程都保留一个已分配字节数的计数器。仅当该计数器自上次采样以来超过 sampling_interval 的平均值时才会生成该事件。
sampling_interval 设置为 0 将导致在考虑新间隔后,系统支持的每个分配都会生成一个事件。
请注意,更新新的采样间隔可能需要不同数量的分配来激发内部数据结构更新。因此,将采样间隔视为平均值很重要。这包括间隔 0,其中可能不会为每个分配立即生成事件。
只能在 OnLoad 或 live 阶段调用
156
11
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此功能。
能力 影响
can_generate_sampled_object_alloc_events 可以生成采样分配事件。如果启用此功能,则可以调用堆采样方法 SetHeapSamplingInterval 并生成 SampledObjectAlloc 事件。
参数
Name Type Description
sampling_interval jint 以字节为单位的采样间隔。采样器使用统计方法生成一个事件,平均而言,给定线程每分配 sampling_interval 字节内存一次。
一旦考虑了新的采样间隔,0 作为采样间隔将为每个分配生成一个样本。
注意:此功能的开销与采样间隔直接相关。较高的采样间隔(例如 1024 字节)会产生较高的开销。较小的间隔(例如 1024KB)的开销会低得多。采样仅应在了解它可能会影响性能的情况下使用。
错误
此函数返回 普遍错误 或以下错误之一
Error Description
JVMTI_ERROR_MUST_POSSESS_CAPABILITY 环境不具备 can_generate_sampled_object_alloc_events 能力。使用 AddCapabilities
JVMTI_ERROR_ILLEGAL_ARGUMENT sampling_interval 小于零。


错误

每个 JVM TI 函数返回一个jvmtiError 错误代码。
agent负责调用JVM TI 函数具有有效参数并在适当的上下文中(附加调用线程、相位正确等)。检测某些错误条件对于实现来说可能是困难的、低效的或不可能的。 功能特定的必要错误 中列出的错误必须由实现检测到。所有其他错误表示对错误情况的建议响应。

普遍错误

任何函数都可能返回以下错误
JVMTI_ERROR_NONE (0)
没有发生错误。这是函数成功完成时返回的错误代码。
JVMTI_ERROR_NULL_POINTER (100)
指针意外地是 NULL
JVMTI_ERROR_OUT_OF_MEMORY (110)
该函数试图分配内存,但没有更多内存可用于分配。
JVMTI_ERROR_ACCESS_DENIED (111)
此虚拟机中尚未启用所需的功能。
JVMTI_ERROR_UNATTACHED_THREAD (115)
用于调用此函数的线程未附加到虚拟机。必须从附加线程进行调用。请参阅 JNI 调用 API 中的 AttachCurrentThread
JVMTI_ERROR_INVALID_ENVIRONMENT (116)
虚拟机 提供的 TI 环境不再连接或不是环境。
JVMTI_ERROR_WRONG_PHASE (112)
所需的功能在当前的 阶段 中不可用。如果虚拟机已完成运行,则始终返回。
JVMTI_ERROR_INTERNAL (113)
发生意外的内部错误。

功能特定的必要错误

某些 JVM 返回以下错误 TI 函数并且必须在条件发生时由实现返回。
JVMTI_ERROR_INVALID_PRIORITY (12)
优先级无效。
JVMTI_ERROR_THREAD_NOT_SUSPENDED (13)
线程未暂停。
JVMTI_ERROR_THREAD_SUSPENDED (14)
线程已暂停。
JVMTI_ERROR_THREAD_NOT_ALIVE (15)
此操作要求线程处于活动状态——也就是说,它必须已启动且尚未终止。
JVMTI_ERROR_CLASS_NOT_PREPARED (22)
该类已加载但尚未准备好。
JVMTI_ERROR_NO_MORE_FRAMES (31)
在指定深度没有 Java 编程语言或 JNI 堆栈帧。
JVMTI_ERROR_OPAQUE_FRAME (32)
有关框架的信息不可用(例如,对于本机框架)。
JVMTI_ERROR_DUPLICATE (40)
项目已经设置。
JVMTI_ERROR_NOT_FOUND (41)
未找到所需的元素(例如字段或断点)
JVMTI_ERROR_NOT_MONITOR_OWNER (51)
该线程不拥有原始监视器。
JVMTI_ERROR_INTERRUPT (52)
呼叫在完成之前被中断。
JVMTI_ERROR_UNMODIFIABLE_CLASS (79)
类不能修改。
JVMTI_ERROR_UNMODIFIABLE_MODULE (80)
无法修改模块。
JVMTI_ERROR_NOT_AVAILABLE (98)
该功能在此虚拟机中不可用。
JVMTI_ERROR_ABSENT_INFORMATION (101)
请求的信息不可用。
JVMTI_ERROR_INVALID_EVENT_TYPE (102)
无法识别指定的事件类型 ID。
JVMTI_ERROR_NATIVE_METHOD (104)
请求的信息不适用于本机方法。
JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED (106)
类加载器不支持此操作。

功能特定代理错误

某些 JVM 返回以下错误 德州仪器功能。如果代理传递的参数无效或在无效上下文中使用,则返回它们。不需要实现来检测这些错误。
JVMTI_ERROR_INVALID_THREAD (10)
传递的线程不是有效线程。
JVMTI_ERROR_INVALID_FIELDID (25)
无效字段。
JVMTI_ERROR_INVALID_MODULE (26)
模块无效。
JVMTI_ERROR_INVALID_METHODID (23)
无效的方法。
JVMTI_ERROR_INVALID_LOCATION (24)
位置无效。
JVMTI_ERROR_INVALID_OBJECT (20)
无效的对象。
JVMTI_ERROR_INVALID_CLASS (21)
类无效。
JVMTI_ERROR_TYPE_MISMATCH (34)
该变量不是所用函数的合适类型。
JVMTI_ERROR_INVALID_SLOT (35)
插槽无效。
JVMTI_ERROR_MUST_POSSESS_CAPABILITY (99)
在此环境中使用的功能是错误的。
JVMTI_ERROR_INVALID_THREAD_GROUP (11)
线程组无效。
JVMTI_ERROR_INVALID_MONITOR (50)
原始监视器无效。
JVMTI_ERROR_ILLEGAL_ARGUMENT (103)
非法参数。
JVMTI_ERROR_INVALID_TYPESTATE (65)
线程的状态已被修改,现在不一致。
JVMTI_ERROR_UNSUPPORTED_VERSION (68)
此 VM 不支持新类文件的版本号。
JVMTI_ERROR_INVALID_CLASS_FORMAT (60)
新类文件格式错误(VM 将返回 ClassFormatError )。
JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION (61)
新的类文件定义将导致循环定义(VM 将返回 ClassCircularityError )。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED (63)
一个新的类文件需要添加一个方法。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED (64)
新的类版本更改了一个字段。
JVMTI_ERROR_FAILS_VERIFICATION (62)
类字节验证失败。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED (66)
新类版本的直接超类不同,或者直接实现的接口集不同。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED (67)
新类版本不声明在旧类版本中声明的方法。
JVMTI_ERROR_NAMES_DONT_MATCH (69)
新类文件中定义的类名与旧类对象中的名称不同。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED (70)
新的类版本具有不同的修饰符。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED (71)
新类版本中的方法与旧类版本中的对应方法具有不同的修饰符。
JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED (72)
新类版本在类属性方面存在不受支持的差异。
JVMTI_ERROR_UNSUPPORTED_OPERATION (73)
此实现不支持功能。


数据类型

JVM TI 扩展了 JNI 定义的数据类型。

JVM 工具接口中使用的 JNI 类型
Type Description
jboolean
拥有 Java 编程语言 boolean。无符号 8 位。
jchar
拥有 Java 编程语言 char。无符号 16 位。
jint
拥有 Java 编程语言 int。带符号的 32 位。
jlong
拥有 Java 编程语言 long。带符号的 64 位。
jfloat
拥有 Java 编程语言 float。 32 位。
jdouble
拥有 Java 编程语言 double。 64 位。
jobject
持有 Java 编程语言对象。
jclass
拥有 Java 编程语言类。
jvalue
是所有原始类型和 jobject 的联合。因此,拥有任何 Java 编程语言的值。
jfieldID
标识 Java 编程语言字段。 jfieldID 由 JVM 返回 可以安全地存储 TI 函数和事件。
jmethodID
标识 Java 编程语言方法、初始值设定项或构造函数。 jmethodID 由 JVM 返回 可以安全地存储 TI 函数和事件。但是,如果类被卸载,它们将变得无效并且不得使用。
JNIEnv
指向 JNI 函数表的指针。指向此 (JNIEnv *) 的指针是一个 JNI 环境。

JVM 工具接口基类型
Type Description
jvmtiEnv
JVM TI environment指针。请参阅 Function 章节jvmtiEnv 指向 功能表 指针。
jthread
拥有线程的 jobject 子类型。
typedef jobject jthread;
jthreadGroup
jobject 的子类型,它包含一个线程组。
typedef jobject jthreadGroup;
jlocation
一个 64 位值,表示方法中单调递增的可执行位置。 -1 表示本地方法。有关给定 VM 上的格式,请参阅 GetJLocationFormat
typedef jlong jlocation;
jrawMonitorID
原始监视器。
struct _jrawMonitorID;
typedef struct _jrawMonitorID *jrawMonitorID;
jvmtiError
保存错误返回码。有关可能的值,请参阅 错误部分
typedef enum {
  JVMTI_ERROR_NONE = 0,
  JVMTI_ERROR_INVALID_THREAD = 10,
   ...
} jvmtiError;
jvmtiEvent
事件类型的标识符。有关可能的值,请参阅 Event 章节。保证本规范的未来版本永远不会指定零作为事件类型标识符。
typedef enum {
  JVMTI_EVENT_SINGLE_STEP = 1,
  JVMTI_EVENT_BREAKPOINT = 2,
   ...
} jvmtiEvent;
jvmtiEventCallbacks
用于事件的回调。
typedef struct {
  jvmtiEventVMInit VMInit;
  jvmtiEventVMDeath VMDeath;
   ...
} jvmtiEventCallbacks;
有关完整结构,请参阅 事件回调
例如,定义了 VM 初始化回调:
typedef void (JNICALL *jvmtiEventVMInit)
  (jvmtiEnv *jvmti_env,
   JNIEnv* jni_env,
   jthread thread);
请参阅各个事件以了解回调函数定义。
jniNativeInterface
typedef 为 JNI 函数表 JNINativeInterface 中定义的 JNI规范 。 JNI 参考实现用下划线定义它。
typedef struct JNINativeInterface_ jniNativeInterface;
结构类型定义
Type Description
jvmtiAddrLocationMap 位置条目的本机地址
jvmtiCapabilities 能力结构
jvmtiClassDefinition 类重定义说明
jvmtiExtensionEventInfo 扩展事件信息
jvmtiExtensionFunctionInfo 扩展功能信息
jvmtiFrameInfo 栈帧信息结构
jvmtiHeapCallbacks 堆回调函数结构
jvmtiHeapReferenceInfo 参考信息结构
jvmtiHeapReferenceInfoArray 数组引用的引用信息结构
jvmtiHeapReferenceInfoConstantPool 常量池引用的引用信息结构
jvmtiHeapReferenceInfoField 字段引用的引用信息结构
jvmtiHeapReferenceInfoJniLocal JNI 本地引用的引用信息结构
jvmtiHeapReferenceInfoReserved 其他参考的参考信息结构
jvmtiHeapReferenceInfoStackLocal 局部变量引用的引用信息结构
jvmtiLineNumberEntry 行号表条目
jvmtiLocalVariableEntry 局部变量表项
jvmtiMonitorStackDepthInfo 监听栈深度信息结构
jvmtiMonitorUsage 对象监视器使用信息
jvmtiParamInfo 扩展函数/事件参数信息
jvmtiStackInfo 堆栈信息结构
jvmtiThreadGroupInfo 线程组信息结构
jvmtiThreadInfo 线程信息结构
jvmtiTimerInfo 定时器信息
函数类型定义
Type Description
jvmtiArrayPrimitiveValueCallback 数组原始值回调
jvmtiExtensionEvent 扩展事件
jvmtiExtensionFunction 扩展功能
jvmtiHeapIterationCallback 堆迭代回调
jvmtiHeapObjectCallback 堆对象回调
jvmtiHeapReferenceCallback 堆引用回调
jvmtiHeapRootCallback 堆根对象回调
jvmtiObjectReferenceCallback 对象引用回调
jvmtiPrimitiveFieldCallback 原始字段回调
jvmtiReservedCallback 保留供将来使用回调
jvmtiStackReferenceCallback 堆栈引用对象回调
jvmtiStartFunction 代理启动函数
jvmtiStringPrimitiveValueCallback 字符串原始值回调
枚举定义
Type Description
jvmtiEventMode 事件启用/禁用
jvmtiHeapObjectFilter 堆对象过滤器枚举
jvmtiHeapReferenceKind 堆引用枚举
jvmtiHeapRootKind 堆根种类枚举
jvmtiIterationControl 迭代控制枚举
jvmtiJlocationFormat JLocation 格式枚举
jvmtiObjectReferenceKind 对象引用枚举
jvmtiParamKind 扩展函数/事件参数种类
jvmtiParamTypes 扩展函数/事件参数类型
jvmtiPhase 执行阶段
jvmtiPrimitiveType 原始类型枚举
jvmtiTimerKind 定时器种类
jvmtiVerboseFlag 详细标志枚举
功能表布局
Position Function 宣言
1 预订的
void *reserved1;
2 设置事件通知模式
jvmtiError (JNICALL *SetEventNotificationMode) (jvmtiEnv* env,
            jvmtiEventMode mode,
            jvmtiEvent event_type,
            jthread event_thread,
            ...);
3 获取所有模块
jvmtiError (JNICALL *GetAllModules) (jvmtiEnv* env,
            jint* module_count_ptr,
            jobject** modules_ptr);
4 获取所有线程
jvmtiError (JNICALL *GetAllThreads) (jvmtiEnv* env,
            jint* threads_count_ptr,
            jthread** threads_ptr);
5 挂起线程
jvmtiError (JNICALL *SuspendThread) (jvmtiEnv* env,
            jthread thread);
6 恢复线程
jvmtiError (JNICALL *ResumeThread) (jvmtiEnv* env,
            jthread thread);
7 停止线程
jvmtiError (JNICALL *StopThread) (jvmtiEnv* env,
            jthread thread,
            jobject exception);
8 中断线程
jvmtiError (JNICALL *InterruptThread) (jvmtiEnv* env,
            jthread thread);
9 获取线程信息
jvmtiError (JNICALL *GetThreadInfo) (jvmtiEnv* env,
            jthread thread,
            jvmtiThreadInfo* info_ptr);
10 获取拥有的显示器信息
jvmtiError (JNICALL *GetOwnedMonitorInfo) (jvmtiEnv* env,
            jthread thread,
            jint* owned_monitor_count_ptr,
            jobject** owned_monitors_ptr);
11 获取当前竞争监视器
jvmtiError (JNICALL *GetCurrentContendedMonitor) (jvmtiEnv* env,
            jthread thread,
            jobject* monitor_ptr);
12 运行代理线程
jvmtiError (JNICALL *RunAgentThread) (jvmtiEnv* env,
            jthread thread,
            jvmtiStartFunction proc,
            const void* arg,
            jint priority);
13 获取顶级线程组
jvmtiError (JNICALL *GetTopThreadGroups) (jvmtiEnv* env,
            jint* group_count_ptr,
            jthreadGroup** groups_ptr);
14 获取线程组信息
jvmtiError (JNICALL *GetThreadGroupInfo) (jvmtiEnv* env,
            jthreadGroup group,
            jvmtiThreadGroupInfo* info_ptr);
15 获取线程组子项
jvmtiError (JNICALL *GetThreadGroupChildren) (jvmtiEnv* env,
            jthreadGroup group,
            jint* thread_count_ptr,
            jthread** threads_ptr,
            jint* group_count_ptr,
            jthreadGroup** groups_ptr);
16 获取帧数
jvmtiError (JNICALL *GetFrameCount) (jvmtiEnv* env,
            jthread thread,
            jint* count_ptr);
17 获取线程状态
jvmtiError (JNICALL *GetThreadState) (jvmtiEnv* env,
            jthread thread,
            jint* thread_state_ptr);
18 获取当前线程
jvmtiError (JNICALL *GetCurrentThread) (jvmtiEnv* env,
            jthread* thread_ptr);
19 获取帧位置
jvmtiError (JNICALL *GetFrameLocation) (jvmtiEnv* env,
            jthread thread,
            jint depth,
            jmethodID* method_ptr,
            jlocation* location_ptr);
20 通知帧弹出
jvmtiError (JNICALL *NotifyFramePop) (jvmtiEnv* env,
            jthread thread,
            jint depth);
21 获取局部变量 - 对象
jvmtiError (JNICALL *GetLocalObject) (jvmtiEnv* env,
            jthread thread,
            jint depth,
            jint slot,
            jobject* value_ptr);
22 获取局部变量 - Int
jvmtiError (JNICALL *GetLocalInt) (jvmtiEnv* env,
            jthread thread,
            jint depth,
            jint slot,
            jint* value_ptr);
23 获取局部变量 - 长
jvmtiError (JNICALL *GetLocalLong) (jvmtiEnv* env,
            jthread thread,
            jint depth,
            jint slot,
            jlong* value_ptr);
24 获取局部变量 - Float
jvmtiError (JNICALL *GetLocalFloat) (jvmtiEnv* env,
            jthread thread,
            jint depth,
            jint slot,
            jfloat* value_ptr);
25 获取局部变量 - 双精度
jvmtiError (JNICALL *GetLocalDouble) (jvmtiEnv* env,
            jthread thread,
            jint depth,
            jint slot,
            jdouble* value_ptr);
26 设置局部变量 - 对象
jvmtiError (JNICALL *SetLocalObject) (jvmtiEnv* env,
            jthread thread,
            jint depth,
            jint slot,
            jobject value);
27 设置局部变量 - Int
jvmtiError (JNICALL *SetLocalInt) (jvmtiEnv* env,
            jthread thread,
            jint depth,
            jint slot,
            jint value);
28 设置局部变量 - 长
jvmtiError (JNICALL *SetLocalLong) (jvmtiEnv* env,
            jthread thread,
            jint depth,
            jint slot,
            jlong value);
29 设置局部变量 - Float
jvmtiError (JNICALL *SetLocalFloat) (jvmtiEnv* env,
            jthread thread,
            jint depth,
            jint slot,
            jfloat value);
30 设置局部变量 - 双精度
jvmtiError (JNICALL *SetLocalDouble) (jvmtiEnv* env,
            jthread thread,
            jint depth,
            jint slot,
            jdouble value);
31 创建原始监视器
jvmtiError (JNICALL *CreateRawMonitor) (jvmtiEnv* env,
            const char* name,
            jrawMonitorID* monitor_ptr);
32 销毁原始监视器
jvmtiError (JNICALL *DestroyRawMonitor) (jvmtiEnv* env,
            jrawMonitorID monitor);
33 原始监视器输入
jvmtiError (JNICALL *RawMonitorEnter) (jvmtiEnv* env,
            jrawMonitorID monitor);
34 原始监视器退出
jvmtiError (JNICALL *RawMonitorExit) (jvmtiEnv* env,
            jrawMonitorID monitor);
35 原始监视器等待
jvmtiError (JNICALL *RawMonitorWait) (jvmtiEnv* env,
            jrawMonitorID monitor,
            jlong millis);
36 原始监视器通知
jvmtiError (JNICALL *RawMonitorNotify) (jvmtiEnv* env,
            jrawMonitorID monitor);
37 原始监视器通知所有
jvmtiError (JNICALL *RawMonitorNotifyAll) (jvmtiEnv* env,
            jrawMonitorID monitor);
38 设置断点
jvmtiError (JNICALL *SetBreakpoint) (jvmtiEnv* env,
            jmethodID method,
            jlocation location);
39 清除断点
jvmtiError (JNICALL *ClearBreakpoint) (jvmtiEnv* env,
            jmethodID method,
            jlocation location);
40 获取命名模块
jvmtiError (JNICALL *GetNamedModule) (jvmtiEnv* env,
            jobject class_loader,
            const char* package_name,
            jobject* module_ptr);
41 设置现场访问监视
jvmtiError (JNICALL *SetFieldAccessWatch) (jvmtiEnv* env,
            jclass klass,
            jfieldID field);
42 清晰的现场访问手表
jvmtiError (JNICALL *ClearFieldAccessWatch) (jvmtiEnv* env,
            jclass klass,
            jfieldID field);
43 设置字段修改监视
jvmtiError (JNICALL *SetFieldModificationWatch) (jvmtiEnv* env,
            jclass klass,
            jfieldID field);
44 清除字段修改手表
jvmtiError (JNICALL *ClearFieldModificationWatch) (jvmtiEnv* env,
            jclass klass,
            jfieldID field);
45 是可修改类
jvmtiError (JNICALL *IsModifiableClass) (jvmtiEnv* env,
            jclass klass,
            jboolean* is_modifiable_class_ptr);
46 分配
jvmtiError (JNICALL *Allocate) (jvmtiEnv* env,
            jlong size,
            unsigned char** mem_ptr);
47 解除分配
jvmtiError (JNICALL *Deallocate) (jvmtiEnv* env,
            unsigned char* mem);
48 获取类签名
jvmtiError (JNICALL *GetClassSignature) (jvmtiEnv* env,
            jclass klass,
            char** signature_ptr,
            char** generic_ptr);
49 获取类状态
jvmtiError (JNICALL *GetClassStatus) (jvmtiEnv* env,
            jclass klass,
            jint* status_ptr);
50 获取源文件名
jvmtiError (JNICALL *GetSourceFileName) (jvmtiEnv* env,
            jclass klass,
            char** source_name_ptr);
51 获取类修饰符
jvmtiError (JNICALL *GetClassModifiers) (jvmtiEnv* env,
            jclass klass,
            jint* modifiers_ptr);
52 获取类方法
jvmtiError (JNICALL *GetClassMethods) (jvmtiEnv* env,
            jclass klass,
            jint* method_count_ptr,
            jmethodID** methods_ptr);
53 获取类字段
jvmtiError (JNICALL *GetClassFields) (jvmtiEnv* env,
            jclass klass,
            jint* field_count_ptr,
            jfieldID** fields_ptr);
54 获取已实现的接口
jvmtiError (JNICALL *GetImplementedInterfaces) (jvmtiEnv* env,
            jclass klass,
            jint* interface_count_ptr,
            jclass** interfaces_ptr);
55 是接口
jvmtiError (JNICALL *IsInterface) (jvmtiEnv* env,
            jclass klass,
            jboolean* is_interface_ptr);
56 是数组类
jvmtiError (JNICALL *IsArrayClass) (jvmtiEnv* env,
            jclass klass,
            jboolean* is_array_class_ptr);
57 获取类加载器
jvmtiError (JNICALL *GetClassLoader) (jvmtiEnv* env,
            jclass klass,
            jobject* classloader_ptr);
58 获取对象哈希码
jvmtiError (JNICALL *GetObjectHashCode) (jvmtiEnv* env,
            jobject object,
            jint* hash_code_ptr);
59 获取对象监视器使用情况
jvmtiError (JNICALL *GetObjectMonitorUsage) (jvmtiEnv* env,
            jobject object,
            jvmtiMonitorUsage* info_ptr);
60 获取字段名称(和签名)
jvmtiError (JNICALL *GetFieldName) (jvmtiEnv* env,
            jclass klass,
            jfieldID field,
            char** name_ptr,
            char** signature_ptr,
            char** generic_ptr);
61 获取字段声明类
jvmtiError (JNICALL *GetFieldDeclaringClass) (jvmtiEnv* env,
            jclass klass,
            jfieldID field,
            jclass* declaring_class_ptr);
62 获取字段修饰符
jvmtiError (JNICALL *GetFieldModifiers) (jvmtiEnv* env,
            jclass klass,
            jfieldID field,
            jint* modifiers_ptr);
63 是场合成
jvmtiError (JNICALL *IsFieldSynthetic) (jvmtiEnv* env,
            jclass klass,
            jfieldID field,
            jboolean* is_synthetic_ptr);
64 获取方法名称(和签名)
jvmtiError (JNICALL *GetMethodName) (jvmtiEnv* env,
            jmethodID method,
            char** name_ptr,
            char** signature_ptr,
            char** generic_ptr);
65 获取方法声明类
jvmtiError (JNICALL *GetMethodDeclaringClass) (jvmtiEnv* env,
            jmethodID method,
            jclass* declaring_class_ptr);
66 获取方法修饰符
jvmtiError (JNICALL *GetMethodModifiers) (jvmtiEnv* env,
            jmethodID method,
            jint* modifiers_ptr);
67 预订的
void *reserved67;
68 获得最大当地人
jvmtiError (JNICALL *GetMaxLocals) (jvmtiEnv* env,
            jmethodID method,
            jint* max_ptr);
69 获取参数大小
jvmtiError (JNICALL *GetArgumentsSize) (jvmtiEnv* env,
            jmethodID method,
            jint* size_ptr);
70 获取行号表
jvmtiError (JNICALL *GetLineNumberTable) (jvmtiEnv* env,
            jmethodID method,
            jint* entry_count_ptr,
            jvmtiLineNumberEntry** table_ptr);
71 获取方法位置
jvmtiError (JNICALL *GetMethodLocation) (jvmtiEnv* env,
            jmethodID method,
            jlocation* start_location_ptr,
            jlocation* end_location_ptr);
72 获取局部变量表
jvmtiError (JNICALL *GetLocalVariableTable) (jvmtiEnv* env,
            jmethodID method,
            jint* entry_count_ptr,
            jvmtiLocalVariableEntry** table_ptr);
73 设置本机方法前缀
jvmtiError (JNICALL *SetNativeMethodPrefix) (jvmtiEnv* env,
            const char* prefix);
74 设置本机方法前缀
jvmtiError (JNICALL *SetNativeMethodPrefixes) (jvmtiEnv* env,
            jint prefix_count,
            char** prefixes);
75 获取字节码
jvmtiError (JNICALL *GetBytecodes) (jvmtiEnv* env,
            jmethodID method,
            jint* bytecode_count_ptr,
            unsigned char** bytecodes_ptr);
76 是本地方法
jvmtiError (JNICALL *IsMethodNative) (jvmtiEnv* env,
            jmethodID method,
            jboolean* is_native_ptr);
77 方法是合成的
jvmtiError (JNICALL *IsMethodSynthetic) (jvmtiEnv* env,
            jmethodID method,
            jboolean* is_synthetic_ptr);
78 获取加载类
jvmtiError (JNICALL *GetLoadedClasses) (jvmtiEnv* env,
            jint* class_count_ptr,
            jclass** classes_ptr);
79 获取类加载器类
jvmtiError (JNICALL *GetClassLoaderClasses) (jvmtiEnv* env,
            jobject initiating_loader,
            jint* class_count_ptr,
            jclass** classes_ptr);
80 流行框架
jvmtiError (JNICALL *PopFrame) (jvmtiEnv* env,
            jthread thread);
81 强制提前返回 - 对象
jvmtiError (JNICALL *ForceEarlyReturnObject) (jvmtiEnv* env,
            jthread thread,
            jobject value);
82 强制提前返回 - Int
jvmtiError (JNICALL *ForceEarlyReturnInt) (jvmtiEnv* env,
            jthread thread,
            jint value);
83 强制提前返回 - 长
jvmtiError (JNICALL *ForceEarlyReturnLong) (jvmtiEnv* env,
            jthread thread,
            jlong value);
84 强制提前返回 - 浮动
jvmtiError (JNICALL *ForceEarlyReturnFloat) (jvmtiEnv* env,
            jthread thread,
            jfloat value);
85 强制提前返回 - 双
jvmtiError (JNICALL *ForceEarlyReturnDouble) (jvmtiEnv* env,
            jthread thread,
            jdouble value);
86 强制提前返回 - 无效
jvmtiError (JNICALL *ForceEarlyReturnVoid) (jvmtiEnv* env,
            jthread thread);
87 重新定义类
jvmtiError (JNICALL *RedefineClasses) (jvmtiEnv* env,
            jint class_count,
            const jvmtiClassDefinition* class_definitions);
88 获取版本号
jvmtiError (JNICALL *GetVersionNumber) (jvmtiEnv* env,
            jint* version_ptr);
89 获得能力
jvmtiError (JNICALL *GetCapabilities) (jvmtiEnv* env,
            jvmtiCapabilities* capabilities_ptr);
90 获取源调试扩展
jvmtiError (JNICALL *GetSourceDebugExtension) (jvmtiEnv* env,
            jclass klass,
            char** source_debug_extension_ptr);
91 方法是否过时
jvmtiError (JNICALL *IsMethodObsolete) (jvmtiEnv* env,
            jmethodID method,
            jboolean* is_obsolete_ptr);
92 挂起线程列表
jvmtiError (JNICALL *SuspendThreadList) (jvmtiEnv* env,
            jint request_count,
            const jthread* request_list,
            jvmtiError* results);
93 恢复线程列表
jvmtiError (JNICALL *ResumeThreadList) (jvmtiEnv* env,
            jint request_count,
            const jthread* request_list,
            jvmtiError* results);
94 添加模块读取
jvmtiError (JNICALL *AddModuleReads) (jvmtiEnv* env,
            jobject module,
            jobject to_module);
95 添加模块导出
jvmtiError (JNICALL *AddModuleExports) (jvmtiEnv* env,
            jobject module,
            const char* pkg_name,
            jobject to_module);
96 添加模块打开
jvmtiError (JNICALL *AddModuleOpens) (jvmtiEnv* env,
            jobject module,
            const char* pkg_name,
            jobject to_module);
97 添加模块使用
jvmtiError (JNICALL *AddModuleUses) (jvmtiEnv* env,
            jobject module,
            jclass service);
98 添加模块提供
jvmtiError (JNICALL *AddModuleProvides) (jvmtiEnv* env,
            jobject module,
            jclass service,
            jclass impl_class);
99 是可修改模块
jvmtiError (JNICALL *IsModifiableModule) (jvmtiEnv* env,
            jobject module,
            jboolean* is_modifiable_module_ptr);
100 获取所有堆栈跟踪
jvmtiError (JNICALL *GetAllStackTraces) (jvmtiEnv* env,
            jint max_frame_count,
            jvmtiStackInfo** stack_info_ptr,
            jint* thread_count_ptr);
101 获取线程列表堆栈跟踪
jvmtiError (JNICALL *GetThreadListStackTraces) (jvmtiEnv* env,
            jint thread_count,
            const jthread* thread_list,
            jint max_frame_count,
            jvmtiStackInfo** stack_info_ptr);
102 获取线程本地存储
jvmtiError (JNICALL *GetThreadLocalStorage) (jvmtiEnv* env,
            jthread thread,
            void** data_ptr);
103 设置线程本地存储
jvmtiError (JNICALL *SetThreadLocalStorage) (jvmtiEnv* env,
            jthread thread,
            const void* data);
104 获取堆栈跟踪
jvmtiError (JNICALL *GetStackTrace) (jvmtiEnv* env,
            jthread thread,
            jint start_depth,
            jint max_frame_count,
            jvmtiFrameInfo* frame_buffer,
            jint* count_ptr);
105 预订的
void *reserved105;
106 获取标签
jvmtiError (JNICALL *GetTag) (jvmtiEnv* env,
            jobject object,
            jlong* tag_ptr);
107 设置标签
jvmtiError (JNICALL *SetTag) (jvmtiEnv* env,
            jobject object,
            jlong tag);
108 强制垃圾收集
jvmtiError (JNICALL *ForceGarbageCollection) (jvmtiEnv* env);
109 遍历从对象可达的对象
jvmtiError (JNICALL *IterateOverObjectsReachableFromObject) (jvmtiEnv* env,
            jobject object,
            jvmtiObjectReferenceCallback object_reference_callback,
            const void* user_data);
110 遍历可达对象
jvmtiError (JNICALL *IterateOverReachableObjects) (jvmtiEnv* env,
            jvmtiHeapRootCallback heap_root_callback,
            jvmtiStackReferenceCallback stack_ref_callback,
            jvmtiObjectReferenceCallback object_ref_callback,
            const void* user_data);
111 遍历堆
jvmtiError (JNICALL *IterateOverHeap) (jvmtiEnv* env,
            jvmtiHeapObjectFilter object_filter,
            jvmtiHeapObjectCallback heap_object_callback,
            const void* user_data);
112 迭代类的实例
jvmtiError (JNICALL *IterateOverInstancesOfClass) (jvmtiEnv* env,
            jclass klass,
            jvmtiHeapObjectFilter object_filter,
            jvmtiHeapObjectCallback heap_object_callback,
            const void* user_data);
113 预订的
void *reserved113;
114 获取带有标签的对象
jvmtiError (JNICALL *GetObjectsWithTags) (jvmtiEnv* env,
            jint tag_count,
            const jlong* tags,
            jint* count_ptr,
            jobject** object_result_ptr,
            jlong** tag_result_ptr);
115 按照参考资料
jvmtiError (JNICALL *FollowReferences) (jvmtiEnv* env,
            jint heap_filter,
            jclass klass,
            jobject initial_object,
            const jvmtiHeapCallbacks* callbacks,
            const void* user_data);
116 遍历堆
jvmtiError (JNICALL *IterateThroughHeap) (jvmtiEnv* env,
            jint heap_filter,
            jclass klass,
            const jvmtiHeapCallbacks* callbacks,
            const void* user_data);
117 预订的
void *reserved117;
118 挂起所有虚拟线程
jvmtiError (JNICALL *SuspendAllVirtualThreads) (jvmtiEnv* env,
            jint except_count,
            const jthread* except_list);
119 恢复所有虚拟线程
jvmtiError (JNICALL *ResumeAllVirtualThreads) (jvmtiEnv* env,
            jint except_count,
            const jthread* except_list);
120 设置 JNI 函数表
jvmtiError (JNICALL *SetJNIFunctionTable) (jvmtiEnv* env,
            const jniNativeInterface* function_table);
121 获取 JNI 函数表
jvmtiError (JNICALL *GetJNIFunctionTable) (jvmtiEnv* env,
            jniNativeInterface** function_table);
122 设置事件回调
jvmtiError (JNICALL *SetEventCallbacks) (jvmtiEnv* env,
            const jvmtiEventCallbacks* callbacks,
            jint size_of_callbacks);
123 生成事件
jvmtiError (JNICALL *GenerateEvents) (jvmtiEnv* env,
            jvmtiEvent event_type);
124 获取扩展函数
jvmtiError (JNICALL *GetExtensionFunctions) (jvmtiEnv* env,
            jint* extension_count_ptr,
            jvmtiExtensionFunctionInfo** extensions);
125 获取扩展事件
jvmtiError (JNICALL *GetExtensionEvents) (jvmtiEnv* env,
            jint* extension_count_ptr,
            jvmtiExtensionEventInfo** extensions);
126 设置扩展事件回调
jvmtiError (JNICALL *SetExtensionEventCallback) (jvmtiEnv* env,
            jint extension_event_index,
            jvmtiExtensionEvent callback);
127 处理环境
jvmtiError (JNICALL *DisposeEnvironment) (jvmtiEnv* env);
128 获取错误名称
jvmtiError (JNICALL *GetErrorName) (jvmtiEnv* env,
            jvmtiError error,
            char** name_ptr);
129 获取 JLocation 格式
jvmtiError (JNICALL *GetJLocationFormat) (jvmtiEnv* env,
            jvmtiJlocationFormat* format_ptr);
130 获取系统属性
jvmtiError (JNICALL *GetSystemProperties) (jvmtiEnv* env,
            jint* count_ptr,
            char*** property_ptr);
131 获取系统属性
jvmtiError (JNICALL *GetSystemProperty) (jvmtiEnv* env,
            const char* property,
            char** value_ptr);
132 设置系统属性
jvmtiError (JNICALL *SetSystemProperty) (jvmtiEnv* env,
            const char* property,
            const char* value_ptr);
133 获取阶段
jvmtiError (JNICALL *GetPhase) (jvmtiEnv* env,
            jvmtiPhase* phase_ptr);
134 获取当前线程 CPU 计时器信息
jvmtiError (JNICALL *GetCurrentThreadCpuTimerInfo) (jvmtiEnv* env,
            jvmtiTimerInfo* info_ptr);
135 获取当前线程 CPU 时间
jvmtiError (JNICALL *GetCurrentThreadCpuTime) (jvmtiEnv* env,
            jlong* nanos_ptr);
136 获取线程 CPU 定时器信息
jvmtiError (JNICALL *GetThreadCpuTimerInfo) (jvmtiEnv* env,
            jvmtiTimerInfo* info_ptr);
137 获取线程 CPU 时间
jvmtiError (JNICALL *GetThreadCpuTime) (jvmtiEnv* env,
            jthread thread,
            jlong* nanos_ptr);
138 获取定时器信息
jvmtiError (JNICALL *GetTimerInfo) (jvmtiEnv* env,
            jvmtiTimerInfo* info_ptr);
139 获取时间
jvmtiError (JNICALL *GetTime) (jvmtiEnv* env,
            jlong* nanos_ptr);
140 获得潜在能力
jvmtiError (JNICALL *GetPotentialCapabilities) (jvmtiEnv* env,
            jvmtiCapabilities* capabilities_ptr);
141 预订的
void *reserved141;
142 添加功能
jvmtiError (JNICALL *AddCapabilities) (jvmtiEnv* env,
            const jvmtiCapabilities* capabilities_ptr);
143 放弃能力
jvmtiError (JNICALL *RelinquishCapabilities) (jvmtiEnv* env,
            const jvmtiCapabilities* capabilities_ptr);
144 获取可用的处理器
jvmtiError (JNICALL *GetAvailableProcessors) (jvmtiEnv* env,
            jint* processor_count_ptr);
145 获取类版本号
jvmtiError (JNICALL *GetClassVersionNumbers) (jvmtiEnv* env,
            jclass klass,
            jint* minor_version_ptr,
            jint* major_version_ptr);
146 获取常量池
jvmtiError (JNICALL *GetConstantPool) (jvmtiEnv* env,
            jclass klass,
            jint* constant_pool_count_ptr,
            jint* constant_pool_byte_count_ptr,
            unsigned char** constant_pool_bytes_ptr);
147 获取环境本地存储
jvmtiError (JNICALL *GetEnvironmentLocalStorage) (jvmtiEnv* env,
            void** data_ptr);
148 设置环境本地存储
jvmtiError (JNICALL *SetEnvironmentLocalStorage) (jvmtiEnv* env,
            const void* data);
149 添加到 Bootstrap 类加载器搜索
jvmtiError (JNICALL *AddToBootstrapClassLoaderSearch) (jvmtiEnv* env,
            const char* segment);
150 设置详细标志
jvmtiError (JNICALL *SetVerboseFlag) (jvmtiEnv* env,
            jvmtiVerboseFlag flag,
            jboolean value);
151 添加到系统类加载器搜索
jvmtiError (JNICALL *AddToSystemClassLoaderSearch) (jvmtiEnv* env,
            const char* segment);
152 重新转换类
jvmtiError (JNICALL *RetransformClasses) (jvmtiEnv* env,
            jint class_count,
            const jclass* classes);
153 获取拥有的监视器堆栈深度信息
jvmtiError (JNICALL *GetOwnedMonitorStackDepthInfo) (jvmtiEnv* env,
            jthread thread,
            jint* monitor_info_count_ptr,
            jvmtiMonitorStackDepthInfo** monitor_info_ptr);
154 获取对象大小
jvmtiError (JNICALL *GetObjectSize) (jvmtiEnv* env,
            jobject object,
            jlong* size_ptr);
155 获取本地实例
jvmtiError (JNICALL *GetLocalInstance) (jvmtiEnv* env,
            jthread thread,
            jint depth,
            jobject* value_ptr);
156 设置堆采样间隔
jvmtiError (JNICALL *SetHeapSamplingInterval) (jvmtiEnv* env,
            jint sampling_interval);


事件

处理事件

代理可以获知应用程序中发生的许多事件。
要处理事件,请使用 SetEventCallbacks 指定一组回调函数。对于每个事件,将调用相应的回调函数。回调函数的参数提供有关事件的附加信息。
回调函数通常在应用程序线程中调用。虚拟机 TI 实现不会以任何方式对事件进行排队。这意味着必须仔细编写事件回调函数。以下是一些一般准则。请参阅个别事件描述以获取更多建议。
一些JVM TI 事件标识具有 JNI 引用的对象。 JVM 中的所有引用 TI事件是JNI本地引用,事件回调返回后失效。除非另有说明,事件回调中发送的指针所引用的内存在事件回调返回后可能不会被引用。
除非另有说明,否则事件将在导致事件的线程上传递。事件在发生时发送。每个事件的规范包括可以发送它的 阶段 集合;如果事件触发活动发生在另一个阶段,则不会发送任何事件。
产生事件的线程不会改变它的执行状态(例如,事件不会导致线程被挂起)。如果代理希望事件导致挂起,则代理负责使用 SuspendThread 显式挂起线程。
如果在多个环境中启用了一个事件,该事件将按照环境创建的顺序发送到每个代理。

启用事件

所有事件最初都是禁用的。为了接收任何事件:

多个同地活动

在许多情况下,一个线程中的同一位置可能会发生多个事件。发生这种情况时,将按照本节中指定的顺序通过事件回调报告所有事件。
如果当前位置位于方法的入口点,则MethodEntry 事件在同一线程中当前位置的任何其他事件之前报告。
如果在当前位置检测到异常捕获,要么是因为它是 catch 子句的开头,要么是清除挂起异常的本机方法已返回,exceptionCatch 事件将在同一位置的任何其他事件之前报告线。
如果 singleStep 事件或 breakpoint 事件在当前位置被触发,则该事件被定义为在执行当前位置的代码之前立即发生。这些事件在同一线程的当前位置执行代码触发的任何事件之前报告(特别是:exceptionfieldAccessfieldModification)。如果同一线程和位置同时触发了步进事件和断点事件,则步进事件在断点事件之前报告。
如果当前位置是方法的出口点(即返回调用者之前的最后一个位置),MethodExit 事件和 FramePop 事件(如果请求)在同一线程中当前位置的所有其他事件之后报告.这两个事件彼此之间没有特定的顺序。
在同一线程中同一位置的代理处理某些其他事件期间,可以触发并置事件。如果这样的事件,类型y, 在处理类型事件期间触发x, 而如果x先于y在上面指定的顺序中,同一地点的事件y报告当前线程和位置。如果x不先于y, y未报告当前线程和位置。例如,如果在 SingleStep 的处理过程中在当前位置设置了断点,则在线程离开当前位置之前将报告该断点。
以下事件永远不会被视为与其他事件位于同一地点。

事件回调

下面的事件回调结构用于指定事件的处理函数。它通过SetEventCallbacks 函数设置。
typedef struct {
  jvmtiEventVMInit VMInit;
  jvmtiEventVMDeath VMDeath;
  jvmtiEventThreadStart ThreadStart;
  jvmtiEventThreadEnd ThreadEnd;
  jvmtiEventClassFileLoadHook ClassFileLoadHook;
  jvmtiEventClassLoad ClassLoad;
  jvmtiEventClassPrepare ClassPrepare;
  jvmtiEventVMStart VMStart;
  jvmtiEventException Exception;
  jvmtiEventExceptionCatch ExceptionCatch;
  jvmtiEventSingleStep SingleStep;
  jvmtiEventFramePop FramePop;
  jvmtiEventBreakpoint Breakpoint;
  jvmtiEventFieldAccess FieldAccess;
  jvmtiEventFieldModification FieldModification;
  jvmtiEventMethodEntry MethodEntry;
  jvmtiEventMethodExit MethodExit;
  jvmtiEventNativeMethodBind NativeMethodBind;
  jvmtiEventCompiledMethodLoad CompiledMethodLoad;
  jvmtiEventCompiledMethodUnload CompiledMethodUnload;
  jvmtiEventDynamicCodeGenerated DynamicCodeGenerated;
  jvmtiEventDataDumpRequest DataDumpRequest;
  jvmtiEventReserved reserved72;
  jvmtiEventMonitorWait MonitorWait;
  jvmtiEventMonitorWaited MonitorWaited;
  jvmtiEventMonitorContendedEnter MonitorContendedEnter;
  jvmtiEventMonitorContendedEntered MonitorContendedEntered;
  jvmtiEventReserved reserved77;
  jvmtiEventReserved reserved78;
  jvmtiEventReserved reserved79;
  jvmtiEventResourceExhausted ResourceExhausted;
  jvmtiEventGarbageCollectionStart GarbageCollectionStart;
  jvmtiEventGarbageCollectionFinish GarbageCollectionFinish;
  jvmtiEventObjectFree ObjectFree;
  jvmtiEventVMObjectAlloc VMObjectAlloc;
  jvmtiEventReserved reserved85;
  jvmtiEventSampledObjectAlloc SampledObjectAlloc;
  jvmtiEventVirtualThreadStart VirtualThreadStart;
  jvmtiEventVirtualThreadEnd VirtualThreadEnd;
} jvmtiEventCallbacks;

事件索引


一小步

void JNICALL
SingleStep(jvmtiEnv *jvmti_env,
      JNIEnv* jni_env,
      jthread thread,
      jmethodID method,
      jlocation location)
单步事件允许代理以 VM 允许的最细粒度跟踪线程执行。每当线程到达新位置时,都会生成单步事件。通常,单步事件代表一个 VM 指令的完成,如定义在Java™ 虚拟机规范.但是,某些实现可能会以不同方式定义位置。在任何情况下,methodlocation 参数唯一标识当前位置,并在该信息可用时允许映射到源文件和行号。
本机方法内不会生成任何单步事件。
仅在直播阶段发送
JVMTI_EVENT_SINGLE_STEP
60
SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_SINGLE_STEP, NULL)
1.0
能力
可选功能:可能不会对所有虚拟机实施。以下功能(由 GetCapabilities 返回)必须为真才能使用此事件。
能力 影响
can_generate_single_step_events 可以获得一小步个事件
参数
Name Type Description
jni_env JNIEnv * 事件(当前)线程的 JNI 环境
thread jthread 即将执行新指令的线程
method