JVM工具接口是什么?
JVM工具接口(JVM TI)是开发和监控工具使用的编程接口。它提供了一种检查状态和控制在Java虚拟机(VM)中运行的应用程序的方式。 JVM TI旨在为需要访问VM状态的各种工具提供VM接口,包括但不限于:性能分析、调试、监控、线程分析和覆盖分析工具。 JVM TI可能并非所有Java虚拟机实现中都可用。 JVM TI是一个双向接口。JVM TI的客户端,以下简称为代理,可以通过事件被通知有趣的发生。JVM TI可以通过许多函数查询和控制应用程序,无论是响应事件还是独立于事件。 代理在与执行被检查应用程序的虚拟机相同的进程中运行并直接与之通信。这种通信是通过本机接口(JVM TI)进行的。本机进程接口允许在最大程度上控制工具而对目标应用程序的正常执行几乎没有干扰。通常,代理相对较小。它们可以由实现大部分工具功能的单独进程控制,而不会干扰目标应用程序的正常执行。架构
工具可以直接编写到JVM TI,也可以通过更高级别的接口间接编写。Java平台调试器架构包括JVM TI,但还包含更高级别的、独立于进程的调试器接口。对于许多工具来说,更高级别的接口比JVM TI更合适。有关Java平台调试器架构的更多信息,请参阅Java平台调试器架构网站。编写代理
代理可以用支持C语言调用约定和C或C++定义的任何本机语言编写。 用于使用JVM TI的函数、事件、数据类型和常量定义在包含文件jvmti.h中。要使用这些定义,将J2SE包含目录添加到您的包含路径中,并在源代码中添加
#include <jvmti.h>
。
部署代理
代理以特定于平台的方式部署,但通常是动态库的平台等效物。例如,在Windows操作系统上,代理库是“动态链接库”(DLL)。在Linux操作环境中,代理库是一个共享对象(.so文件)。
可以通过指定代理库名称的命令行选项在VM启动时启动代理。一些实现可能支持一种机制来在活动阶段启动代理。如何启动这一点是特定于实现的。
静态链接代理(自版本1.2.3起)
本机JVMTI代理可以与VM静态链接。库和VM映像的组合方式取决于实现。如果代理L的映像已与VM组合,则仅当代理导出一个名为Agent_OnLoad_L的函数时,代理L被定义为静态链接。 如果一个静态链接代理L导出一个名为Agent_OnLoad_L的函数和一个名为Agent_OnLoad的函数,则将忽略Agent_OnLoad函数。如果代理L是静态链接的,则将调用Agent_OnLoad_L函数,参数和预期返回值与Agent_OnLoad函数指定的相同。一个被静态链接的代理L将禁止以相同名称的代理动态加载。 如果一个静态链接的代理L导出一个名为Agent_OnUnload_L的函数和一个名为Agent_OnUnload的函数,则将忽略Agent_OnUnload函数。如果一个静态链接的代理L导出一个名为Agent_OnUnload_L的函数和一个名为Agent_OnUnload的函数,则将忽略Agent_OnUnload函数。 如果一个静态链接的代理L导出一个名为Agent_OnAttach_L的函数和一个名为Agent_OnAttach的函数,则将忽略Agent_OnAttach函数。如果一个静态链接的代理L导出一个名为Agent_OnAttach_L的函数和一个名为Agent_OnAttach的函数,则将忽略Agent_OnAttach函数。代理命令行选项
下面使用术语“命令行选项”指的是在JNI调用API的JNI_CreateJavaVM函数的JavaVMInitArgs参数中提供的选项。
在VM启动时,以下两个命令行选项之一用于正确加载和运行代理。这些参数标识包含代理的库以及在启动时传递的选项字符串。
-
-agentlib:<agent-lib-name>=<options> -
-agentlib:后面的名称是要加载的库的名称。库的查找,包括其完整名称和位置,按照特定于平台的方式进行。通常,<agent-lib-name>会扩展为操作系统特定的文件名。选项<options>将在启动时传递给代理。例如,如果指定选项-agentlib:foo=opt1,opt2,VM将尝试从Windows下的系统PATH中加载共享库foo.dll,或者从Linux下的LD_LIBRARY_PATH中加载libfoo.so。如果代理库已静态链接到可执行文件中,则不会进行实际加载。 -
-agentpath:<path-to-agent>=<options> -
-agentpath:后面的路径是要加载库的绝对路径。不会发生库名称扩展。选项<options>将在启动时传递给代理。例如,如果指定选项-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的状态。不需要命令行选项来启用JVM或JVM的某些方面,这是通过功能的程序化使用来处理的。
代理启动
VM通过调用启动函数来启动每个代理。如果代理在OnLoad阶段启动,则将调用函数Agent_OnLoad或静态链接代理的Agent_OnLoad_L。如果代理在活动阶段启动,则将调用函数Agent_OnAttach或静态链接代理的Agent_OnAttach_L。每个代理只调用一次启动函数。
代理启动(OnLoad阶段)
如果代理在OnLoad阶段启动,则其代理库必须导出具有以下原型的启动函数:
或对于名为'L'的静态链接代理:JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
VM将通过调用此函数来启动代理。它将在VM初始化的早期调用,以便: 虚拟机将调用JNIEXPORT jint JNICALL Agent_OnLoad_L(JavaVM *vm, char *options, void *reserved)
Agent_OnLoad 或 Agent_OnLoad_<agent-lib-name> 函数,并将 <options> 作为第二个参数传递 - 也就是说,使用命令行选项示例, "opt1,opt2" 将传递给 char *options 参数的 Agent_OnLoad。 options 参数被编码为 修改后的 UTF-8 字符串。如果未指定 =<options>,则传递一个长度为零的字符串给 options。 options 字符串的生命周期是 Agent_OnLoad 或 Agent_OnLoad_<agent-lib-name> 调用。如果在此时间之后仍需要该字符串或字符串的部分,则必须复制。从 Agent_OnLoad 被调用到返回的时间段称为 OnLoad 阶段。由于虚拟机在 OnLoad 阶段期间尚未初始化,因此在 Agent_OnLoad 内允许的操作集受到限制(请参阅此时可用功能的功能描述)。代理可以安全地处理选项并使用 SetEventCallbacks 设置事件回调。一旦接收到虚拟机初始化事件(即调用 VMInit 回调),代理就可以完成其初始化。
原因:早期启动是必需的,以便代理可以设置所需的功能,其中许多功能必须在虚拟机初始化之前设置。在 JVMDI 中,-Xdebug 命令行选项提供了非常粗粒度的功能控制。JVMPI 实现使用各种技巧提供单个“JVMPI on”开关。没有合理的命令行选项可以提供所需功能与性能影响之间所需的精细控制。早期启动还是必需的,以便代理可以控制执行环境 - 修改文件系统和系统属性以安装其功能。
从Agent_OnLoad 或 Agent_OnLoad_<agent-lib-name> 的返回值用于指示错误。除零以外的任何值均表示错误并导致虚拟机终止。
代理启动(活动阶段)
虚拟机可能支持一种机制,允许代理在虚拟机的活动 阶段中启动。支持方式的详细信息是特定于实现的。例如,工具可能使用某些特定于平台的机制或特定于实现的 API,附加到运行中的虚拟机,并请求其启动给定代理。 虚拟机会在标准错误流上为每个尝试在活动阶段启动的代理打印警告。如果先前已启动代理(在OnLoad 阶段或活动阶段),则在尝试第二次或后续次启动相同代理时是否打印警告是特定于实现的。警告可以通过特定于实现的命令行选项禁用。
实现注意: 对于 HotSpot 虚拟机,VM 选项 -XX:+EnableDynamicAgentLoading 用于选择允许在活动阶段动态加载代理。此选项抑制了在活动阶段启动代理时向标准错误打印警告。
如果在活动阶段启动代理,则其代理库必须导出具有以下原型的启动函数:
或对于名为 'L' 的静态链接代理:JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM* vm, char *options, void *reserved)
虚拟机将通过调用此函数来启动代理。它将在附加到虚拟机的线程的上下文中调用。第一个参数 <vm> 是 Java VM。 <options> 参数是提供给代理的启动选项。 <options> 被编码为 修改后的 UTF-8 字符串。如果未提供启动选项,则传递一个长度为零的字符串给JNIEXPORT jint JNICALL Agent_OnAttach_L(JavaVM* vm, char *options, void *reserved)
options。 options 字符串的生命周期是 Agent_OnAttach 或 Agent_OnAttach_<agent-lib-name> 调用。如果在此时间之后仍需要该字符串或字符串的部分,则必须复制。
请注意,一些 功能 在活动阶段可能不可用。
Agent_OnAttach 或 Agent_OnAttach_<agent-lib-name > 函数初始化代理并返回一个值给虚拟机,指示是否发生错误。除零以外的任何值表示错误。错误不会导致虚拟机终止。相反,虚拟机会忽略错误,或者采取某些特定于实现的操作--例如,可能会将错误打印到标准错误,或者在系统日志中记录错误。
代理卸载
库可以选择导出具有以下原型的卸载函数:或对于名为 'L' 的静态链接代理:JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm)
当库即将被卸载时,虚拟机将调用此函数。库将被卸载(除非它被静态链接到可执行文件中),并且如果某些特定于平台的机制导致卸载(本文档中未指定卸载机制),或者库被(实际上)由虚拟机的终止卸载,则将调用此函数。虚拟机终止包括正常终止和虚拟机失败,包括启动失败,但当然不包括不受控制的关闭。如果JNIEXPORT void JNICALL Agent_OnUnload_L(JavaVM *vm)
Agent_OnAttach/ Agent_OnAttach_L 函数报告错误(返回非零值),实现也可以选择不调用此函数。请注意此函数与 VM 死亡事件之间的区别:要发送 VM 死亡事件,虚拟机必须至少运行到初始化点,并存在已设置 VMDeath 回调并启用事件的有效 JVM TI 环境。这些对于 Agent_OnUnload 或 Agent_OnUnload_<agent-lib-name> 都不是必需的,如果库由于其他原因被卸载,则也会调用此函数。在发送 VM 死亡事件之前,将调用此函数(假设由于 VM 终止而调用此函数)。此函数可用于清理代理分配的资源。
JAVA_TOOL_OPTIONS
由于无法始终访问或修改命令行,例如在嵌入式虚拟机中或仅在脚本深处启动的虚拟机中,提供了一个JAVA_TOOL_OPTIONS 变量,以便代理可以在这些情况下启动。
支持环境变量或其他命名字符串的平台可能支持 JAVA_TOOL_OPTIONS 变量。此变量将在空格边界处分隔为选项。空格字符包括空格、制表符、回车、换行、垂直制表符和换页符。连续的空格字符被视为等同于单个空格字符。除非用引号引起来,否则选项中不包含空格。引号如下:
- 位于一对单引号('')之间的所有字符,除了单引号,都被引用。
- 双引号字符在一对单引号('')之间没有特殊含义。
- 位于一对双引号("")之间的所有字符,除了双引号,都被引用。
- 单引号字符在一对双引号("")之间没有特殊含义。
- 引用部分可以从变量的任何位置开始或结束。
- 在引用时,空格字符没有特殊含义--它们像任何其他字符一样包含在选项中,不标记空格边界。
- 引号标记不包含在选项中。
JNI_CreateJavaVM(在 JNI 调用 API 中)将这些选项前置到其 JavaVMInitArgs 参数中提供的选项之前。在安全性成为问题的情况下,平台可以禁用此功能;例如,参考实现在 Unix 系统上当有效用户或组 ID 与实际 ID 不同时会禁用此功能。此功能旨在支持工具的初始化--特别包括启动本地或 Java 编程语言代理。多个工具可能希望使用此功能,因此不应覆盖变量,而应将选项附加到变量。请注意,由于变量在 JNI 调用 API 创建 VM 调用时处理,因此由启动器处理的选项(例如,VM 选择选项)将不会被处理。
环境
JVM TI 规范支持多个同时存在的 JVM TI 代理。每个代理都有自己的 JVM TI 环境。也就是说,每个代理的 JVM TI 状态是独立的 - 对一个环境的更改不会影响其他环境。一个 JVM TI 环境的状态包括: 尽管它们的 JVM TI 状态是独立的,代理检查和修改 VM 的共享状态,它们还共享它们执行的本机环境。因此,代理可以扰乱其他代理的结果或导致它们失败。代理编写者有责任指定与其他代理的兼容性级别。 JVM TI实现无法阻止代理之间的破坏性交互。减少这些事件发生可能性的技术超出了本文档的范围。 代理通过将JVM版本作为JNI调用API函数 GetEnv的接口ID来创建JVM TI环境。有关创建和使用JVM TI环境的更多详细信息,请参阅访问JVM TI函数。通常,通过从Agent_OnLoad调用GetEnv来创建JVM TI环境。
字节码插装
此接口不包括一些人们可能期望在具有性能分析支持的接口中看到的事件。一些示例包括完整速度的方法进入和退出事件。相反,该接口提供了对字节码插装的支持,即修改构成目标程序的Java虚拟机字节码指令的能力。通常,这些修改是为了向方法的代码添加“事件” - 例如,在方法的开头添加一个调用MyProfiler.methodEntered()的调用。由于更改仅是添加性的,它们不会修改应用程序状态或行为。由于插入的代理代码是标准字节码,因此VM可以以全速运行,不仅优化目标程序,还优化插装。如果插装不涉及从字节码执行切换,则不需要昂贵的状态转换。结果是高性能事件。这种方法还为代理提供了完全控制:插装可以限制在代码的“有趣”部分(例如,最终用户的代码)并且可以是有条件的。插装可以完全在Java编程语言代码中运行,也可以调用本机代理。插装可以简单地维护计数器,也可以对事件进行统计采样。
可以通过以下三种方式插入插装:
- 静态插装:在加载到VM之前对类文件进行插装 - 例如,通过创建一个已修改以添加插装的
*.class文件的副本目录。这种方法非常笨拙,并且一般来说,代理无法知道将要加载的类文件的来源。 - 加载时插装:当VM加载类文件时,将类文件的原始字节发送给代理进行插装。由类加载触发的
ClassFileLoadHook事件提供此功能。此机制提供了对一次性插装的高效和完整访问。 - 动态插装:修改已加载(甚至可能正在运行)的类。这是通过调用
RetransformClasses函数触发的可选功能的一部分。类可以多次修改,并且可以返回到其原始状态。该机制允许在执行过程中发生变化的插装。
ClassFileLoadHook事件和RetransformClasses函数),以及在开发期间进行修复和继续调试(RedefineClasses函数)。
在插装核心类时必须小心避免干扰依赖关系。例如,获取每个对象分配通知的一种方法是对Object的构造函数进行插装。假设构造函数最初为空,则构造函数可以更改为:
public Object() {
MyProfiler.allocationTracker(this);
}
但是,如果使用ClassFileLoadHook事件进行此更改,则可能会影响典型VM的方式:第一个创建的对象将调用构造函数,导致加载MyProfiler;然后导致对象创建,由于MyProfiler尚未加载,会导致无限递归;从而导致堆栈溢出。对此的改进是延迟调用跟踪方法直到安全时间。例如,trackAllocations可以在VMInit事件的处理程序中设置。
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平台而不是本机平台(除非另有说明)。例如:- “线程”表示Java编程语言线程。
- “堆栈帧”表示Java虚拟机堆栈帧。
- “类”表示Java编程语言类。
- “堆”表示Java虚拟机堆。
- “监视器”表示Java编程语言对象监视器。
函数
访问函数
本机代码通过调用JVM TI函数来访问JVM TI功能。访问JVM TI函数是通过与Java本机接口(JNI)函数访问方式相同的接口指针来实现的。JVM TI接口指针称为环境指针。 环境指针是指向环境的指针,类型为jvmtiEnv*。环境包含有关其JVM TI连接的信息。环境中的第一个值是指向函数表的指针。函数表是指向JVM TI函数的指针数组。每个函数指针位于数组内的预定义偏移量处。
在C语言中使用时:使用双重间接访问函数;环境指针提供上下文,并且是每个函数调用的第一个参数;例如:
jvmtiEnv *jvmti;
...
jvmtiError err = (*jvmti)->GetLoadedClasses(jvmti, &class_count, &classes);
在C++语言中使用时:函数作为jvmtiEnv的成员函数访问;环境指针不会传递给函数调用;例如:
jvmtiEnv *jvmti;
...
jvmtiError err = jvmti->GetLoadedClasses(&class_count, &classes);
除非另有说明,本规范中的所有示例和声明均使用C语言。
可以通过JNI调用APIGetEnv函数获取JVM TI环境:
jvmtiEnv *jvmti;
...
(*jvm)->GetEnv(jvm, &jvmti, JVMTI_VERSION_1_0);
每次调用GetEnv都会创建一个新的JVM TI连接,因此会创建一个新的JVM TI环境。 GetEnv的version参数必须是JVM TI版本。返回的环境可能与请求的版本不同,但返回的环境必须是兼容的。GetEnv将返回JNI_EVERSION如果没有可用的兼容版本,如果不支持JVM TI或JVM TI在当前VM配置中不受支持。其他接口可能会添加用于在特定上下文中创建JVM TI环境的接口。每个环境都有自己的状态(例如,所需事件、事件处理函数和功能)。使用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 TI调用期间创建的。局部引用是必须管理的资源(请参阅JNI文档)。当线程从本机代码返回时,所有局部引用都将被释放。请注意,包括典型代理线程在内的一些线程永远不会从本机代码返回。确保线程能够创建十六个局部引用而无需任何显式管理。对于在返回本机代码之前执行有限数量的JVM TI调用的线程(例如,处理事件的线程),可能确定不需要任何显式管理。然而,长时间运行的代理线程将需要显式的局部引用管理--通常使用JNI函数PushLocalFrame和PopLocalFrame。相反,为了在从本机代码返回后保留引用,它们必须转换为全局引用。这些规则不适用于jmethodID和jfieldID,因为它们不是jobject。
调用函数的先决状态
除非函数明确说明代理必须将线程或VM带到特定状态(例如,暂停),否则JVM TI实现负责将VM带到安全和一致的状态以执行函数。异常和函数
JVM TI函数永远不会抛出异常;错误条件通过函数返回值进行通信。任何现有的异常状态在调用JVM TI函数时保留。有关处理异常的信息,请参阅JNI规范中的Java异常部分。函数索引
- 内存管理
- 线程
- 线程组
- 堆栈帧
- 强制提前返回
- 堆
- 堆(1.0)
- 局部变量
- 断点
- 监视字段
- 模块
- 类
- 对象
- 字段
- 方法
- 原始监视器
- JNI函数拦截
- 事件管理
- 扩展机制
- 能力
- 计时器
- 类加载器搜索
- 系统属性
- 通用
- 堆监控
内存管理
内存管理函数:- 分配
- 释 TI功能,可用于为代理提供工作内存。由JVM管理的内存 TI与其他内存分配库和机制不兼容。
分配
通过JVM TI分配器分配一块内存区域。分配的内存应该使用jvmtiError Allocate(jvmtiEnv* env, jlong size, unsigned char** mem_ptr)Deallocate释放。可在任何阶段调用461.0功能所需功能参数 名称 类型 描述 sizejlong要分配的字节数。 理由:
jlong用于与JVMDI兼容。mem_ptrunsigned char**返回时,指向分配内存起始位置的指针。如果 size为零,则返回NULL。 代理传递一个指向unsigned char*的指针。返回时,unsigned char*指向一个新分配的大小为size的数组。该数组应使用Deallocate释放。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_OUT_OF_MEMORY无法满足内存请求。 JVMTI_ERROR_ILLEGAL_ARGUMENTsize小于零。JVMTI_ERROR_NULL_POINTERmem_ptr为NULL。
释放
使用JVM TI分配器释放jvmtiError Deallocate(jvmtiEnv* env, unsigned char* mem)mem。应使用此函数释放由JVM TI函数(包括使用Allocate分配的内存)。必须释放所有分配的内存,否则无法回收内存。可在任何阶段调用471.0功能所需功能参数 名称 类型 描述 memunsigned char *指向分配内存起始位置的指针。请忽略“返回时,元素被设置。” 代理传递一个 unsigned char数组。数组元素的传入值将被忽略。返回时,元素被设置。如果mem为NULL,则调用被忽略。错误此函数返回一个通用错误
线程
线程函数:- 获取线程状态
- 获取当前线程
- 获取所有线程
- 挂起线程
- 挂起线程列表
- 挂起所有虚拟线程
- 恢复线程
- 恢复线程列表
- 恢复所有虚拟线程
- 停止线程
- 中断线程
- 获取线程信息
- 获取拥有的监视器信息
- 获取拥有的监视器堆栈深度信息
- 获取当前争用的监视器
- 运行代理线程
- 设置线程本地存储
- 获取线程本地存储
jvmtiThreadInfo- 线程信息结构jvmtiMonitorStackDepthInfo- 监视器堆栈深度信息结构
jthread可以是对平台线程或虚拟线程的JNI引用。某些函数不支持虚拟线程,在使用虚拟线程的引用调用时会返回JVMTI_ERROR_UNSUPPORTED_OPERATION。
获取线程状态
获取线程的状态。线程的状态由以下层次问题的答案表示:jvmtiError GetThreadState(jvmtiEnv* env, jthread thread, jint* thread_state_ptr)- 存活?
- 未存活。
- 为什么不存活?
- 新的。
- 已终止 (
JVMTI_THREAD_STATE_TERMINATED)
- 为什么不存活?
- 存活 (
JVMTI_THREAD_STATE_ALIVE)- 暂停?
- 已暂停 (
JVMTI_THREAD_STATE_SUSPENDED) - 未暂停
- 已暂停 (
- 中断?
- 已中断 (
JVMTI_THREAD_STATE_INTERRUPTED) - 未中断。
- 已中断 (
- 在本地代码中?
- 在本地代码中 (
JVMTI_THREAD_STATE_IN_NATIVE) - 在Java编程语言代码中
- 在本地代码中 (
- 何种存活状态?
- 可运行 (
JVMTI_THREAD_STATE_RUNNABLE) - 阻塞 (
JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER) - 等待 (
JVMTI_THREAD_STATE_WAITING)- 定时等待?
- 为什么在等待?
- Object.wait (
JVMTI_THREAD_STATE_IN_OBJECT_WAIT) - LockSupport.park (
JVMTI_THREAD_STATE_PARKED) - 睡眠中 (
JVMTI_THREAD_STATE_SLEEPING)
- Object.wait (
- 可运行 (
- 暂停?
- 未存活。
以下定义用于将JVM TI线程状态转换为线程状态标志 常量 值 描述 JVMTI_THREAD_STATE_ALIVE0x0001 线程存活。如果线程是新的(未启动)或已终止,则为零。 JVMTI_THREAD_STATE_TERMINATED0x0002 线程已完成执行。 JVMTI_THREAD_STATE_RUNNABLE0x0004 线程可运行。 JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER0x0400 线程正在等待进入同步块/方法或在 Object.wait()后等待重新进入同步块/方法。JVMTI_THREAD_STATE_WAITING0x0080 线程正在等待。 JVMTI_THREAD_STATE_WAITING_INDEFINITELY0x0010 线程正在无超时等待。例如, Object.wait()。JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT0x0020 线程正在等待指定的最大等待时间。例如, Object.wait(long)。JVMTI_THREAD_STATE_SLEEPING0x0040 线程正在睡眠 -- Thread.sleep。JVMTI_THREAD_STATE_IN_OBJECT_WAIT0x0100 线程正在等待对象监视器 -- Object.wait。JVMTI_THREAD_STATE_PARKED0x0200 线程被停放,例如: LockSupport.park,LockSupport.parkUtil和LockSupport.parkNanos。正在睡眠的虚拟线程,在Thread.sleep中,可能设置此状态标志,而不是JVMTI_THREAD_STATE_SLEEPING。JVMTI_THREAD_STATE_SUSPENDED0x100000 线程被挂起,由挂起函数(例如 SuspendThread)挂起。如果设置了此位,其他位指的是挂起前的线程状态。JVMTI_THREAD_STATE_INTERRUPTED0x200000 线程已被中断。 JVMTI_THREAD_STATE_IN_NATIVE0x400000 线程在本地代码中 -- 即,正在运行尚未回调到VM或Java编程语言代码的本地方法。 运行VM编译的Java编程语言代码时不设置此标志,运行VM代码或VM支持代码时也不设置此标志。本地VM接口函数,如JNI和JVM TI函数,可能被实现为VM代码。 JVMTI_THREAD_STATE_VENDOR_10x10000000 由VM供应商定义。 JVMTI_THREAD_STATE_VENDOR_20x20000000 由VM供应商定义。 JVMTI_THREAD_STATE_VENDOR_30x40000000 由VM供应商定义。 java.lang.Thread.State风格状态。
规则 对于一个问题,答案不能多于一个,尽管可能没有答案(因为答案未知,不适用,或没有一个答案是正确的)。只有在封闭答案匹配时才设置答案。也就是说,不会同时设置以下任何一个:java.lang.Thread.State 转换掩码 常量 值 描述 JVMTI_JAVA_LANG_THREAD_STATE_MASKJVMTI_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_NEW0 java.lang.Thread.State.NEWJVMTI_JAVA_LANG_THREAD_STATE_TERMINATEDJVMTI_THREAD_STATE_TERMINATED java.lang.Thread.State.TERMINATEDJVMTI_JAVA_LANG_THREAD_STATE_RUNNABLEJVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE java.lang.Thread.State.RUNNABLEJVMTI_JAVA_LANG_THREAD_STATE_BLOCKEDJVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER java.lang.Thread.State.BLOCKEDJVMTI_JAVA_LANG_THREAD_STATE_WAITINGJVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY java.lang.Thread.State.WAITINGJVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITINGJVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT java.lang.Thread.State.TIMED_WAITINGJVMTI_THREAD_STATE_RUNNABLEJVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTERJVMTI_THREAD_STATE_WAITING
JVMTI_THREAD_STATE_ALIVE,J2SETM兼容的实现将始终设置其中一个)。如果设置了其中任何一个,封闭答案JVMTI_THREAD_STATE_ALIVE将被设置。不会同时设置以下任何一个:JVMTI_THREAD_STATE_WAITING_INDEFINITELYJVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT
JVMTI_THREAD_STATE_WAITING,J2SETM兼容的实现将始终设置其中一个)。如果设置了任何一个,封闭答案JVMTI_THREAD_STATE_ALIVE和JVMTI_THREAD_STATE_WAITING将被设置。不会同时设置以下任何一个:JVMTI_THREAD_STATE_IN_OBJECT_WAITJVMTI_THREAD_STATE_PARKEDJVMTI_THREAD_STATE_SLEEPING
JVMTI_THREAD_STATE_ALIVE和JVMTI_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_TERMINATED除非未设置JVMTI_THREAD_STATE_ALIVE,否则不能设置。 线程状态表示设计用于在将来的规范版本中进行扩展;线程状态值应相应地使用,即它们不应作为序数使用。大多数查询可以通过测试单个位来进行,如果希望在switch语句中使用,则应使用状态位与感兴趣的位进行掩码处理。所有未在上述定义的位均保留供将来使用。符合当前规范的VM必须将保留位设置为零。代理应忽略保留位--不应假定它们为零,因此不应包括在比较中。 示例 请注意,下面的值不包括保留和供应商位。 在synchronized语句中被阻塞的线程状态将是:
尚未启动的线程状态将是:JVMTI_THREAD_STATE_ALIVE + JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER
在0Object.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"; }能力所需功能参数 名称 类型 描述 threadjthread要查询的线程。如果 thread为NULL,则使用当前线程。thread_state_ptrjint*返回时,指向由线程状态标志定义的状态标志。代理传递指向 jint的指针。返回时,jint已设置。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_NULL_POINTERthread_state_ptr为NULL。
获取当前线程
获取当前线程。当前线程是调用该函数的Java编程语言线程。如果启用了jvmtiError GetCurrentThread(jvmtiEnv* env, jthread* thread_ptr)can_generate_early_vmstart功能并且尚未初始化java.lang.Thread类,则在启动阶段该函数可能返回NULL。 请注意,大多数接受线程作为参数的JVM TI函数将接受NULL表示当前线程。能力所需功能参数 名称 类型 描述 thread_ptrjthread*返回时,指向当前线程或 NULL。代理传递指向jthread的指针。返回时,jthread已设置。由thread_ptr返回的对象是JNI本地引用,必须进行管理。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERthread_ptr为NULL。
获取所有线程
获取附加到VM的所有活动平台线程。线程列表包括代理线程。不包括虚拟线程。如果jvmtiError GetAllThreads(jvmtiEnv* env, jint* threads_count_ptr, jthread** threads_ptr)java.lang.Thread.isAlive()返回true,即线程已启动但尚未终止。线程的范围由JVM的上下文确定 TI环境,通常是所有附加到VM的线程。能力所需功能参数 名称 类型 描述 threads_count_ptrjint*返回时,指向线程数。 代理传递一个指向 jint的指针。返回时,jint已设置。threads_ptrjthread**返回时,指向每个线程的引用数组。 代理传递一个指向 jthread*的指针。返回时,jthread*指向一个新分配的大小为*threads_count_ptr的数组。该数组应使用Deallocate释放。由threads_ptr返回的对象是JNI本地引用,必须进行管理。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERthreads_count_ptr为NULL。JVMTI_ERROR_NULL_POINTERthreads_ptr为NULL。
挂起线程
挂起指定的线程。如果指定了调用线程,则此函数将一直等到其他线程调用jvmtiError SuspendThread(jvmtiEnv* env, jthread thread)ResumeThread。如果线程当前已挂起,则此函数不执行任何操作并返回错误。能力可选功能:可能并非所有虚拟机都实现。必须具备以下功能(由GetCapabilities返回)才能使用此函数。能力 效果 can_suspend可以挂起和恢复线程 参数 名称 类型 描述 threadjthread要挂起的线程。如果 thread为NULL,则使用当前线程。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_suspend能力。使用AddCapabilities。JVMTI_ERROR_THREAD_SUSPENDED线程已经被挂起。 JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(尚未启动或已终止)。
挂起线程列表
挂起jvmtiError SuspendThreadList(jvmtiEnv* env, jint request_count, const jthread* request_list, jvmtiError* results)request_count指定的线程,这些线程在request_list数组中指定。线程可以使用ResumeThreadList或ResumeThread恢复。如果调用线程在request_list数组中指定,则此函数将一直等到其他线程恢复它。在挂起线程时遇到的错误将在results数组中返回,而不是在此函数的返回值中。当前已挂起的线程状态不会改变。能力可选功能:可能并非所有虚拟机都实现。必须具备以下功能(由GetCapabilities返回)才能使用此函数。能力 效果 can_suspend可以挂起和恢复线程 request_count个元素的数组。返回时,填充有相应线程挂起的错误代码。如果线程由此调用挂起,则错误代码将为JVMTI_ERROR_NONE。可能的错误代码是为SuspendThread指定的那些。 代理传入一个足够大以容纳request_count个jvmtiError元素的数组。数组元素的传入值将被忽略。返回时,元素被设置。参数 名称 类型 描述 request_countjint要挂起的线程数。 request_listconst jthread*要挂起的线程列表。 代理传入一个包含 request_count个jthread元素的数组。resultsjvmtiError*错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_suspend。请使用AddCapabilities。JVMTI_ERROR_ILLEGAL_ARGUMENTrequest_count小于0。JVMTI_ERROR_NULL_POINTERrequest_list为NULL。JVMTI_ERROR_NULL_POINTERresults为NULL。
暂停所有虚拟线程
暂停所有虚拟线程,除了例外列表中的线程。当前暂停的虚拟线程不会改变状态。可以使用jvmtiError SuspendAllVirtualThreads(jvmtiEnv* env, jint except_count, const jthread* except_list)ResumeAllVirtualThreads或ResumeThreadList或ResumeThread来恢复虚拟线程。能力可选功能:可能并非所有虚拟机都实现。必须满足以下能力(由GetCapabilities返回)才能使用此函数。能力 效果 can_suspend可以暂停和恢复线程 can_support_virtual_threads可以支持虚拟线程 参数名称 类型 描述 except_countjintexcept_listconst jthread *不暂停的线程列表。 代理传入一个包含 except_count个jthread元素的数组。如果except_list为NULL,且except_count == 0,则不是错误。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_suspend。请使用AddCapabilities。JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_support_virtual_threads。请使用AddCapabilities。JVMTI_ERROR_INVALID_THREADexcept_list中的线程无效。JVMTI_ERROR_NULL_POINTERexcept_list为NULL,且except_count非零。JVMTI_ERROR_ILLEGAL_ARGUMENTexcept_count小于0。
恢复线程
恢复一个暂停的线程。通过JVM暂停函数(例如jvmtiError ResumeThread(jvmtiEnv* env, jthread thread)SuspendThread)当前暂停的任何线程将恢复执行;其他线程不受影响。能力可选功能:可能并非所有虚拟机都实现。必须满足以下能力(由GetCapabilities返回)才能使用此函数。能力 效果 can_suspend可以暂停和恢复线程 参数名称 类型 描述 threadjthread要恢复的线程。 错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_suspend。请使用AddCapabilities。JVMTI_ERROR_THREAD_NOT_SUSPENDED线程未被暂停。 JVMTI_ERROR_INVALID_TYPESTATE线程的状态已被修改,现在不一致。 JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(尚未启动或已终止)。
恢复线程列表
恢复在jvmtiError ResumeThreadList(jvmtiEnv* env, jint request_count, const jthread* request_list, jvmtiError* results)request_count中指定的线程。request_list数组。通过JVM暂停函数(例如SuspendThreadList)暂停的任何线程将恢复执行。能力可选功能:可能并非所有虚拟机都实现了。必须满足以下能力(由GetCapabilities返回)才能使用此功能。能力 效果 can_suspend可以暂停和恢复线程 参数 名称 类型 描述 request_countjint要恢复的线程数。 request_listconst jthread*要恢复的线程。 代理传入一个包含 request_count个jthread元素的数组。resultsjvmtiError*代理提供的一个包含 request_count个元素的数组。返回时,填充有相应线程恢复的错误代码。如果线程是通过此调用暂停的,则错误代码将是JVMTI_ERROR_NONE。可能的错误代码是为ResumeThread指定的那些。 代理传入一个足够大以容纳request_count个jvmtiError元素的数组。数组元素的传入值将被忽略。返回时,这些元素将被设置。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_suspend。请使用AddCapabilities。JVMTI_ERROR_ILLEGAL_ARGUMENTrequest_count小于0。JVMTI_ERROR_NULL_POINTERrequest_list为NULL。JVMTI_ERROR_NULL_POINTERresults为NULL。
恢复所有虚拟线程
恢复除异常列表中的线程之外的所有虚拟线程。当前已恢复的虚拟线程状态不会改变。虚拟线程可以通过jvmtiError ResumeAllVirtualThreads(jvmtiEnv* env, jint except_count, const jthread* except_list)SuspendAllVirtualThreads或SuspendThreadList或SuspendThread来暂停。能力可选功能:可能并非所有虚拟机都实现了。必须满足以下能力(由GetCapabilities返回)才能使用此功能。能力 效果 can_suspend可以暂停和恢复线程 can_support_virtual_threads可以支持虚拟线程 参数 名称 类型 描述 except_countjintexcept_listconst jthread *不要恢复的线程列表。 代理传入一个包含 except_count个jthread元素的数组。如果except_list为NULL,且except_count == 0,则不是错误。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_suspend。请使用AddCapabilities。JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_support_virtual_threads。请使用AddCapabilities。JVMTI_ERROR_INVALID_THREADexcept_list中的线程无效。JVMTI_ERROR_NULL_POINTERexcept_list为NULL,且except_count非零。JVMTI_ERROR_ILLEGAL_ARGUMENTexcept_count小于0。
停止线程
向指定线程发送指定的异步异常。jvmtiError StopThread(jvmtiEnv* env, jthread thread, jobject exception)能力可选功能:可能并非所有虚拟机都实现了。必须满足以下能力(由GetCapabilities返回)才能使用此功能。能力 效果 can_signal_thread可以向线程发送停止或中断信号 参数 名称 类型 描述 threadjthread要停止的线程。当虚拟线程在事件中被暂停时, StopThread函数可用于向虚拟线程发送异步异常。实现可能支持在其他情况下向暂停的虚拟线程发送异步异常。exceptionjobject异步异常对象。 错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_signal_thread。请使用AddCapabilities。JVMTI_ERROR_THREAD_NOT_SUSPENDED线程是虚拟线程,未被暂停且不是当前线程。 JVMTI_ERROR_OPAQUE_FRAME线程是暂停的虚拟线程,实现无法从当前帧抛出异步异常。 JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread未启动或已终止。JVMTI_ERROR_INVALID_OBJECTexception不是对象。
中断线程
中断指定的线程(类似于jvmtiError InterruptThread(jvmtiEnv* env, jthread thread)java.lang.Thread.interrupt)。能力可选功能:可能不适用于所有虚拟机。必须通过GetCapabilities返回的以下能力为真才能使用此函数。能力 效果 can_signal_thread可以向线程发送停止或中断信号 参数 名称 类型 描述 threadjthread要中断的线程。 错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_signal_thread。请使用AddCapabilities。JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread未启动或已终止。
获取线程信息
获取线程信息。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- 线程信息结构字段 类型 描述 namechar*线程名称,编码为修改的 UTF-8字符串。 priorityjint线程优先级。参见线程优先级常量: jvmtiThreadPriority。虚拟线程的优先级始终为JVMTI_THREAD_NORM_PRIORITY。is_daemonjboolean这是守护线程吗?虚拟线程的守护状态始终为 JNI_TRUE。thread_groupjthreadGroup此线程所属的线程组。如果线程已终止,则为 NULL。context_class_loaderjobject与此线程关联的上下文类加载器。 参数 名称 类型 描述 threadjthread要查询的线程。如果 thread为NULL,则使用当前线程。info_ptrjvmtiThreadInfo*返回时,填充有描述指定线程的信息。 代理传递指向 jvmtiThreadInfo的指针。返回时,jvmtiThreadInfo已设置。在jvmtiThreadInfo的name字段中返回的指针是新分配的数组。应使用Deallocate释放数组。在jvmtiThreadInfo的thread_group字段中返回的对象是JNI本地引用,必须管理。在jvmtiThreadInfo的context_class_loader字段中返回的对象是JNI本地引用,必须管理。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_NULL_POINTERinfo_ptr为NULL。
获取拥有的监视器信息
获取指定线程拥有的监视器的信息。jvmtiError GetOwnedMonitorInfo(jvmtiEnv* env, jthread thread, jint* owned_monitor_count_ptr, jobject** owned_monitors_ptr)能力可选功能:可能并非所有虚拟机都实现了。必须使用此功能时,以下能力(由GetCapabilities返回)必须为真。能力 效果 can_get_owned_monitor_info可以获取有关监视器所有权的信息 - GetOwnedMonitorInfo参数 名称 类型 描述 threadjthread要查询的线程。如果 thread为NULL,则使用当前线程。owned_monitor_count_ptrjint*返回的监视器数量。 代理传递一个指向 jint的指针。返回时,jint已被设置。owned_monitors_ptrjobject**拥有的监视器数组。 代理传递一个指向 jobject*的指针。返回时,jobject*指向一个新分配的大小为*owned_monitor_count_ptr的数组。应使用Deallocate释放数组。由owned_monitors_ptr返回的对象是JNI本地引用,必须进行管理。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_get_owned_monitor_info。使用AddCapabilities。JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(未启动或已终止)。JVMTI_ERROR_NULL_POINTERowned_monitor_count_ptr为NULL。JVMTI_ERROR_NULL_POINTERowned_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)能力可选功能:可能并非所有虚拟机都实现了。必须使用此功能时,以下能力(由GetCapabilities返回)必须为真。能力 效果 can_get_owned_monitor_stack_depth_info可以获取具有堆栈深度的拥有监视器的信息 - GetOwnedMonitorStackDepthInfojvmtiMonitorStackDepthInfo- 监视器堆栈深度信息结构字段 类型 描述 monitorjobject拥有的监视器。 stack_depthjint堆栈深度。对应于堆栈帧函数中使用的堆栈深度。即,零是当前帧,一是调用当前帧的帧。如果实现无法确定堆栈深度(例如,对于通过JNI MonitorEnter获取的监视器),则为负一。参数 名称 类型 描述 threadjthread要查询的线程。如果 thread为NULL,则使用当前线程。monitor_info_count_ptrjint*返回的监视器数量。 代理传递一个指向 jint的指针。返回时,jint已被设置。monitor_info_ptrjvmtiMonitorStackDepthInfo **拥有的监视器深度信息数组。 代理传递一个指向 jvmtiMonitorStackDepthInfo*的指针。返回时,jvmtiMonitorStackDepthInfo*指向一个新分配的大小为*monitor_info_count_ptr的数组。应使用Deallocate释放数组。在jvmtiMonitorStackDepthInfo的monitor字段中返回的对象是JNI本地引用,必须进行管理。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_get_owned_monitor_stack_depth_info。使用AddCapabilities。JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(未启动或已终止)。JVMTI_ERROR_NULL_POINTERmonitor_info_count_ptr为NULL。JVMTI_ERROR_NULL_POINTERmonitor_info_ptr为NULL。
获取当前争用的监视器
获取指定线程正在等待进入或通过jvmtiError GetCurrentContendedMonitor(jvmtiEnv* env, jthread thread, jobject* monitor_ptr)java.lang.Object.wait重新获取其监视器的对象(如果有)。能力可选功能:可能并非所有虚拟机都实现了。要使用此功能,必须满足以下能力(由GetCapabilities返回)。能力 效果 can_get_current_contended_monitor可以 GetCurrentContendedMonitor参数 名称 类型 描述 threadjthread要查询的线程。如果 thread为NULL,则使用当前线程。monitor_ptrjobject*返回时,填充有当前争用的监视器,如果没有则为NULL。 代理传递一个指向 jobject的指针。返回时,jobject已被设置。由monitor_ptr返回的对象是JNI本地引用,必须进行管理。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_get_current_contended_monitor。使用AddCapabilities。JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(未启动或已终止)。JVMTI_ERROR_NULL_POINTERmonitor_ptr为NULL。
代理启动函数
代理提供的回调函数。此函数是使用typedef void (JNICALL *jvmtiStartFunction) (jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg);RunAgentThread启动的代理线程的入口点。参数 名称 类型 描述 jvmti_envjvmtiEnv *JVM TI环境。 jni_envJNIEnv *JNI环境。 argvoid *传递给 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调用创建线程对象。 为方便起见,提供以下常见线程优先级:
新线程以指定的线程优先级常量 常量 值 描述 JVMTI_THREAD_MIN_PRIORITY1 可能的最低线程优先级 JVMTI_THREAD_NORM_PRIORITY5 正常线程优先级 JVMTI_THREAD_MAX_PRIORITY10 可能的最高线程优先级 priority作为守护线程启动。如果启用,将发送一个ThreadStart事件。 由于线程已启动,因此此函数返回时线程将处于活动状态,除非线程立即终止。 线程的线程组被忽略--具体来说,线程不会添加到线程组中,并且线程不会在Java编程语言或JVM TI级别的线程组查询中看到。 线程对Java编程语言查询不可见,但包含在JVM TI查询中(例如,GetAllThreads和GetAllStackTraces)。 在执行proc时,新线程将附加到VM--请参阅JNI文档中的附加到VM。能力所需功能参数 名称 类型 描述 threadjthread要运行的线程。该 thread可能不是虚拟线程。否则,将返回错误代码JVMTI_ERROR_UNSUPPORTED_OPERATION。procjvmtiStartFunction启动函数。 argconst void *启动函数的参数。 代理传递一个指针。如果 arg为NULL,则将NULL传递给启动函数。priorityjint启动线程的优先级。可以使用 java.lang.Thread.setPriority允许的任何线程优先级,包括jvmtiThreadPriority中的优先级。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_PRIORITYpriority小于JVMTI_THREAD_MIN_PRIORITY或大于JVMTI_THREAD_MAX_PRIORITYJVMTI_ERROR_UNSUPPORTED_OPERATIONthread是虚拟线程。JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_NULL_POINTERproc为NULL。
设置线程本地存储
VM存储与每个环境-线程对关联的指针值。此指针值称为线程本地存储。除非使用此函数设置,否则此值为jvmtiError SetThreadLocalStorage(jvmtiEnv* env, jthread thread, const void* data)NULL。代理可以分配内存,其中存储特定于线程的信息。通过设置线程本地存储,然后可以使用GetThreadLocalStorage访问它。 代理调用此函数以设置JVM TI线程本地存储的值。JVM TI向代理提供一个指针大小的线程本地存储,可用于记录每个线程的信息。能力所需功能参数 名称 类型 描述 threadjthread存储到此线程。如果 thread为NULL,则使用当前线程。dataconst void *要输入到线程本地存储中的值。 代理传递一个指针。如果 data为NULL,则值设置为NULL。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(尚未启动或已终止)。
获取线程本地存储
代理调用此函数以获取JVM TI线程本地存储的值。jvmtiError GetThreadLocalStorage(jvmtiEnv* env, jthread thread, void** data_ptr)能力所需功能参数 名称 类型 描述 threadjthread从此线程检索。如果 thread为NULL,则使用当前线程。data_ptrvoid**通过此指针返回线程本地存储的值。如果未使用 SetThreadLocalStorage设置线程本地存储,则返回的指针为NULL。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(尚未启动或已终止)。JVMTI_ERROR_NULL_POINTERdata_ptr为NULL。
线程组
线程组函数: 线程组类型:jvmtiThreadGroupInfo- 线程组信息结构
获取顶级线程组
返回VM中所有顶级(无父级)线程组。jvmtiError GetTopThreadGroups(jvmtiEnv* env, jint* group_count_ptr, jthreadGroup** groups_ptr)能力所需功能参数 名称 类型 描述 group_count_ptrjint*返回时,指向顶级线程组的数量。 代理传递一个指向 jint的指针。返回时,jint已设置。groups_ptrjthreadGroup**返回时,指向顶级线程组数组的指针。 代理传递一个指向 jthreadGroup*的指针。返回时,jthreadGroup*指向一个新分配的大小为*group_count_ptr的数组。数组应使用Deallocate释放。由groups_ptr返回的对象是JNI本地引用,必须管理。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERgroup_count_ptr为NULL。JVMTI_ERROR_NULL_POINTERgroups_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结构的字段中。能力所需功能jvmtiThreadGroupInfo- 线程组信息结构字段 类型 描述 parentjthreadGroup父线程组。 namechar*线程组的名称,编码为修改后的UTF-8字符串。 max_priorityjint此线程组的最大优先级。 is_daemonjboolean这是一个守护线程组吗? 参数 名称 类型 描述 groupjthreadGroup要查询的线程组。 info_ptrjvmtiThreadGroupInfo*返回时,填充描述指定线程组的信息。 代理传递一个指向 jvmtiThreadGroupInfo的指针。返回时,jvmtiThreadGroupInfo已设置。在jvmtiThreadGroupInfo的parent字段中返回的对象是JNI本地引用,必须进行管理。在jvmtiThreadGroupInfo的name字段中返回的指针是新分配的数组。应使用Deallocate释放数组。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_THREAD_GROUPgroup不是线程组对象。JVMTI_ERROR_NULL_POINTERinfo_ptr为NULL。
获取线程组子项
获取此线程组中的活动平台线程和子线程组。此函数不返回虚拟线程。jvmtiError GetThreadGroupChildren(jvmtiEnv* env, jthreadGroup group, jint* thread_count_ptr, jthread** threads_ptr, jint* group_count_ptr, jthreadGroup** groups_ptr)能力所需功能参数 名称 类型 描述 groupjthreadGroup要查询的组。 thread_count_ptrjint*返回时,指向此线程组中活动线程的数量。 代理传递一个指向 jint的指针。返回时,jint已设置。threads_ptrjthread**返回时,指向此线程组中活动线程的数组。 代理传递一个指向 jthread*的指针。返回时,jthread*指向一个新分配的大小为*thread_count_ptr的数组。应使用Deallocate释放数组。由threads_ptr返回的对象是JNI本地引用,必须进行管理。group_count_ptrjint*返回时,指向子线程组的数量。 代理传递一个指向 jint的指针。返回时,jint已设置。groups_ptrjthreadGroup**返回时,指向子线程组的数组。 代理传递一个指向 jthreadGroup*的指针。返回时,jthreadGroup*指向一个新分配的大小为*group_count_ptr的数组。应使用Deallocate释放数组。由groups_ptr返回的对象是JNI本地引用,必须进行管理。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_THREAD_GROUPgroup不是线程组对象。JVMTI_ERROR_NULL_POINTERthread_count_ptr为NULL。JVMTI_ERROR_NULL_POINTERthreads_ptr为NULL。JVMTI_ERROR_NULL_POINTERgroup_count_ptr为NULL。JVMTI_ERROR_NULL_POINTERgroups_ptr为NULL。
堆栈帧
堆栈帧函数: 堆栈帧类型:jvmtiFrameInfo- 堆栈帧信息结构jvmtiStackInfo- 堆栈信息结构
main()和run()更深的帧。但是,这种呈现必须在使用堆栈帧或堆栈深度的所有JVM TI功能中保持一致。堆栈帧信息结构
返回有关堆栈帧的信息在此结构中。typedef struct { jmethodID method; jlocation location; } jvmtiFrameInfo;jvmtiFrameInfo- 堆栈帧信息结构字段 类型 描述 methodjmethodID在此帧中执行的方法。 locationjlocation在此帧中执行的指令的索引。如果帧正在执行本地方法,则为 -1。堆栈信息结构
返回一组堆栈帧的信息在此结构中。typedef struct { jthread thread; jint state; jvmtiFrameInfo* frame_buffer; jint frame_count; } jvmtiStackInfo;jvmtiStackInfo- 堆栈信息结构字段 类型 描述 threadjthread返回时,跟踪的线程。 statejint返回时,线程状态。参见 GetThreadState。frame_bufferjvmtiFrameInfo *返回时,此代理分配的缓冲区填充有堆栈帧信息。 frame_countjint返回时,填充到 frame_buffer中的记录数。这将是min(max_frame_count, stackDepth)。
获取堆栈跟踪
获取线程堆栈的信息。如果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("执行方法: %s", methodName); } }thread来调用此函数。GetLineNumberTable函数可用于将位置映射到行号。请注意,此映射可以延迟执行。能力所需功能jvmtiFrameInfo记录。参数 名称 类型 描述 threadjthread获取此线程的堆栈跟踪。如果 thread为NULL,则使用当前线程。start_depthjint从此深度开始检索帧。如果为非负数,则从当前帧计数,第一个检索的帧位于深度 start_depth处。例如,如果为零,则从当前帧开始;如果为一,则从当前帧的调用者开始;如果为二,则从当前帧的调用者的调用者开始;依此类推。如果为负数,则从最老帧下方计数,第一个检索的帧位于深度stackDepth+ start_depth处,其中stackDepth是堆栈上的帧数。例如,如果为负一,则只检索最老的帧;如果为负二,则从最老帧调用。max_frame_countjintframe_bufferjvmtiFrameInfo *返回时,此代理分配的缓冲区填充有堆栈帧信息。 代理传递一个足够大的数组,可以容纳 max_frame_count个jvmtiFrameInfo元素。数组元素的传入值将被忽略。返回时,设置了*count_ptr的元素。count_ptrjint*返回时,指向填充记录数的指针。对于非负的 start_depth,这将是min(max_frame_count, stackDepth- start_depth)。对于负的start_depth,这将是min(max_frame_count,-start_depth)。 代理传递一个指向jint的指针。返回时,设置了jint。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_ILLEGAL_ARGUMENTstart_depth为正且大于或等于stackDepth。或start_depth为负且小于-stackDepth。JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(尚未启动或已终止)。JVMTI_ERROR_ILLEGAL_ARGUMENTmax_frame_count小于0。JVMTI_ERROR_NULL_POINTERframe_buffer为NULL。JVMTI_ERROR_NULL_POINTERcount_ptr为NULL。
获取所有堆栈跟踪
获取附加到VM的所有活动平台线程的堆栈跟踪。列表包括代理线程的堆栈跟踪。不包括虚拟线程的堆栈跟踪。 如果jvmtiError GetAllStackTraces(jvmtiEnv* env, jint max_frame_count, jvmtiStackInfo** stack_info_ptr, jint* thread_count_ptr)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); } } /* 此处的Deallocate调用释放GetAllStackTraces分配的所有数据 */ err = (*jvmti)->Deallocate(jvmti, stack_info);能力所需功能代理程序传递一个指向 jint的指针。 返回时,jint已设置。参数 名称 类型 描述 max_frame_countjint每个线程检索的最大 jvmtiFrameInfo记录数。stack_info_ptrjvmtiStackInfo **返回时,此缓冲区填充了每个线程的堆栈信息。 thread_count_ptr确定jvmtiStackInfo记录的数量。 请注意,此缓冲区被分配为包括jvmtiStackInfo.frame_buffer指向的jvmtiFrameInfo缓冲区。 这些缓冲区不得单独释放。 代理程序传递一个指向jvmtiStackInfo*的指针。 返回时,jvmtiStackInfo*指向一个新分配的数组。 应使用Deallocate释放数组。jvmtiStackInfo字段thread中返回的对象是JNI本地引用,必须管理。thread_count_ptrjint*错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_ILLEGAL_ARGUMENTmax_frame_count小于0。JVMTI_ERROR_NULL_POINTERstack_info_ptr为NULL。JVMTI_ERROR_NULL_POINTERthread_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的示例。能力所需功能代理程序传入一个包含 thread_count个jthread元素的数组。jvmtiFrameInfo记录数。thread_count确定jvmtiStackInfo记录的数量。 请注意,此缓冲区被分配为包括jvmtiFrameInfo缓冲区指向的jvmtiStackInfo.frame_buffer。 这些缓冲区不得单独释放。 代理程序传递一个指向jvmtiStackInfo*的指针。 返回时,jvmtiStackInfo*指向一个新分配的大小为*thread_count的数组。 应使用Deallocate释放数组。jvmtiStackInfo字段thread中返回的对象是JNI本地引用,必须 管理。参数 名称 类型 描述 thread_countjintthread_listconst jthread*max_frame_countjintstack_info_ptrjvmtiStackInfo **错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_THREADthread_list中的一个元素不是线程对象。JVMTI_ERROR_ILLEGAL_ARGUMENTthread_count小于0。JVMTI_ERROR_NULL_POINTERthread_list为NULL。JVMTI_ERROR_ILLEGAL_ARGUMENTmax_frame_count小于0。JVMTI_ERROR_NULL_POINTERstack_info_ptr为NULL。
获取帧计数
获取指定线程调用堆栈中当前帧的数量。 如果为正在执行字节码的线程调用此函数(例如,不是当前线程且未暂停),则返回的信息是瞬时的。jvmtiError GetFrameCount(jvmtiEnv* env, jthread thread, jint* count_ptr)能力所需功能参数 名称 类型 描述 线程jthread要查询的线程。如果 thread为NULL,则使用当前线程。count_ptrjint*返回时,指向调用堆栈中帧的数量。 代理传递指向 jint的指针。返回时,jint已设置。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(未启动或已终止)。JVMTI_ERROR_NULL_POINTERcount_ptr为NULL。
弹出帧
弹出jvmtiError PopFrame(jvmtiEnv* env, jthread thread)thread的堆栈中的当前帧。弹出帧将您带回到上一个帧。当线程恢复时,线程的执行状态将重置为调用方法被调用之前的状态。也就是(使用Java™虚拟机规范术语):- 当前帧被丢弃,前一个帧变为当前帧
- 操作数栈被恢复--参数值被添加回去,如果调用不是
invokestatic,objectref也被添加回去 - Java虚拟机PC被恢复为调用指令的操作码
PopFrame和恢复线程之间,堆栈的状态是未定义的。要弹出第一个帧之外的帧,必须重复以下三个步骤:- 通过事件(步骤,断点,...)暂停线程
- 调用
PopFrame - 恢复线程
synchronized方法)和在被调用方法中进入的锁synchronized块被释放。注意:这不适用于本地锁或java.util.concurrent.locks锁。 最终块不会被执行。 对全局状态的更改未被处理,因此保持更改。 指定的线程必须被暂停或必须是当前线程。 被调用方法和调用方法都必须是非本地Java编程语言方法。 此函数不会生成任何JVM TI事件。能力可选功能:可能不适用于所有虚拟机。要使用此函数,必须返回以下功能(由GetCapabilities返回)。功能 效果 can_pop_frame可以从堆栈中弹出帧 - PopFrame参数 名称 类型 描述 线程jthread要弹出当前帧的线程。当虚拟线程在事件中被暂停时,可以使用 PopFrame函数弹出虚拟线程的当前帧。实现可能支持在其他情况下弹出暂停的虚拟线程的当前帧。错误此函数返回通用错误或以下错误之一错误 描述 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_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(未启动或已终止)。
获取帧位置
对于Java编程语言帧,返回当前执行指令的位置。jvmtiError GetFrameLocation(jvmtiEnv* env, jthread thread, jint depth, jmethodID* method_ptr, jlocation* location_ptr)能力所需功能参数 名称 类型 描述 threadjthread要查询的帧的线程。如果 thread为NULL,则使用当前线程。depthjint要查询的帧的深度。 method_ptrjmethodID*返回时,指向当前位置的方法。 代理传递指向 jmethodID的指针。返回时,jmethodID已设置。location_ptrjlocation*返回时,指向当前执行指令的索引。如果帧正在执行本地方法,则设置为 -1。 代理传递指向jlocation的指针。返回时,jlocation已设置。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread未启动或已终止。JVMTI_ERROR_ILLEGAL_ARGUMENTdepth小于零。JVMTI_ERROR_NO_MORE_FRAMES指定深度处没有堆栈帧。 JVMTI_ERROR_NULL_POINTERmethod_ptr为NULL。JVMTI_ERROR_NULL_POINTERlocation_ptr为NULL。
通知帧弹出
当当前位于jvmtiError NotifyFramePop(jvmtiEnv* env, jthread thread, jint depth)depth的帧从堆栈中弹出时,生成一个FramePop事件。有关详细信息,请参阅FramePop事件。只有对应于非本地Java编程语言方法的帧才能接收通知。 指定的线程必须被挂起或必须是当前线程。能力可选功能:可能未在所有虚拟机中实现。必须通过GetCapabilities返回的以下能力为真才能使用此函数。能力 效果 can_generate_frame_pop_events可以设置并获取 FramePop事件参数 名称 类型 描述 threadjthread将生成帧弹出事件的帧的线程。如果 thread为NULL,则使用当前线程。depthjint将生成帧弹出事件的帧的深度。 错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_generate_frame_pop_events。使用AddCapabilities。JVMTI_ERROR_OPAQUE_FRAME在 depth处的帧正在执行本地方法。JVMTI_ERROR_THREAD_NOT_SUSPENDED线程未被挂起且不是当前线程。 JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread未启动或已终止。JVMTI_ERROR_ILLEGAL_ARGUMENTdepth小于零。JVMTI_ERROR_NO_MORE_FRAMES指定深度处没有堆栈帧。
强制提前返回
强制提前返回函数: 这些函数允许代理强制从当前帧返回。指定的线程必须被挂起或必须是当前线程。这些函数可用于在事件挂起时强制从虚拟线程的当前帧返回。实现可能支持在其他情况下强制从挂起的虚拟线程的当前帧返回。将提前返回的方法称为 被调用方法。被调用方法是在调用函数时指定线程的当前方法(由 Java™虚拟机规范,第3.6章 定义)。 返回发生在此线程上的Java编程语言代码的执行恢复时。在调用这些函数和线程执行恢复之间,堆栈的状态是未定义的。 被调用方法中不会执行更多指令。特别地,finally块不会执行。注意:这可能导致应用程序中的不一致状态。 通过调用被调用方法获取的锁(如果它是一个synchronized方法)以及在被调用方法内部进入的synchronized块获取的锁将被释放。注意:这不适用于本地锁或java.util.concurrent.locks锁。 事件,例如MethodExit,将像在正常返回时生成。 被调用方法必须是非本地Java编程语言方法。在堆栈上只有一个帧的线程上强制返回会导致在恢复时线程退出。
强制提前返回 - 对象
此函数可用于从结果类型为jvmtiError ForceEarlyReturnObject(jvmtiEnv* env, jthread thread, jobject value)Object或Object的子类的方法返回。能力可选功能:可能并非所有虚拟机都实现了。必须满足以下能力(由GetCapabilities返回)才能使用此功能。能力 效果 can_force_early_return可以从方法中提前返回,如Force Early Return类别中所述。 参数 名称 类型 描述 threadjthread要提前返回其当前帧的线程。如果 thread为NULL,则使用当前线程。valuejobject被调用帧的返回值。一个对象或 NULL。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_force_early_return能力。请使用AddCapabilities。JVMTI_ERROR_OPAQUE_FRAME尝试从对应于本地方法的帧中提前返回。线程是一个暂停的虚拟线程,实现无法强制其当前帧返回。或者实现无法在此帧上提供此功能。 JVMTI_ERROR_TYPE_MISMATCH被调用方法的结果类型不是 Object或Object的子类。JVMTI_ERROR_TYPE_MISMATCH提供的 value与被调用方法的结果类型不兼容。JVMTI_ERROR_THREAD_NOT_SUSPENDED线程未暂停且不是当前线程。 JVMTI_ERROR_NO_MORE_FRAMES调用栈上没有更多帧。 JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(尚未启动或已终止)。JVMTI_ERROR_INVALID_OBJECTvalue不是对象。
提前返回 - 整数
此函数可用于从结果类型为jvmtiError ForceEarlyReturnInt(jvmtiEnv* env, jthread thread, jint value)int、short、char、byte或boolean的方法中返回。能力可选功能:可能并非所有虚拟机都实现了。必须满足以下能力(由GetCapabilities返回)才能使用此功能。能力 效果 can_force_early_return可以从方法中提前返回,如Force Early Return类别中所述。 参数 名称 类型 描述 threadjthread要提前返回其当前帧的线程。如果 thread为NULL,则使用当前线程。valuejint被调用帧的返回值。 错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_force_early_return能力。请使用AddCapabilities。JVMTI_ERROR_OPAQUE_FRAME尝试从对应于本地方法的帧中提前返回。线程是一个暂停的虚拟线程,实现无法强制其当前帧返回。或者实现无法在此帧上提供此功能。 JVMTI_ERROR_TYPE_MISMATCH被调用方法的结果类型不是 int、short、char、byte或boolean。JVMTI_ERROR_THREAD_NOT_SUSPENDED线程未暂停且不是当前线程。 JVMTI_ERROR_NO_MORE_FRAMES调用栈上没有更多帧。 JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(尚未启动或已终止)。
提前返回 - 长整型
此函数可用于从结果类型为jvmtiError ForceEarlyReturnLong(jvmtiEnv* env, jthread thread, jlong value)long的方法中返回。能力可选功能:可能并非所有虚拟机都实现了。必须满足以下能力(由GetCapabilities返回)才能使用此功能。能力 效果 can_force_early_return可以从方法中提前返回,如Force Early Return类别中所述。 参数 名称 类型 描述 threadjthread要提前返回其当前帧的线程。如果 thread为NULL,则使用当前线程。valuejlong被调用帧的返回值。 错误此函数返回一个通用错误或以下错误之一错误 描述 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_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(未启动或已终止)。
强制提前返回 - 浮点数
此函数可用于从结果类型为jvmtiError ForceEarlyReturnFloat(jvmtiEnv* env, jthread thread, jfloat value)float的方法中返回。能力可选功能:可能不适用于所有虚拟机。必须使用此功能时,以下能力(由GetCapabilities返回)必须为真。能力 效果 can_force_early_return可以从方法中提前返回,如“强制提前返回”类别中描述的。 参数 名称 类型 描述 threadjthread要提前返回其当前帧的线程。如果 thread为NULL,则使用当前线程。valuejfloat调用帧的返回值。 错误此函数返回一个通用错误或以下错误之一错误 描述 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_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(未启动或已终止)。
强制提前返回 - 双精度浮点数
此函数可用于从结果类型为jvmtiError ForceEarlyReturnDouble(jvmtiEnv* env, jthread thread, jdouble value)double的方法中返回。能力可选功能:可能不适用于所有虚拟机。必须使用此功能时,以下能力(由GetCapabilities返回)必须为真。能力 效果 can_force_early_return可以从方法中提前返回,如“强制提前返回”类别中描述的。 参数 名称 类型 描述 threadjthread要提前返回其当前帧的线程。如果 thread为NULL,则使用当前线程。valuejdouble调用帧的返回值。 错误此函数返回一个通用错误或以下错误之一错误 描述 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_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(未启动或已终止)。
强制提前返回 - 无返回值
此函数可用于从没有结果类型的方法返回。也就是说,被调用的方法必须声明为jvmtiError ForceEarlyReturnVoid(jvmtiEnv* env, jthread thread)void。能力可选功能:可能并非所有虚拟机都实现了。必须通过GetCapabilities返回的以下能力为真才能使用此函数。能力 效果 can_force_early_return可以从方法中提前返回,如“强制提前返回”类别中所述。 参数 名称 类型 描述 threadjthread要提前返回其当前帧的线程。如果 thread为NULL,则使用当前线程。错误此函数返回一个通用错误或以下错误之一错误 描述 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_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(尚未启动或已终止)。
堆
堆函数: 堆函数类型: 堆类型:jvmtiHeapReferenceKind- 堆引用枚举jvmtiPrimitiveType- 基本类型枚举jvmtiHeapReferenceInfoField- 字段引用的引用信息结构jvmtiHeapReferenceInfoArray- 数组引用的引用信息结构jvmtiHeapReferenceInfoConstantPool- 常量池引用的引用信息结构jvmtiHeapReferenceInfoStackLocal- 局部变量引用的引用信息结构jvmtiHeapReferenceInfoJniLocal- JNI本地引用的引用信息结构jvmtiHeapReferenceInfoReserved- 其他引用的引用信息结构jvmtiHeapReferenceInfo- 引用信息结构jvmtiHeapCallbacks- 堆回调函数结构
对象标记
标记是与对象关联的值。标记由代理使用SetTag函数显式设置,或者由诸如jvmtiHeapIterationCallback之类的回调函数设置。 标记是局部于环境的;也就是说,一个环境的标记在另一个环境中不可见。 标记是jlong值,可以简单地用于标记对象或存储指向更详细信息的指针。未标记的对象的标记为零。将标记设置为零会使对象未标记。堆回调函数
遍历堆并递归跟踪对象引用的堆函数使用代理提供的回调函数来传递信息。 这些堆回调函数必须遵守以下限制--这些回调不能使用JNI函数。这些回调不能使用JVM TI函数,除非明确允许使用的回调安全函数(请参阅原始监视器、内存管理和环境本地存储函数)。 实现可以在内部线程或调用迭代函数的线程上调用回调。堆回调是单线程的--一次只会调用一个回调。 堆过滤标志可用于基于对象的标记状态或其类来阻止报告。如果未设置任何标志(jint为零),则不会过滤对象。
堆访问控制标志由堆回调返回,可用于中止迭代。对于堆引用回调,还可用于修剪遍历引用图(未设置堆过滤标志 常量 值 描述 JVMTI_HEAP_FILTER_TAGGED0x4 过滤已标记的对象。已标记的对象不包括在内。 JVMTI_HEAP_FILTER_UNTAGGED0x8 过滤未标记的对象。未标记的对象不包括在内。 JVMTI_HEAP_FILTER_CLASS_TAGGED0x10 过滤具有已标记类的对象。类已标记的对象不包括在内。 JVMTI_HEAP_FILTER_CLASS_UNTAGGED0x20 过滤具有未标记类的对象。类未标记的对象不包括在内。 JVMTI_VISIT_OBJECTS)。
堆引用枚举由堆引用回调和基本字段回调提供,用于描述正在报告的引用类型。堆访问控制标志 常量 值 描述 JVMTI_VISIT_OBJECTS0x100 如果我们正在访问一个对象,并且此回调是由 FollowReferences发起的,则遍历此对象的引用。否则忽略。JVMTI_VISIT_ABORT0x8000 中止迭代。忽略所有其他位。
原始类型的单字符类型描述符的定义。堆引用枚举( jvmtiHeapReferenceKind)常量 值 描述 JVMTI_HEAP_REFERENCE_CLASS1 从对象到其类的引用。 JVMTI_HEAP_REFERENCE_FIELD2 从对象到其实例字段值的引用。 JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT3 从数组到其元素的引用。 JVMTI_HEAP_REFERENCE_CLASS_LOADER4 从类到其类加载器的引用。 JVMTI_HEAP_REFERENCE_SIGNERS5 从类到其签名者数组的引用。 JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN6 从类到其保护域的引用。 JVMTI_HEAP_REFERENCE_INTERFACE7 从类到其接口之一的引用。注意:接口是通过常量池引用定义的,因此引用的接口也可能使用 JVMTI_HEAP_REFERENCE_CONSTANT_POOL引用类型报告。JVMTI_HEAP_REFERENCE_STATIC_FIELD8 从类到其静态字段值的引用。 JVMTI_HEAP_REFERENCE_CONSTANT_POOL9 从类到常量池中的一个已解析条目的引用。 JVMTI_HEAP_REFERENCE_SUPERCLASS10 从类到其超类的引用。如果超类是 java.lang.Object,则不发送回调。注意:加载的类通过常量池引用定义超类,因此引用的超类也可能使用JVMTI_HEAP_REFERENCE_CONSTANT_POOL引用类型报告。JVMTI_HEAP_REFERENCE_JNI_GLOBAL21 堆根引用:JNI 全局引用。 JVMTI_HEAP_REFERENCE_SYSTEM_CLASS22 堆根引用:系统类。 JVMTI_HEAP_REFERENCE_MONITOR23 堆根引用:监视器。 JVMTI_HEAP_REFERENCE_STACK_LOCAL24 线程堆栈上的局部变量。 JVMTI_HEAP_REFERENCE_JNI_LOCAL25 JNI 本地引用。 JVMTI_HEAP_REFERENCE_THREAD26 堆根引用:线程。 JVMTI_HEAP_REFERENCE_OTHER27 堆根引用:其他堆根引用。 原始类型枚举( jvmtiPrimitiveType)常量 值 描述 JVMTI_PRIMITIVE_TYPE_BOOLEAN90 'Z' - Java 编程语言 boolean- JNIjbooleanJVMTI_PRIMITIVE_TYPE_BYTE66 'B' - Java 编程语言 byte- JNIjbyteJVMTI_PRIMITIVE_TYPE_CHAR67 'C' - Java 编程语言 char- JNIjcharJVMTI_PRIMITIVE_TYPE_SHORT83 'S' - Java 编程语言 short- JNIjshortJVMTI_PRIMITIVE_TYPE_INT73 'I' - Java 编程语言 int- JNIjintJVMTI_PRIMITIVE_TYPE_LONG74 'J' - Java 编程语言 long- JNIjlongJVMTI_PRIMITIVE_TYPE_FLOAT70 'F' - Java 编程语言 float- JNIjfloatJVMTI_PRIMITIVE_TYPE_DOUBLE68 'D' - Java 编程语言 double- JNIjdouble字段引用的引用信息结构
为字段引用返回的引用信息JVMTI_HEAP_REFERENCE_FIELD和JVMTI_HEAP_REFERENCE_STATIC_FIELD引用。typedef struct { jint index; } jvmtiHeapReferenceInfoField;jvmtiHeapReferenceInfoField- 字段引用信息结构字段 类型 描述 indexjint对于 JVMTI_HEAP_REFERENCE_FIELD,引用对象不是类或接口。在这种情况下,index是引用对象类中字段的索引。这个类以下简称为C。 对于JVMTI_HEAP_REFERENCE_STATIC_FIELD,引用对象是一个类(以下简称为C)或一个接口(以下简称为I)。在这种情况下,index是该类或接口中字段的索引。 如果引用对象不是接口,则字段索引确定如下:- 列出C及其超类中的所有字段,从
java.lang.Object的所有字段开始,以C的所有字段结束。 - 在此列表中,按照
GetClassFields返回的顺序放置给定类的字段。 - 为此列表中的字段分配索引n,n+1,...,按顺序排列,其中n是C实现的所有接口中字段的计数。注意,C实现其超类直接实现的所有接口,以及这些接口的所有超接口。
- 列出在I中直接声明的字段。
- 在此列表中,按照
GetClassFields返回的顺序放置字段。 - 为此列表中的字段分配索引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; }C1上调用GetClassFields返回C1的字段顺序为:a,b;C2的字段按顺序返回为:q,r。类C1的实例将具有以下字段索引:
类字段 索引 描述 a 2 C1实现的接口中字段的计数为两个(n=2):I0的p和I1的x。b 3 后续索引。 C1将具有相同的字段索引。 类C2的实例将具有以下字段索引:
类字段 索引 描述 a 3 C2实现的接口中字段的计数为三个(n=3):I0的p,I1的x和I2的y(C2的一个接口)。注意,I0的字段p只包含一次。b 4 相对于"a"的后续索引。 q 5 相对于"b"的后续索引。 r 6 相对于"q"的后续索引。 C2将具有相同的字段索引。请注意,字段的索引可能因查看它的对象而异,例如上面的字段"a"。还请注意:并非所有字段索引都可能从回调中可见,但出于说明目的,所有索引都显示出来。 接口I1将具有以下字段索引:字段 索引 描述 x 1 I1的所有超接口中字段的计数为一个(n=1):I0的p。数组引用信息结构
返回JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT引用的引用信息。typedef struct { jint index; } jvmtiHeapReferenceInfoArray;jvmtiHeapReferenceInfoArray- 数组引用信息结构字段 类型 描述 indexjint数组索引。 常量池引用信息结构
返回JVMTI_HEAP_REFERENCE_CONSTANT_POOL引用的引用信息。typedef struct { jint index; } jvmtiHeapReferenceInfoConstantPool;jvmtiHeapReferenceInfoConstantPool- 常量池引用信息结构字段 类型 描述 indexjint类的常量池中的索引。请参阅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- 本地变量引用信息结构字段 类型 描述 thread_tagjlong与此堆栈对应的线程标记,如果未标记则为零。 thread_idjlong与此堆栈对应的线程的唯一线程ID。 depthjint帧的深度。 methodjmethodID在此帧中执行的方法。 locationjlocation此帧中当前执行的位置。 slotjint本地变量的槽号。 JNI本地引用信息结构
返回JVMTI_HEAP_REFERENCE_JNI_LOCAL引用的引用信息。typedef struct { jlong thread_tag; jlong thread_id; jint depth; jmethodID method; } jvmtiHeapReferenceInfoJniLocal;jvmtiHeapReferenceInfoJniLocal- JNI本地引用的引用信息结构字段 类型 描述 thread_tagjlong与此堆栈对应的线程标记,如果未标记则为零。 thread_idjlong与此堆栈对应的线程的唯一线程ID。 depthjint帧的深度。 methodjmethodID在此帧中执行的方法。 其他引用的引用信息结构
其他引用返回的引用信息。typedef struct { jlong reserved1; jlong reserved2; jlong reserved3; jlong reserved4; jlong reserved5; jlong reserved6; jlong reserved7; jlong reserved8; } jvmtiHeapReferenceInfoReserved;jvmtiHeapReferenceInfoReserved- 其他引用的引用信息结构字段 类型 描述 reserved1jlong保留以供将来使用。 reserved2jlong保留以供将来使用。 reserved3jlong保留以供将来使用。 reserved4jlong保留以供将来使用。 reserved5jlong保留以供将来使用。 reserved6jlong保留以供将来使用。 reserved7jlong保留以供将来使用。 reserved8jlong保留以供将来使用。 引用信息结构
有关引用者返回的信息。表示各种引用信息的联合。typedef union { jvmtiHeapReferenceInfoField field; jvmtiHeapReferenceInfoArray array; jvmtiHeapReferenceInfoConstantPool constant_pool; jvmtiHeapReferenceInfoStackLocal stack_local; jvmtiHeapReferenceInfoJniLocal jni_local; jvmtiHeapReferenceInfoReserved other; } jvmtiHeapReferenceInfo;jvmtiHeapReferenceInfo- 引用信息结构字段 类型 描述 fieldjvmtiHeapReferenceInfoFieldJVMTI_HEAP_REFERENCE_FIELD和JVMTI_HEAP_REFERENCE_STATIC_FIELD引用的引用者信息。arrayjvmtiHeapReferenceInfoArrayJVMTI_HEAP_REFERENCE_ARRAY_ELEMENT引用的引用者信息。constant_pooljvmtiHeapReferenceInfoConstantPoolJVMTI_HEAP_REFERENCE_CONSTANT_POOL引用的引用者信息。stack_localjvmtiHeapReferenceInfoStackLocalJVMTI_HEAP_REFERENCE_STACK_LOCAL引用的引用者信息。jni_localjvmtiHeapReferenceInfoJniLocalJVMTI_HEAP_REFERENCE_JNI_LOCAL引用的引用者信息。otherjvmtiHeapReferenceInfoReserved保留以供将来使用。 堆回调函数结构
typedef struct { jvmtiHeapIterationCallback 堆迭代回调; jvmtiHeapReferenceCallback 堆引用回调; jvmtiPrimitiveFieldCallback 原始字段回调; jvmtiArrayPrimitiveValueCallback 数组原始值回调; jvmtiStringPrimitiveValueCallback 字符串原始值回调; jvmtiReservedCallback 保留5; jvmtiReservedCallback 保留6; jvmtiReservedCallback 保留7; jvmtiReservedCallback 保留8; jvmtiReservedCallback 保留9; jvmtiReservedCallback 保留10; jvmtiReservedCallback 保留11; jvmtiReservedCallback 保留12; jvmtiReservedCallback 保留13; jvmtiReservedCallback 保留14; jvmtiReservedCallback 保留15; } jvmtiHeapCallbacks;jvmtiHeapCallbacks- 堆回调函数结构字段 类型 描述 heap_iteration_callbackjvmtiHeapIterationCallback用于描述堆中对象的回调。被 IterateThroughHeap函数调用,被FollowReferences函数忽略。heap_reference_callbackjvmtiHeapReferenceCallback用于描述对象引用的回调。被 FollowReferences函数调用,被IterateThroughHeap函数忽略。primitive_field_callbackjvmtiPrimitiveFieldCallback用于描述原始字段的回调。 array_primitive_value_callbackjvmtiArrayPrimitiveValueCallback用于描述原始值数组的回调。 string_primitive_value_callbackjvmtiStringPrimitiveValueCallback用于描述字符串值的回调。 reserved5jvmtiReservedCallback保留以供将来使用。 reserved6jvmtiReservedCallback保留以供将来使用。 reserved7jvmtiReservedCallback保留以供将来使用。 reserved8jvmtiReservedCallback保留以供将来使用。 reserved9jvmtiReservedCallback保留以供将来使用。 reserved10jvmtiReservedCallback保留以供将来使用。 reserved11jvmtiReservedCallback保留以供将来使用。 reserved12jvmtiReservedCallback保留以供将来使用。 reserved13jvmtiReservedCallback保留以供将来使用。 reserved14jvmtiReservedCallback保留以供将来使用。 reserved15jvmtiReservedCallback保留以供将来使用。 理由:堆转储功能(下文)使用每个对象的回调。虽然似乎缓冲区方法会提供更好的吞吐量,但测试结果并未显示这种情况——可能是由于内存引用的局部性或数组访问开销。
堆迭代回调
代理提供的回调函数。描述(但不传入)堆中的对象。 此函数应返回所需访问控制标志的位向量。这将决定是否应中止整个迭代(typedef jint (JNICALL *jvmtiHeapIterationCallback) (jlong class_tag, jlong size, jlong* tag_ptr, jint length, void* user_data);JVMTI_VISIT_OBJECTS标志被忽略)。 请参阅堆回调函数限制。class_tag是与java.lang.Class关联的标记(如果java.lang.Class未标记则为零)。参数 名称 类型 描述 class_tagjlongsizejlong对象的大小(以字节为单位)。参见 GetObjectSize。tag_ptrjlong*对象标记值,如果对象未标记则为零。要将与对象关联的标记值设置为代理设置的 jlong指向的值。lengthjint如果此对象是数组,则为数组的长度。否则为负一(-1)。 user_datavoid*传入迭代函数的用户提供的数据。
堆引用回调
代理提供的回调函数。描述从一个对象或VM(引用者)到另一个对象(被引用对象)或堆根到被引用对象的引用。 此函数应返回所需的访问控制标志的位向量。这将决定是否应访问被引用对象引用的对象,或者是否应中止整个迭代。 请参阅堆回调函数限制。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);参数 名称 类型 描述 reference_kindjvmtiHeapReferenceKind引用的类型。 reference_infoconst jvmtiHeapReferenceInfo *关于引用的详细信息。当reference_kind为 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_tagjlong被引用对象的类标记(如果类未标记则为零)。如果被引用对象表示运行时类,则 class_tag是与java.lang.Class关联的标记(如果java.lang.Class未标记则为零)。referrer_class_tagjlong引用者对象的类标记(如果类未标记或被引用对象是堆根则为零)。如果引用者对象表示运行时类,则 referrer_class_tag是与java.lang.Class关联的标记(如果java.lang.Class未标记则为零)。sizejlong被引用对象的大小(以字节为单位)。参见 GetObjectSize。tag_ptrjlong*指向被引用对象标记值的指针,如果对象未标记则为零。要将与对象关联的标记值设置为代理设置的参数指向的 jlong。referrer_tag_ptrjlong*指向引用者对象的标记的指针,如果引用者对象未标记则指向零。如果引用者不是对象(即,此回调报告堆根),则为 NULL。要将与引用者对象关联的标记值设置为代理设置的参数指向的jlong。如果此回调报告对象自身的引用,则referrer_tag_ptr == tag_ptr。lengthjint如果此对象是数组,则为数组的长度。否则为负一(-1)。 user_datavoid*传递给迭代函数的用户提供的数据。
原始字段回调
代理提供的回调函数,描述对象(该对象)的原始字段。原始字段是其类型为原始类型的字段。如果对象是类,则此回调将描述静态字段,否则将描述实例字段。 此函数应返回所需的访问控制标志的位向量。这将决定是否应中止整个迭代(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标志将被忽略)。 请参阅堆回调函数限制。参数 名称 类型 描述 kindjvmtiHeapReferenceKind字段的类型 -- 实例或静态( JVMTI_HEAP_REFERENCE_FIELD或JVMTI_HEAP_REFERENCE_STATIC_FIELD)。infoconst jvmtiHeapReferenceInfo *哪个字段(字段索引)。 object_class_tagjlong对象的类的标记(如果类未标记则为零)。如果对象表示运行时类,则 object_class_tag是与java.lang.Class关联的标记(如果java.lang.Class未标记则为零)。object_tag_ptrjlong*指向对象标记的指针,如果对象未标记则为零。要将与对象关联的标记值设置为代理设置的参数指向的 jlong。valuejvalue字段的值。 value_typejvmtiPrimitiveType字段的类型。 user_datavoid*传递给迭代函数的用户提供的数据。
数组原始值回调
代理提供的回调函数。描述原始类型数组中的值。 此函数应返回所需的访问控制标志的位向量。这将决定是否应中止整个迭代(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标志将被忽略)。 请参阅堆回调函数限制。参数 名称 类型 描述 class_tagjlong数组对象的类标记(如果类未标记则为零)。 sizejlong数组的大小(以字节为单位)。参见 GetObjectSize。tag_ptrjlong*指向数组对象标记的指针,如果对象未标记则为零。要将与对象关联的标记值设置为代理设置的参数指向的 jlong。element_countjint原始数组的长度。 element_typejvmtiPrimitiveType数组元素的类型。 elementsconst void*数组中元素的打包数组,每个元素为 element_type大小的element_count项。user_datavoid*传递给迭代函数的用户提供的数据。
字符串原始值回调
代理提供的回调函数。描述了java.lang.String的值。 此函数应返回所需访问控制标志的位向量。这将决定是否应中止整个迭代(忽略typedef jint (JNICALL *jvmtiStringPrimitiveValueCallback) (jlong class_tag, jlong size, jlong* tag_ptr, const jchar* value, jint value_length, void* user_data);JVMTI_VISIT_OBJECTS标志)。 请参阅堆回调函数限制。参数 名称 类型 描述 class_tagjlongString类的类标记(如果类未标记,则为零)。 sizejlong字符串的大小(以字节为单位)。请参阅 GetObjectSize。tag_ptrjlong*指向String对象的标记,如果对象未标记则为零。要设置与对象关联的标记值,代理设置参数指向的 jlong。valueconst jchar*String的值,编码为Unicode字符串。 value_lengthjint字符串的长度。长度等于字符串中的16位Unicode字符数。 user_datavoid*传递给迭代函数的用户提供的数据。
保留供将来使用的回调函数
占位符 -- 保留供将来使用。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的引用被遍历时,当从堆根到B的引用被遍历时,或者当B被指定为initial_object时,则称B为已访问。从A到B的引用直到A被访问之前不会被遍历。引用按照遍历引用的顺序报告。对象引用通过调用代理提供的回调函数jvmtiHeapReferenceCallback来报告。在从A到B的引用中,A被称为引用者,B被称为被引用者。对于每个引用者的引用,回调仅调用一次;即使存在引用循环或多个路径到引用者,这也是正确的。引用者和被引用者之间可能存在多个引用,每个引用都会被报告。这些引用可以通过检查reference_kind和reference_info参数来区分jvmtiHeapReferenceCallback回调。 此函数报告对象引用的Java编程语言视图,而不是虚拟机实现视图。当它们非空时,将报告以下对象引用:- 实例对象报告对每个非基本实例字段的引用(包括继承字段)。
- 实例对象报告对对象类型(类)的引用。
- 类报告对超类和直接实现/扩展接口的引用。
- 类报告对类加载器、保护域、签名者和常量池中的已解析条目的引用。
- 类报告对每个直接声明的非基本静态字段的引用。
- 数组报告对数组类型(类)和每个数组元素的引用。
- 基本数组报告对数组类型的引用。
jvmtiArrayPrimitiveValueCallback或jvmtiStringPrimitiveValueCallback来报告。在访问具有该字段的对象后,将报告原始字段;通过调用代理提供的回调函数jvmtiPrimitiveFieldCallback来报告。 提供回调或为NULL仅确定是否调用回调,不影响访问哪些对象,也不影响是否调用其他回调。但是,由jvmtiHeapReferenceCallback返回的访问控制标志确定当前对象引用的对象是否被访问。由此函数的参数heap_filter和klass提供的堆过滤器标志不控制哪些对象被访问,但它们控制哪些对象和原始值由回调报告。例如,如果设置的唯一回调是array_primitive_value_callback,并且klass设置为字节类的数组,则只会报告字节数组。下表总结了这一点:
在执行此函数期间,堆的状态不会改变:不会分配对象,不会进行垃圾回收,并且对象的状态(包括保存的值)不会改变。因此,执行Java编程语言代码的线程、尝试恢复Java编程语言代码执行的线程以及尝试执行JNI函数的线程通常会被阻塞。控制访问的对象 控制报告的对象 控制报告的原始值 由 jvmtiHeapReferenceCallback返回的堆访问控制标志是 是,因为访问受控制 是,因为访问受控制 在 callbacks中设置的array_primitive_value_callback否 是 否 heap_filter否 是 是 klass否 是 是 能力可选功能:可能不会为所有虚拟机实现。必须满足以下功能(由GetCapabilities返回)才能使用此函数。功能 效果 can_tag_objects可以设置和获取标记,如堆类别中所述。 参数 名称 类型 描述 heap_filterjint这是一个位向量,用于限制调用回调函数的对象。这适用于对象和基本类型的回调。 klassjclass仅在对象是此类的实例时报告回调。属于 klass子类的对象不会被报告。如果klass是一个接口,则不会报告任何对象。这适用于对象和基本类型的回调。 如果klass是NULL,则回调不会限制到特定类的实例。initial_objectjobject要跟踪的对象 如果 initial_object是NULL,则从堆根引用开始跟踪。callbacksconst jvmtiHeapCallbacks *定义回调函数集的结构。 代理传递一个指向 jvmtiHeapCallbacks的指针。user_dataconst void *用户提供的数据将传递给回调函数。 代理传递一个指针。如果 user_data是NULL,则将NULL作为用户提供的数据传递。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_tag_objects能力。使用AddCapabilities。JVMTI_ERROR_INVALID_CLASSklass不是一个有效的类。JVMTI_ERROR_INVALID_OBJECTinitial_object不是一个有效的对象。JVMTI_ERROR_NULL_POINTERcallbacks是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对比):
在执行此函数期间,堆的状态不会改变:不会分配对象,不会进行垃圾回收,并且对象的状态(包括持有的值)不会改变。因此,执行Java编程语言代码的线程、尝试恢复Java编程语言代码执行的线程以及尝试执行JNI函数的线程通常会被阻塞。控制访问的对象 控制报告的对象 控制报告的基本值 由 jvmtiHeapIterationCallback返回的堆访问控制标志否
(除非它们中止迭代)否
(除非它们中止迭代)否
(除非它们中止迭代)array_primitive_value_callback在callbacks中设置否 是 否 heap_filter否 是 是 klass否 是 是 能力可选功能:可能不会为所有虚拟机实现。必须具备以下能力(由GetCapabilities返回)才能使用此函数。能力 效果 can_tag_objects可以设置和获取标签,如堆类别中描述的。 参数 名称 类型 描述 heap_filterjint这是一个位向量,用于限制调用回调函数的对象。这适用于对象和基本类型的回调。 klassjclass仅在对象是此类的实例时报告回调。属于 klass子类的对象不会被报告。如果klass是一个接口,则不会报告任何对象。这适用于对象和基本类型的回调。 如果klass是NULL,则回调不会限制到特定类的实例。callbacksconst jvmtiHeapCallbacks *定义回调函数集的结构。 代理传递一个指向 jvmtiHeapCallbacks的指针。user_dataconst void *用户提供的数据将传递给回调函数。 代理传递一个指针。如果 user_data是NULL,则将NULL作为用户提供的数据传递。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_tag_objects。请使用AddCapabilities。JVMTI_ERROR_INVALID_CLASSklass不是有效的类。JVMTI_ERROR_NULL_POINTERcallbacks为NULL。
获取标签
检索与对象关联的标签。标签是一个长整型值,通常用于存储唯一标识符或对象信息的指针。标签是通过jvmtiError GetTag(jvmtiEnv* env, jobject object, jlong* tag_ptr)SetTag设置的。未设置标签的对象返回零值。能力可选功能:可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力为真才能使用此函数。能力 效果 can_tag_objects可以设置和获取标签,如Heap类别中所述。 参数 名称 类型 描述 objectjobject要检索其标签的对象。 tag_ptrjlong*返回时,引用的长整型设置为标签的值。 代理传递一个指向 jlong的指针。返回时,jlong已设置。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_tag_objects。请使用AddCapabilities。JVMTI_ERROR_INVALID_OBJECTobject不是对象。JVMTI_ERROR_NULL_POINTERtag_ptr为NULL。
设置标签
设置与对象关联的标签。标签是一个长整型值,通常用于存储唯一标识符或对象信息的指针。标签可通过jvmtiError SetTag(jvmtiEnv* env, jobject object, jlong tag)GetTag查看。能力可选功能:可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力为真才能使用此函数。能力 效果 can_tag_objects可以设置和获取标签,如Heap类别中所述。 参数 名称 类型 描述 objectjobject要设置其标签的对象。 tagjlong标签的新值。 错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_tag_objects。请使用AddCapabilities。JVMTI_ERROR_INVALID_OBJECTobject不是对象。
获取带有标签的对象
返回具有指定标签的堆中的对象。格式为对象和标签的并行数组。jvmtiError GetObjectsWithTags(jvmtiEnv* env, jint tag_count, const jlong* tags, jint* count_ptr, jobject** object_result_ptr, jlong** tag_result_ptr)能力可选功能:可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力为真才能使用此函数。能力 效果 can_tag_objects可以设置和获取标签,如Heap类别中所述。 参数 名称 类型 描述 tag_countjint要扫描的标签数量。 tagsconst jlong *扫描具有这些标签的对象。在此数组中不允许为零。 代理传入一个包含 tag_count个元素的jlong数组。count_ptrjint *返回具有 tags中任意标签的对象数量。 代理传入一个指向jint的指针。返回时,jint已被设置。object_result_ptrjobject **返回具有 tags中任意标签的对象数组。 代理传入一个指向jobject*的指针。返回时,jobject*指向一个新分配的大小为*count_ptr的数组。该数组应使用Deallocate进行释放。如果object_result_ptr为NULL,则不返回此信息。由object_result_ptr返回的对象是 JNI 本地引用,必须进行 管理。tag_result_ptrjlong **对于 object_result_ptr中的每个对象,返回相应索引处的标签。 代理传入一个指向jlong*的指针。返回时,jlong*指向一个新分配的大小为*count_ptr的数组。该数组应使用Deallocate进行释放。如果tag_result_ptr为NULL,则不返回此信息。错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_tag_objects能力。请使用AddCapabilities。JVMTI_ERROR_ILLEGAL_ARGUMENTtags中存在零。JVMTI_ERROR_ILLEGAL_ARGUMENTtag_count小于0。JVMTI_ERROR_NULL_POINTERtags为NULL。JVMTI_ERROR_NULL_POINTERcount_ptr为NULL。
强制垃圾回收
强制虚拟机执行垃圾回收。垃圾回收尽可能完整。此函数不会导致 finalizer 运行。此函数在垃圾回收完成前不会返回。 尽管垃圾回收尽可能完整,但不能保证在函数返回时所有jvmtiError ForceGarbageCollection(jvmtiEnv* env)
ObjectFree事件都已发送。特别是,对象可能因等待 finalization 而无法释放。能力所需功能参数无错误此函数返回一个 通用错误
堆(1.0)
堆(1.0)函数: 堆(1.0)函数类型: 堆(1.0)类型:jvmtiHeapObjectFilter- 堆对象过滤器枚举jvmtiHeapRootKind- 堆根种类枚举jvmtiObjectReferenceKind- 对象引用枚举jvmtiIterationControl- 迭代控制枚举
- 允许访问原始值(字符串、数组和基本字段的值)
- 允许设置引用者的标签,从而实现更高效的局部引用图构建
- 提供更广泛的过滤能力
- 是可扩展的,允许它们的功能在未来的 JVM TI 版本中增强
堆对象过滤器枚举( jvmtiHeapObjectFilter)常量 值 描述 JVMTI_HEAP_OBJECT_TAGGED1 仅标记的对象。 JVMTI_HEAP_OBJECT_UNTAGGED2 仅未标记的对象。 JVMTI_HEAP_OBJECT_EITHER3 标记或未标记的对象。 堆根种类枚举( jvmtiHeapRootKind)常量 值 描述 JVMTI_HEAP_ROOT_JNI_GLOBAL1 JNI 全局引用。 JVMTI_HEAP_ROOT_SYSTEM_CLASS2 系统类。 JVMTI_HEAP_ROOT_MONITOR3 监视器。 JVMTI_HEAP_ROOT_STACK_LOCAL4 堆栈本地。 JVMTI_HEAP_ROOT_JNI_LOCAL5 JNI 本地引用。 JVMTI_HEAP_ROOT_THREAD6 线程。 JVMTI_HEAP_ROOT_OTHER7 其他。 对象引用枚举( jvmtiObjectReferenceKind)常量 值 描述 JVMTI_REFERENCE_CLASS1 从对象到其类的引用。 JVMTI_REFERENCE_FIELD2 从对象到其实例字段值的引用。对于这种引用, referrer_index参数传递给jvmtiObjectReferenceCallback是实例字段的索引。该索引基于对象所有字段的顺序。这包括类中直接声明的静态和实例字段的所有字段,并包括在超类和超接口中声明的所有字段(公共和私有字段)。因此,索引是通过将字段在直接声明类中的索引(参见GetClassFields)与在所有超类和超接口中声明的所有字段(公共和私有字段)的总数相加来计算的。索引从零开始。JVMTI_REFERENCE_ARRAY_ELEMENT3 从数组到其元素的引用。对于这种引用, referrer_index参数传递给jvmtiObjectReferenceCallback是数组索引。JVMTI_REFERENCE_CLASS_LOADER4 从类到其类加载器的引用。 JVMTI_REFERENCE_SIGNERS5 从类到其签名者数组的引用。 JVMTI_REFERENCE_PROTECTION_DOMAIN6 从类到其保护域的引用。 JVMTI_REFERENCE_INTERFACE7 从类到其接口之一的引用。 JVMTI_REFERENCE_STATIC_FIELD8 从类到其静态字段值的引用。对于这种引用, referrer_index参数传递给jvmtiObjectReferenceCallback是静态字段的索引。该索引基于对象所有字段的顺序。这包括类中直接声明的静态和实例字段的所有字段,并包括在超类和超接口中声明的所有字段(公共和私有字段)。因此,索引是通过将字段在直接声明类中的索引(参见GetClassFields)与在所有超类和超接口中声明的所有字段(公共和私有字段)的总数相加来计算的。索引从零开始。注意:此定义与JVM 1.0规范中的定义不同。理由:没有已知的实现使用了1.0定义。
JVMTI_REFERENCE_CONSTANT_POOL9 从类到常量池中的已解析条目的引用。对于这种引用, referrer_index参数传递给jvmtiObjectReferenceCallback是类的常量池表中的索引,从1开始。参见《Java™虚拟机规范,第4.4章》。迭代控制枚举( jvmtiIterationControl)常量 值 描述 JVMTI_ITERATION_CONTINUE1 继续迭代。如果这是引用迭代,则跟随此对象的引用。 JVMTI_ITERATION_IGNORE2 继续迭代。如果这是引用迭代,则忽略此对象的引用。 JVMTI_ITERATION_ABORT0 中止迭代。
堆对象回调
代理提供的回调函数。描述(但不传递)堆中的对象。 返回值应为typedef jvmtiIterationControl (JNICALL *jvmtiHeapObjectCallback) (jlong class_tag, jlong size, jlong* tag_ptr, void* user_data);JVMTI_ITERATION_CONTINUE以继续迭代,或JVMTI_ITERATION_ABORT以停止迭代。 请参阅堆回调函数限制。参数 名称 类型 描述 class_tagjlong对象的类标记(如果类未标记,则为零)。如果对象表示运行时类,则 class_tag是与java.lang.Class关联的标记(如果java.lang.Class未标记,则为零)。sizejlong对象的大小(以字节为单位)。参见 GetObjectSize。tag_ptrjlong*对象标记值,如果对象未标记则为零。要将标记值设置为与对象关联的值,代理设置参数指向的 jlong。user_datavoid*传递给迭代函数的用户提供的数据。
堆根对象回调
代理提供的回调函数。描述(但不传递)作为垃圾回收根的对象。 返回值应为typedef jvmtiIterationControl (JNICALL *jvmtiHeapRootCallback) (jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong* tag_ptr, void* user_data);JVMTI_ITERATION_CONTINUE以继续迭代,JVMTI_ITERATION_IGNORE以继续迭代而不追踪被引用对象的引用,或JVMTI_ITERATION_ABORT以停止迭代。 请参阅堆回调函数限制。参数 名称 类型 描述 root_kindjvmtiHeapRootKind堆根的类型。 class_tagjlong对象的类标记(如果类未标记,则为零)。如果对象表示运行时类,则 class_tag是与java.lang.Class关联的标记(如果java.lang.Class未标记,则为零)。sizejlong对象的大小(以字节为单位)。参见 GetObjectSize。tag_ptrjlong*对象标记值,如果对象未标记则为零。要将标记值设置为与对象关联的值,代理设置参数指向的 jlong。user_datavoid*传递给迭代函数的用户提供的数据。
堆栈引用对象回调
代理提供的回调函数。描述(但不传入)堆栈上作为垃圾回收根源的对象。 返回值应为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以继续迭代而不追踪被引用对象的引用,或JVMTI_ITERATION_ABORT以停止迭代。 请参阅堆回调函数限制。JVMTI_HEAP_ROOT_STACK_LOCAL或JVMTI_HEAP_ROOT_JNI_LOCAL)。class_tag是与java.lang.Class关联的标记(如果java.lang.Class未标记则为零)。GetObjectSize。jlong。参数 名称 类型 描述 root_kindjvmtiHeapRootKindclass_tagjlongsizejlongtag_ptrjlong*thread_tagjlongdepthjintmethodjmethodIDslotjintuser_datavoid*
对象引用回调
代理提供的回调函数。描述从一个对象(引用者)到另一个对象(被引用对象)的引用。 返回值应为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以继续迭代而不追踪被引用对象的引用,或JVMTI_ITERATION_ABORT以停止迭代。 请参阅堆回调函数限制。class_tag是与java.lang.Class关联的标记(如果java.lang.Class未标记则为零)。GetObjectSize。jlong。JVMTI_REFERENCE_FIELD或JVMTI_REFERENCE_STATIC_FIELD的引用,引用者对象中字段的索引。索引基于所有对象字段的顺序 - 有关详细描述,请参阅 JVMTI_REFERENCE_FIELD或 JVMTI_REFERENCE_STATIC_FIELD。 对于类型为JVMTI_REFERENCE_ARRAY_ELEMENT的引用,数组索引 - 有关详细描述,请参阅JVMTI_REFERENCE_ARRAY_ELEMENT。 对于类型为JVMTI_REFERENCE_CONSTANT_POOL的引用,类常量池中的索引 - 有关详细描述,请参阅JVMTI_REFERENCE_CONSTANT_POOL。 对于其他类型的引用,referrer_index为-1。参数 名称 类型 描述 reference_kindjvmtiObjectReferenceKindclass_tagjlongsizejlongtag_ptrjlong*referrer_tagjlongreferrer_indexjintuser_datavoid*
迭代从对象可达的对象
此函数迭代从指定对象直接和间接可达的所有对象。对于每个具有对对象B的引用的对象A(称为引用者),将调用指定的回调函数来描述对象引用。对于每个引用者到被引用对象可能存在多个引用,可以通过jvmtiError IterateOverObjectsReachableFromObject(jvmtiEnv* env, jobject object, jvmtiObjectReferenceCallback object_reference_callback, const void* user_data)jvmtiObjectReferenceCallback.reference_kind和jvmtiObjectReferenceCallback.referrer_index进行区分。对象的回调将始终在其引用者的回调之后发生。 请参阅FollowReferences以获取报告的对象引用。 在执行此函数期间,堆的状态不会更改:不会分配对象,不会进行垃圾回收,并且对象的状态(包括持有的值)不会更改。因此,执行Java编程语言代码的线程,尝试恢复Java编程语言代码的线程以及尝试执行JNI函数的线程通常会被阻塞。能力可选功能:可能未针对所有虚拟机实现。必须满足以下功能(由GetCapabilities返回)才能使用此函数。功能 效果 can_tag_objects可以设置和获取标记,如堆类别中所述。 参数 名称 类型 描述 objectjobject对象 object_reference_callbackjvmtiObjectReferenceCallback用于描述每个对象引用的回调函数。 user_dataconst void *用户提供的数据,将传递给回调函数。 代理传入一个指针。如果 user_data为NULL,则将NULL作为用户提供的数据传递。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_tag_objects的能力。使用AddCapabilities。JVMTI_ERROR_INVALID_OBJECTobject不是一个对象。JVMTI_ERROR_NULL_POINTERobject_reference_callback为NULL。
遍历可达对象
此函数遍历根对象以及从根对象直接和间接可达的所有对象。根对象包括系统类集、JNI全局引用、来自平台线程堆栈的引用以及其他用于垃圾回收目的的对象。 对于每个根对象,将调用jvmtiError IterateOverReachableObjects(jvmtiEnv* env, jvmtiHeapRootCallback heap_root_callback, jvmtiStackReferenceCallback stack_ref_callback, jvmtiObjectReferenceCallback object_ref_callback, const void* user_data)heap_root_callback或stack_ref_callback回调函数。一个对象可能因多个原因成为根对象,在这种情况下,将为每个原因调用适当的回调函数。 对于每个对象引用,将调用object_ref_callback回调函数来描述对象引用。对于每个引用方的引用,回调函数仅调用一次;即使存在引用循环或多个路径到引用方,也是如此。引用方和被引用方之间可能存在多个引用,可以通过jvmtiObjectReferenceCallback.reference_kind和jvmtiObjectReferenceCallback.referrer_index进行区分。对象的回调总是在其引用方的回调之后发生。 查看FollowReferences以获取报告的对象引用。 根总是在报告任何对象引用之前报告给分析器。换句话说,在为所有根调用适当的回调函数之前,不会调用object_ref_callback回调函数。如果将object_ref_callback指定为NULL,则此函数在向分析器报告根对象后返回。 在执行此函数期间,堆的状态不会发生变化:不会分配对象,不会进行垃圾回收,对象的状态(包括持有的值)也不会改变。因此,执行Java编程语言代码的线程、尝试恢复Java编程语言代码执行的线程以及尝试执行JNI函数的线程通常会被阻塞。能力可选功能:可能不是所有虚拟机都实现的。必须通过GetCapabilities返回的以下能力为真才能使用此函数。能力 效果 can_tag_objects可以设置和获取标签,如 Heap类别中所述。参数 名称 类型 描述 heap_root_callbackjvmtiHeapRootCallback用于每个堆根的回调函数,类型为 JVMTI_HEAP_ROOT_JNI_GLOBAL、JVMTI_HEAP_ROOT_SYSTEM_CLASS、JVMTI_HEAP_ROOT_MONITOR、JVMTI_HEAP_ROOT_THREAD或JVMTI_HEAP_ROOT_OTHER。 如果heap_root_callback为NULL,则不报告堆根。stack_ref_callbackjvmtiStackReferenceCallback用于每个 JVMTI_HEAP_ROOT_STACK_LOCAL或JVMTI_HEAP_ROOT_JNI_LOCAL堆根的回调函数。 如果stack_ref_callback为NULL,则不报告堆根引用。object_ref_callbackjvmtiObjectReferenceCallback用于每个对象引用的回调函数。 如果 object_ref_callback为NULL,则不跟踪从根对象的引用。user_dataconst void *用户提供的数据,将传递给回调函数。 代理传入一个指针。如果 user_data为NULL,则将NULL作为用户提供的数据传递。错误此函数返回一个通用错误或以下错误之一错误 描述 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函数的线程通常会被阻塞。能力可选功能:并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此功能。能力 效果 can_tag_objects可以设置和获取标签,如在Heap类别中描述的。 参数 名称 类型 描述 klassjclass仅迭代此类的对象。 object_filterjvmtiHeapObjectFilter指示调用回调函数的对象。 heap_object_callbackjvmtiHeapObjectCallback要为每个与 object_filter匹配的klass实例调用的迭代器函数。user_dataconst void *要传递给回调的用户提供的数据。 代理传入一个指针。如果 user_data为NULL,则将NULL作为用户提供的数据传递。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_tag_objects能力。使用AddCapabilities。JVMTI_ERROR_INVALID_CLASSklass不是类对象或类已被卸载。JVMTI_ERROR_ILLEGAL_ARGUMENTobject_filter不是jvmtiHeapObjectFilter。JVMTI_ERROR_NULL_POINTERheap_object_callback为NULL。
本地变量
本地变量函数:- 获取本地变量 - 对象
- 获取本地实例
- 获取本地变量 - 整数
- 获取本地变量 - 长整数
- 获取本地变量 - 浮点数
- 获取本地变量 - 双精度浮点数
- 设置本地变量 - 对象
- 设置本地变量 - 整数
- 设置本地变量 - 长整数
- 设置本地变量 - 浮点数
- 设置本地变量 - 双精度浮点数
GetLocalVariableTable获得。GetLocalXXX函数可用于检索虚拟线程帧中包含的本地变量的值。SetLocalXXX函数可用于在暂停在事件的虚拟线程的顶层帧中设置本地变量的值。实现可能支持在其他情况下设置本地变量。
获取本地变量 - 对象
此函数可用于检索类型为jvmtiError GetLocalObject(jvmtiEnv* env, jthread thread, jint depth, jint slot, jobject* value_ptr)Object或Object子类的本地变量的值。 指定的线程必须被挂起或必须是当前线程。SetNativeMethodPrefix与使用能力可选功能:可能并非所有虚拟机都实现了。必须满足以下能力(由GetCapabilities返回)才能使用此函数。能力 效果 can_access_local_variables可以设置和获取本地变量 参数 名称 类型 描述 threadjthread包含变量值的帧的线程。如果 thread为NULL,则使用当前线程。depthjint包含变量值的帧的深度。 slotjint变量的槽号。 value_ptrjobject*返回时,指向变量的值。 代理传递一个指向 jobject的指针。返回时,jobject已设置。由value_ptr返回的对象是JNI本地引用,必须管理。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_access_local_variables。使用AddCapabilities。JVMTI_ERROR_INVALID_SLOT无效的 slot。JVMTI_ERROR_TYPE_MISMATCH变量类型不是 Object或Object的子类。JVMTI_ERROR_OPAQUE_FRAME不是可见帧 JVMTI_ERROR_THREAD_NOT_SUSPENDED线程未被挂起且不是当前线程。 JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(尚未启动或已终止)。JVMTI_ERROR_ILLEGAL_ARGUMENTdepth小于零。JVMTI_ERROR_NO_MORE_FRAMES指定深度处没有堆栈帧。 JVMTI_ERROR_NULL_POINTERvalue_ptr为NULL。
获取本地实例
此函数可用于检索非静态帧中槽0(“jvmtiError GetLocalInstance(jvmtiEnv* env, jthread thread, jint depth, jobject* value_ptr)this”对象)的本地对象变量的值。此函数可以从本地方法帧中检索“this”对象,而GetLocalObject()在这些情况下会返回JVMTI_ERROR_OPAQUE_FRAME。 指定的线程必须被挂起或必须是当前线程。能力可选功能:可能并非所有虚拟机都实现了。必须满足以下能力(由GetCapabilities返回)才能使用此函数。能力 效果 can_access_local_variables可以设置和获取本地变量 参数 名称 类型 描述 threadjthread包含变量值的帧的线程。如果 thread为NULL,则使用当前线程。depthjint包含变量值的帧的深度。 value_ptrjobject*返回时,指向变量的值。 代理传递一个指向 jobject的指针。返回时,jobject已设置。由value_ptr返回的对象是JNI本地引用,必须管理。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_access_local_variables。使用AddCapabilities。JVMTI_ERROR_INVALID_SLOT如果指定的帧是静态方法帧。 JVMTI_ERROR_THREAD_NOT_SUSPENDED线程未被挂起且不是当前线程。 JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(尚未启动或已终止)。JVMTI_ERROR_ILLEGAL_ARGUMENTdepth小于零。JVMTI_ERROR_NO_MORE_FRAMES指定深度处没有堆栈帧。 JVMTI_ERROR_NULL_POINTERvalue_ptr为NULL。
获取本地变量 - Int
此函数可用于检索类型为jvmtiError GetLocalInt(jvmtiEnv* env, jthread thread, jint depth, jint slot, jint* value_ptr)int,short,char,字节,或布尔。 指定的线程必须被挂起或必须是当前线程。能力可选功能:可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力为真才能使用此函数。能力 效果 can_access_local_variables可以设置和获取局部变量 参数 名称 类型 描述 线程jthread包含变量值的帧的线程。如果 线程为NULL,则使用当前线程。深度jint包含变量值的帧的深度。 槽jint变量的槽号。 value_ptrjint*返回时,指向变量的值。 代理传递一个指向 jint的指针。返回时,jint已被设置。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_access_local_variables。使用AddCapabilities。JVMTI_ERROR_INVALID_SLOT无效的 槽。JVMTI_ERROR_TYPE_MISMATCH变量类型不是 int、short、char、byte或boolean。JVMTI_ERROR_OPAQUE_FRAME不是可见帧 JVMTI_ERROR_THREAD_NOT_SUSPENDED线程未被挂起且不是当前线程。 JVMTI_ERROR_INVALID_THREAD线程不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE线程不活动(未启动或已终止)。JVMTI_ERROR_ILLEGAL_ARGUMENT深度小于零。JVMTI_ERROR_NO_MORE_FRAMES指定的 深度没有堆栈帧。JVMTI_ERROR_NULL_POINTERvalue_ptr为NULL。
获取局部变量 - 长整型
此函数可用于检索类型为jvmtiError GetLocalLong(jvmtiEnv* env, jthread thread, jint depth, jint slot, jlong* value_ptr)long的局部变量的值。 指定的线程必须被挂起或必须是当前线程。能力可选功能:可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力为真才能使用此函数。能力 效果 can_access_local_variables可以设置和获取局部变量 参数 名称 类型 描述 线程jthread包含变量值的帧的线程。如果 线程为NULL,则使用当前线程。深度jint包含变量值的帧的深度。 槽jint变量的槽号。 value_ptrjlong*返回时,指向变量的值。 代理传递一个指向 jlong的指针。返回时,jlong已被设置。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_access_local_variables。使用AddCapabilities。JVMTI_ERROR_INVALID_SLOT无效的 槽。JVMTI_ERROR_TYPE_MISMATCH变量类型不是 long。JVMTI_ERROR_OPAQUE_FRAME不是可见帧 JVMTI_ERROR_THREAD_NOT_SUSPENDED线程未被挂起且不是当前线程。 JVMTI_ERROR_INVALID_THREAD线程不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE线程不活动(未启动或已终止)。JVMTI_ERROR_ILLEGAL_ARGUMENT深度小于零。JVMTI_ERROR_NO_MORE_FRAMES指定的 深度没有堆栈帧。JVMTI_ERROR_NULL_POINTERvalue_ptr为NULL。能力可选功能:并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此功能。能力 效果 can_access_local_variables可以设置和获取本地变量 参数 名称 类型 描述 线程jthread包含变量值的帧的线程。如果 thread为NULL,则使用当前线程。深度jint包含变量值的帧的深度。 槽位jint变量的槽位编号。 值指针jfloat*返回时,指向变量的值。 代理传递一个指向 jfloat的指针。返回时,jfloat已被设置。错误此函数返回通用错误或以下错误之一错误 描述 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_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(未启动或已终止)。JVMTI_ERROR_ILLEGAL_ARGUMENTdepth小于零。JVMTI_ERROR_NO_MORE_FRAMES指定深度处没有堆栈帧。 JVMTI_ERROR_NULL_POINTERvalue_ptr为NULL。
获取本地变量 - 双精度
此函数可用于检索类型为jvmtiError GetLocalDouble(jvmtiEnv* env, jthread thread, jint depth, jint slot, jdouble* value_ptr)long的本地变量的值。 指定的线程必须已暂停或必须是当前线程。能力可选功能:并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此功能。能力 效果 can_access_local_variables可以设置和获取本地变量 参数 名称 类型 描述 线程jthread包含变量值的帧的线程。如果 thread为NULL,则使用当前线程。深度jint包含变量值的帧的深度。 槽位jint变量的槽位编号。 值指针jdouble*返回时,指向变量的值。 代理传递一个指向 jdouble的指针。返回时,jdouble已被设置。错误此函数返回通用错误或以下错误之一错误 描述 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_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(未启动或已终止)。JVMTI_ERROR_ILLEGAL_ARGUMENTdepth小于零。JVMTI_ERROR_NO_MORE_FRAMES指定深度处没有堆栈帧。 JVMTI_ERROR_NULL_POINTERvalue_ptr为NULL。
设置本地变量 - 对象
此函数可用于设置类型为jvmtiError SetLocalObject(jvmtiEnv* env, jthread thread, jint depth, jint slot, jobject value)Object或Object子类的本地变量的值。 指定的线程必须已暂停或必须是当前线程。能力可选功能:并非所有虚拟机都实现了。必须通过GetCapabilities返回的以下能力为真才能使用此功能。能力 效果 can_access_local_variables可以设置和获取本地变量 参数 名称 类型 描述 线程jthread包含变量值的帧的线程。如果 thread为NULL,则使用当前线程。深度jint包含变量值的帧的深度。 槽jint变量的槽号。 值jobject变量的新值。 错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_access_local_variables。请使用AddCapabilities。JVMTI_ERROR_INVALID_SLOT无效的 slot。JVMTI_ERROR_TYPE_MISMATCH变量类型不是 Object或Object的子类。JVMTI_ERROR_TYPE_MISMATCH提供的 value与变量类型不兼容。JVMTI_ERROR_OPAQUE_FRAME不是可见帧 JVMTI_ERROR_OPAQUE_FRAME线程是挂起的虚拟线程,实现不支持在给定深度的帧中设置本地变量的值。请参阅本地变量。 JVMTI_ERROR_THREAD_NOT_SUSPENDED线程未挂起且不是当前线程。 JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread未启动或已终止。JVMTI_ERROR_ILLEGAL_ARGUMENTdepth小于零。JVMTI_ERROR_NO_MORE_FRAMES指定深度处没有堆栈帧。 JVMTI_ERROR_INVALID_OBJECTvalue不是对象。
设置本地变量 - 整数
此函数可用于设置类型为jvmtiError SetLocalInt(jvmtiEnv* env, jthread thread, jint depth, jint slot, jint value)int、short、char、byte或boolean的本地变量的值。 指定的线程必须被挂起或必须是当前线程。能力可选功能:并非所有虚拟机都实现了。必须通过GetCapabilities返回的以下能力为真才能使用此功能。能力 效果 can_access_local_variables可以设置和获取本地变量 参数 名称 类型 描述 线程jthread包含变量值的帧的线程。如果 thread为NULL,则使用当前线程。深度jint包含变量值的帧的深度。 槽jint变量的槽号。 值jint变量的新值。 错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_access_local_variables。请使用AddCapabilities。JVMTI_ERROR_INVALID_SLOT无效的 slot。JVMTI_ERROR_TYPE_MISMATCH变量类型不是 int、short、char、byte或boolean。JVMTI_ERROR_OPAQUE_FRAME不是可见帧 JVMTI_ERROR_OPAQUE_FRAME线程是挂起的虚拟线程,实现不支持在给定深度的帧中设置本地变量的值。请参阅本地变量。 JVMTI_ERROR_THREAD_NOT_SUSPENDED线程未挂起且不是当前线程。 JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread未启动或已终止。JVMTI_ERROR_ILLEGAL_ARGUMENTdepth小于零。JVMTI_ERROR_NO_MORE_FRAMES指定深度处没有堆栈帧。
设置本地变量 - 长整型
此函数可用于设置类型为jvmtiError SetLocalLong(jvmtiEnv* env, jthread thread, jint depth, jint slot, jlong value)long的本地变量的值。 指定的线程必须被挂起或必须是当前线程。能力可选功能:可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力为真才能使用此功能。能力 效果 can_access_local_variables可以设置和获取本地变量 参数 名称 类型 描述 threadjthread包含变量值的帧的线程。如果 thread为NULL,则使用当前线程。depthjint包含变量值的帧的深度。 slotjint变量的槽号。 valuejlong变量的新值。 错误此函数返回一个通用错误或以下错误之一错误 描述 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_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread未启动或已终止。JVMTI_ERROR_ILLEGAL_ARGUMENTdepth小于零。JVMTI_ERROR_NO_MORE_FRAMES指定深度处没有堆栈帧。
设置本地变量 - 浮点数
此函数可用于设置类型为jvmtiError SetLocalFloat(jvmtiEnv* env, jthread thread, jint depth, jint slot, jfloat value)float的本地变量的值。 指定的线程必须被挂起或必须是当前线程。能力可选功能:可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力为真才能使用此功能。能力 效果 can_access_local_variables可以设置和获取本地变量 参数 名称 类型 描述 threadjthread包含变量值的帧的线程。如果 thread为NULL,则使用当前线程。depthjint包含变量值的帧的深度。 slotjint变量的槽号。 valuejfloat变量的新值。 错误此函数返回一个通用错误或以下错误之一错误 描述 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_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread未启动或已终止。JVMTI_ERROR_ILLEGAL_ARGUMENTdepth小于零。JVMTI_ERROR_NO_MORE_FRAMES指定深度处没有堆栈帧。
设置本地变量 - 双精度浮点数
此函数可用于设置类型为jvmtiError SetLocalDouble(jvmtiEnv* env, jthread thread, jint depth, jint slot, jdouble value)double的本地变量的值。 指定的线程必须被挂起或必须是当前线程。能力可选功能:并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此功能。能力 效果 can_access_local_variables可以设置和获取局部变量 参数 名称 类型 描述 threadjthread包含变量值的帧的线程。如果 thread为NULL,则使用当前线程。depthjint包含变量值的帧的深度。 slotjint变量的槽号。 valuejdouble变量的新值。 错误此函数返回一个通用错误或以下错误之一错误 描述 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_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(未启动或已终止)。JVMTI_ERROR_ILLEGAL_ARGUMENTdepth小于零。JVMTI_ERROR_NO_MORE_FRAMES指定深度处没有堆栈帧。
断点
断点函数:
设置断点
在由jvmtiError SetBreakpoint(jvmtiEnv* env, jmethodID method, jlocation location)method和location指示的指令处设置断点。一个指令只能有一个断点。 每当指定的指令即将执行时,会生成一个断点事件。能力可选功能:并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此功能。能力 效果 can_generate_breakpoint_events可以设置并因此获取 断点事件参数 名称 类型 描述 methodjmethodID要设置断点的方法 locationjlocation要设置断点的指令的索引 错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_generate_breakpoint_events。请使用AddCapabilities。JVMTI_ERROR_DUPLICATE指定的字节码已经有一个断点。 JVMTI_ERROR_INVALID_METHODIDmethod不是jmethodID。JVMTI_ERROR_INVALID_LOCATIONlocation不是有效位置。
清除断点
清除由jvmtiError ClearBreakpoint(jvmtiEnv* env, jmethodID method, jlocation location)method和location指示的字节码处的断点。能力可选功能:并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此功能。能力 效果 can_generate_breakpoint_events可以设置并因此获取 断点事件参数 名称 类型 描述 methodjmethodID要清除断点的方法 locationjlocation要清除断点的指令索引 错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_generate_breakpoint_events能力。请使用AddCapabilities。JVMTI_ERROR_NOT_FOUND指定的字节码中没有断点。 JVMTI_ERROR_INVALID_METHODIDmethod不是 jmethodID。JVMTI_ERROR_INVALID_LOCATIONlocation不是有效的位置。
监视字段
监视字段函数:
设置字段访问监视
当由jvmtiError SetFieldAccessWatch(jvmtiEnv* env, jclass klass, jfieldID field)klass和field指定的字段即将被访问时生成一个FieldAccess事件。每次访问该字段时都会生成一个事件,直到使用ClearFieldAccessWatch取消。来自Java编程语言代码或JNI代码的字段访问会被监视,通过其他方式修改的字段不会被监视。请注意,JVM TI用户应注意,他们自己的字段访问将触发监视。一个字段只能设置一个字段访问监视。字段的修改不被视为访问--使用SetFieldModificationWatch监视修改。能力可选功能: 可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此函数。能力 效果 can_generate_field_access_events可以在字段访问上设置监视点 - SetFieldAccessWatch参数 名称 类型 描述 klassjclass包含要监视的字段的类 fieldjfieldID要监视的字段 错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_generate_field_access_events能力。请使用AddCapabilities。JVMTI_ERROR_DUPLICATE指定的字段已经被监视以进行访问。 JVMTI_ERROR_INVALID_CLASSklass不是类对象或类已被卸载。JVMTI_ERROR_INVALID_FIELDIDfield不是 jfieldID。
清除字段访问监视
取消先前由jvmtiError ClearFieldAccessWatch(jvmtiEnv* env, jclass klass, jfieldID field)SetFieldAccessWatch设置的字段访问监视,针对klass和field指定的字段。能力可选功能: 可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此函数。能力 效果 can_generate_field_access_events可以在字段访问上设置监视点 - SetFieldAccessWatch参数 名称 类型 描述 klassjclass包含要监视的字段的类 fieldjfieldID要监视的字段 错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_generate_field_access_events能力。请使用AddCapabilities。JVMTI_ERROR_NOT_FOUND指定的字段未被监视以进行访问。 JVMTI_ERROR_INVALID_CLASSklass不是类对象或类已被卸载。JVMTI_ERROR_INVALID_FIELDIDfield不是 jfieldID。
设置字段修改监视
当由jvmtiError SetFieldModificationWatch(jvmtiEnv* env, jclass klass, jfieldID field)klass和field指定的字段即将被修改时生成一个FieldModification事件。每次修改该字段时都会生成一个事件,直到使用ClearFieldModificationWatch。来自Java编程语言代码或JNI代码的字段修改会被监视,其他方式修改的字段不会被监视。请注意,JVM TI用户应该注意,他们自己的字段修改将触发监视。一个字段只能设置一个字段修改监视。能力可选功能:可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力为真才能使用此功能。能力 效果 can_generate_field_modification_events可以在字段修改上设置监视点 - SetFieldModificationWatch参数 名称 类型 描述 klassjclass包含要监视的字段的类 fieldjfieldID要监视的字段 错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_generate_field_modification_events。使用AddCapabilities。JVMTI_ERROR_DUPLICATE指定的字段已经被监视以进行修改。 JVMTI_ERROR_INVALID_CLASSklass不是类对象或类已被卸载。JVMTI_ERROR_INVALID_FIELDIDfield不是jfieldID。
清除字段修改监视
取消先前由jvmtiError ClearFieldModificationWatch(jvmtiEnv* env, jclass klass, jfieldID field)SetFieldModificationWatch设置的字段修改监视,取消指定的klass和field字段。能力可选功能:可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力为真才能使用此功能。能力 效果 can_generate_field_modification_events可以在字段修改上设置监视点 - SetFieldModificationWatch参数 名称 类型 描述 klassjclass包含要监视的字段的类 fieldjfieldID要监视的字段 错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_generate_field_modification_events。使用AddCapabilities。JVMTI_ERROR_NOT_FOUND指定的字段未被监视以进行修改。 JVMTI_ERROR_INVALID_CLASSklass不是类对象或类已被卸载。JVMTI_ERROR_INVALID_FIELDIDfield不是jfieldID。
模块
模块函数:
获取所有模块
返回虚拟机中加载的所有模块的数组。数组包括每个类加载器的未命名模块。数组中的模块数量通过jvmtiError GetAllModules(jvmtiEnv* env, jint* module_count_ptr, jobject** modules_ptr)module_count_ptr返回,数组本身通过modules_ptr返回。能力必需功能参数 名称 类型 描述 module_count_ptrjint*返回时,指向返回的模块数量。 代理传递一个指向 jint的指针。返回时,jint已被设置。modules_ptrjobject**返回时,指向一个引用数组,每个模块一个引用。 代理传递一个指向 jobject*的指针。返回时,jobject*指向一个新分配的大小为*module_count_ptr的数组。数组应使用Deallocate释放。由modules_ptr返回的对象是JNI本地引用,必须管理。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERmodule_count_ptr为NULL。JVMTI_ERROR_NULL_POINTERmodules_ptr为NULL。
获取命名模块
返回给定包含特定包的类加载器定义的命名模块的jvmtiError GetNamedModule(jvmtiEnv* env, jobject class_loader, const char* package_name, jobject* module_ptr)java.lang.Module对象。模块通过module_ptr返回。 如果类加载器定义了命名模块并且包含该包,则返回该命名模块,否则返回NULL。能力所需功能参数 名称 类型 描述 class_loaderjobject一个类加载器。如果 class_loader不为NULL或为java.lang.ClassLoader的子类,则此函数返回JVMTI_ERROR_ILLEGAL_ARGUMENT。 如果class_loader为NULL,则假定为引导加载器。package_nameconst char*包的名称,编码为修改后的UTF-8字符串。包名采用内部形式(JVMS 4.2.1);标识符用斜杠而不是句点分隔。 代理传入一个 char数组。module_ptrjobject*返回时,指向一个 java.lang.Module对象或指向NULL。 代理传递一个指向jobject的指针。返回时,jobject已被设置。由module_ptr返回的对象是JNI本地引用,必须管理。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_ILLEGAL_ARGUMENT如果类加载器不为 NULL且不是类加载器对象。JVMTI_ERROR_NULL_POINTERpackage_name为NULL。JVMTI_ERROR_NULL_POINTERmodule_ptr为NULL。
添加模块读取
更新一个模块以读取另一个模块。当jvmtiError AddModuleReads(jvmtiEnv* env, jobject module, jobject to_module)module是一个未命名模块时,此函数无效。此函数便于在需要扩展模块读取的模块中进行代码的插装。能力所需功能参数 名称 类型 描述 modulejobject要更新的模块。 to_modulejobject要读取的额外模块。 错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_MODULE如果 module不是模块对象。JVMTI_ERROR_INVALID_MODULE如果 to_module不是模块对象。JVMTI_ERROR_UNMODIFIABLE_MODULE如果无法修改模块。请参阅 IsModifiableModule。JVMTI_ERROR_NULL_POINTERmodule为NULL。JVMTI_ERROR_NULL_POINTERto_module为NULL。
添加模块导出
更新一个模块以向另一个模块导出一个包。当jvmtiError AddModuleExports(jvmtiEnv* env, jobject module, const char* pkg_name, jobject to_module)module是一个未命名模块或开放模块时,此函数无效。此函数便于在需要扩展模块导出的包集的插装代码中进行插装。能力所需功能参数 名称 类型 描述 modulejobject要更新的模块。 pkg_nameconst char*导出的包名称。 代理传入一个 char数组。to_modulejobject要导出包的模块。如果 to_module不是java.lang.Module的子类,则此函数返回JVMTI_ERROR_INVALID_MODULE。错误此函数返回一个通用错误或以下错误之一错误 描述 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_POINTERmodule为NULL。JVMTI_ERROR_NULL_POINTERpkg_name为NULL。JVMTI_ERROR_NULL_POINTERto_module为NULL。
添加模块打开
更新模块以将一个包打开到另一个模块。当jvmtiError AddModuleOpens(jvmtiEnv* env, jobject module, const char* pkg_name, jobject to_module)module是一个未命名模块或一个开放模块时,此函数不执行任何操作。此函数有助于在需要扩展模块打开到其他模块的包集的情况下对模块中的代码进行仪器化。能力所需功能代理传入一个 char数组。to_module不是java.lang.Module的子类,则此函数返回JVMTI_ERROR_INVALID_MODULE。参数 名称 类型 描述 modulejobjectpkg_nameconst char*to_modulejobject错误此函数返回一个通用错误或以下错误之一错误 描述 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_POINTERmodule为NULL。JVMTI_ERROR_NULL_POINTERpkg_name为NULL。JVMTI_ERROR_NULL_POINTERto_module为NULL。
添加模块使用
更新模块以将服务添加到模块使用的服务集。当模块是未命名模块时,此函数不执行任何操作。此函数有助于在需要扩展模块正在使用的服务集的情况下对命名模块中的代码进行仪器化。jvmtiError AddModuleUses(jvmtiEnv* env, jobject module, jclass service)能力所需功能参数 名称 类型 描述 modulejobjectservicejclass错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_MODULE如果 module不是模块对象。JVMTI_ERROR_INVALID_CLASS如果 service不是类对象。JVMTI_ERROR_UNMODIFIABLE_MODULE如果模块无法修改。请参阅 IsModifiableModule。JVMTI_ERROR_NULL_POINTERmodule为NULL。JVMTI_ERROR_NULL_POINTERservice为NULL。
添加模块提供
更新模块以将服务添加到模块提供的服务集。当模块是未命名模块时,此函数不执行任何操作。此函数有助于在需要更改所提供服务的情况下对命名模块中的代码进行仪器化。jvmtiError AddModuleProvides(jvmtiEnv* env, jobject module, jclass service, jclass impl_class)能力所需功能参数 名称 类型 描述 modulejobject要更新的模块。 servicejclass要提供的服务。 impl_classjclass提供的服务的实现类。 错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_MODULE如果 module不是模块对象。JVMTI_ERROR_INVALID_CLASS如果 service不是类对象。JVMTI_ERROR_INVALID_CLASS如果 impl_class不是类对象。JVMTI_ERROR_UNMODIFIABLE_MODULE如果无法修改模块。请参阅 IsModifiableModule。JVMTI_ERROR_NULL_POINTERmodule为NULL。JVMTI_ERROR_NULL_POINTERservice为NULL。JVMTI_ERROR_NULL_POINTERimpl_class为NULL。
可修改模块
确定模块是否可修改。如果模块可修改,则可以使用jvmtiError IsModifiableModule(jvmtiEnv* env, jobject module, jboolean* is_modifiable_module_ptr)AddModuleReads、AddModuleExports、AddModuleOpens、AddModuleUses和AddModuleProvides更新此模块。如果模块不可修改,则无法使用这些函数更新模块。当用于确定未命名模块是否可修改时,此函数的结果始终为JNI_TRUE。能力所需功能参数 名称 类型 描述 modulejobjectis_modifiable_module_ptrjboolean*返回时,指向此函数的布尔结果。 代理传递指向 jboolean的指针。返回时,已设置jboolean。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_MODULE如果 module不是模块对象。JVMTI_ERROR_NULL_POINTERmodule为NULL。JVMTI_ERROR_NULL_POINTERis_modifiable_module_ptr为NULL。
类
类函数:- 获取已加载的类
- 获取类加载器加载的类
- 获取类签名
- 获取类状态
- 获取源文件名
- 获取类修饰符
- 获取类方法
- 获取类字段
- 获取实现的接口
- 获取类版本号
- 获取常量池
- 是否为接口
- 是否为数组类
- 是否为可修改类
- 获取类加载器
- 获取源调试扩展
- 重新转换类
- 重新定义类
jvmtiClassDefinition- 类重定义描述
获取已加载的类
返回虚拟机中加载的所有类的数组。数组中的类数量通过jvmtiError GetLoadedClasses(jvmtiEnv* env, jint* class_count_ptr, jclass** classes_ptr)class_count_ptr返回,数组本身通过classes_ptr返回。 类或接口的创建可以由以下操作之一触发:- 通过使用类加载器从
class文件表示派生并加载类(请参阅 Java™虚拟机规范,第5.3章)。 - 通过调用 Lookup::defineHiddenClass 创建隐藏类或接口,该操作使用
class文件表示。 - 通过调用某些Java SE平台API的方法。
java.lang.Integer.TYPE)不包括在返回的列表中。能力所需功能参数 名称 类型 描述 class_count_ptrjint*返回时指向类的数量。代理传递一个指向 jint的指针。返回时,jint已被设置。classes_ptrjclass**返回时指向一个引用数组,每个类一个引用。代理传递一个指向 jclass*的指针。返回时,jclass*指向一个新分配的大小为*class_count_ptr的数组。该数组应使用Deallocate进行释放。由classes_ptr返回的对象是 JNI 本地引用,必须进行 管理。错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERclass_count_ptr为NULL。JVMTI_ERROR_NULL_POINTERclasses_ptr为NULL。
获取类加载器加载的类
返回此类加载器可以通过名称找到的所有类的数组,通过 ClassLoader::loadClass, Class::forName 和字节码链接。也就是说,所有这些类都已记录为启动加载器的初始化加载器。返回的数组中的每个类都是由此类加载器创建的,可以直接定义它,也可以委托给另一个类加载器。参见 Java™虚拟机规范,第5.3章。 返回的列表不包括 隐藏类或接口,或其元素类型为隐藏类或接口的数组类,因为任何类加载器都无法发现它们。 数组中的类的数量通过jvmtiError GetClassLoaderClasses(jvmtiEnv* env, jobject initiating_loader, jint* class_count_ptr, jclass** classes_ptr)class_count_ptr返回,数组本身通过classes_ptr返回。 参见 Lookup::defineHiddenClass。能力所需功能参数 名称 类型 描述 initiating_loaderjobject一个初始化类加载器。 如果 initiating_loader为NULL,则返回由引导加载器初始化的类。class_count_ptrjint*返回时指向类的数量。 代理传递一个指向 jint的指针。返回时,jint已被设置。classes_ptrjclass**返回时指向一个引用数组,每个类一个引用。 代理传递一个指向 jclass*的指针。返回时,jclass*指向一个新分配的大小为*class_count_ptr的数组。该数组应使用Deallocate进行释放。由classes_ptr返回的对象是 JNI 本地引用,必须进行 管理。错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERclass_count_ptr为NULL。JVMTI_ERROR_NULL_POINTERclasses_ptr为NULL。
获取类签名
返回由jvmtiError GetClassSignature(jvmtiEnv* env, jclass klass, char** signature_ptr, char** generic_ptr)klass指示的类的名称和通用签名。 如果类是类或接口,则:- 如果类或接口不是 隐藏的,则返回的名称是 JNI 类型签名。例如,java.util.List 是 "Ljava/util/List;"
- 如果类或接口是 隐藏的,则返回的名称是形式为:
"L" + N + "." + S + ";"的字符串,其中N是二进制名称以内部形式编码(JVMS 4.2.1)指示的类文件传递给 Lookup::defineHiddenClass,而S是未限定名称。返回的名称不是类型描述符,不符合 JVMS 4.3.2。例如,com.foo.Foo/AnySuffix 是 "Lcom/foo/Foo.AnySuffix;"
klass指示的类表示数组类,则返回的名称是一个字符串,由一个或多个 "[" 字符表示数组嵌套的深度,后跟元素类型的类签名。例如,java.lang.String[] 的类签名是 "[Ljava/lang/String;",int[] 的是 "[I"。 如果由klass指示的类表示原始类型或void,则返回的名称是相应原始类型的 类型签名字符。例如,java.lang.Integer.TYPE 是 "I"。能力所需功能参数 名称 类型 描述 klassjclass要查询的类。 signature_ptrchar **返回时指向类的 JNI 类型签名,编码为 修改的 UTF-8 字符串。 代理传递一个指向 char*的指针。返回时,char*指向一个新分配的数组。该数组应使用Deallocate进行释放。如果signature_ptr为NULL,则不返回签名。generic_ptrchar **返回时指向类的通用签名,编码为 修改的 UTF-8 字符串。如果类没有通用签名属性,则返回时指向 NULL。 代理传递一个指向char*的指针。返回时,char*指向一个新分配的数组。该数组应使用Deallocate进行释放。如果generic_ptr为NULL,则不返回通用签名。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_CLASSklass不是一个类对象或该类已被卸载。
获取类状态
获取类的状态。以下位中的零个或多个可以被设置。jvmtiError GetClassStatus(jvmtiEnv* env, jclass klass, jint* status_ptr)类状态标志 常量 值 描述 JVMTI_CLASS_STATUS_VERIFIED1 类字节码已经验证 JVMTI_CLASS_STATUS_PREPARED2 类准备完成 JVMTI_CLASS_STATUS_INITIALIZED4 类初始化完成。静态初始化程序已运行。 JVMTI_CLASS_STATUS_ERROR8 初始化期间的错误使类无法使用 JVMTI_CLASS_STATUS_ARRAY16 类是一个数组。如果设置,所有其他位都为零。 JVMTI_CLASS_STATUS_PRIMITIVE32 类是一个原始类(例如, java.lang.Integer.TYPE)。如果设置,所有其他位都为零。能力所需功能参数 名称 类型 描述 klassjclass要查询的类。 status_ptrjint*返回时,指向该类当前状态的一个或多个类状态标志。 代理传递一个指向 jint的指针。返回时,jint已被设置。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_CLASSklass不是一个类对象或该类已被卸载。JVMTI_ERROR_NULL_POINTERstatus_ptr为NULL。
获取源文件名
对于由jvmtiError GetSourceFileName(jvmtiEnv* env, jclass klass, char** source_name_ptr)klass指示的类,通过source_name_ptr返回源文件名。返回的字符串仅包含文件名,不包含目录名。 对于原始类(例如,java.lang.Integer.TYPE)和数组,此函数返回JVMTI_ERROR_ABSENT_INFORMATION。能力可选功能:可能不是所有虚拟机都实现。必须具备以下能力(由GetCapabilities返回)才能使用此函数。能力 效果 can_get_source_file_name可以获取类的源文件名 参数 名称 类型 描述 klassjclass要查询的类。 source_name_ptrchar**返回时,指向类的源文件名,编码为修改的UTF-8字符串。 代理传递一个指向 char*的指针。返回时,char*指向一个新分配的数组。应使用Deallocate释放数组。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_get_source_file_name。使用AddCapabilities。JVMTI_ERROR_ABSENT_INFORMATION类信息不包括源文件名。这包括类是数组类或原始类的情况。 JVMTI_ERROR_INVALID_CLASSklass不是一个类对象或该类已被卸载。JVMTI_ERROR_NULL_POINTERsource_name_ptr为NULL。
获取类修饰符
对于由jvmtiError GetClassModifiers(jvmtiEnv* env, jclass klass, jint* modifiers_ptr)klass指示的类,通过modifiers_ptr返回访问标志。访问标志在 The Java™ Virtual Machine Specification, Chapter 4 中定义。 如果类是数组类,则其公共、私有和受保护修饰符与其组件类型的相同。对于原始类型的数组,此组件类型由一个原始类之一表示(例如,java.lang.Integer.TYPE)。 如果类是原始类,则其公共修饰符始终为真,其受保护和私有修饰符始终为假。 如果类是数组类或原始类,则其最终修饰符始终为真,其接口修饰符始终为假。其其他修饰符的值不由此规范确定。能力所需功能参数 名称 类型 描述 klassjclass要查询的类。 modifiers_ptrjint*返回时,指向此类的当前访问标志。 代理传递一个指向 jint的指针。返回时,jint已被设置。错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_INVALID_CLASSklass不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTERmodifiers_ptr是NULL。
获取类方法
返回由jvmtiError GetClassMethods(jvmtiEnv* env, jclass klass, jint* method_count_ptr, jmethodID** methods_ptr)klass指示的类的方法计数通过method_count_ptr和方法ID列表通过methods_ptr。方法列表包含构造函数和静态初始化程序以及真实方法。仅返回直接声明的方法(不包括继承的方法)。对于数组类和基本类(例如,java.lang.Integer.TYPE),返回一个空方法列表。能力所需功能可选特性 能力 效果 can_maintain_original_method_order可以按照类文件中的顺序返回方法 参数 名称 类型 描述 klassjclass要查询的类。 method_count_ptrjint*返回时,指向此类中声明的方法数量。 代理传递一个指向 jint的指针。返回时,jint已被设置。methods_ptrjmethodID**返回时,指向方法ID数组。 代理传递一个指向 jmethodID*的指针。返回时,jmethodID*指向一个新分配的大小为*method_count_ptr的数组。应使用Deallocate释放数组。错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_CLASS_NOT_PREPAREDklass未准备好。JVMTI_ERROR_INVALID_CLASSklass不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTERmethod_count_ptr是NULL。JVMTI_ERROR_NULL_POINTERmethods_ptr是NULL。
获取类字段
返回由jvmtiError GetClassFields(jvmtiEnv* env, jclass klass, jint* field_count_ptr, jfieldID** fields_ptr)klass指示的类的字段计数通过field_count_ptr和字段ID列表通过fields_ptr。仅返回直接声明的字段(不包括继承的字段)。字段按照它们在类文件中出现的顺序返回。对于数组类和基本类(例如,java.lang.Integer.TYPE),返回一个空字段列表。使用 JNI 来确定数组的长度。能力所需功能参数 名称 类型 描述 klassjclass要查询的类。 field_count_ptrjint*返回时,指向此类中声明的字段数量。 代理传递一个指向 jint的指针。返回时,jint已被设置。fields_ptrjfieldID**返回时,指向字段ID数组。 代理传递一个指向 jfieldID*的指针。返回时,jfieldID*指向一个新分配的大小为*field_count_ptr的数组。应使用Deallocate释放数组。错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_CLASS_NOT_PREPAREDklass未准备好。JVMTI_ERROR_INVALID_CLASSklass不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTERfield_count_ptr是NULL。JVMTI_ERROR_NULL_POINTERfields_ptr是NULL。
获取已实现的接口
返回此类的直接超级接口。对于类,此函数返回其jvmtiError GetImplementedInterfaces(jvmtiEnv* env, jclass klass, jint* interface_count_ptr, jclass** interfaces_ptr)implements子句中声明的接口。对于接口,此函数返回其extends子句中声明的接口。对于数组类和基本类(例如,java.lang.Integer.TYPE),返回一个空接口列表。能力所需功能参数 名称 类型 描述 klassjclass要查询的类。 interface_count_ptrjint*返回时指向接口数量的指针。 代理传递一个指向 jint的指针。 返回时,jint已被设置。interfaces_ptrjclass**返回时指向接口数组的指针。 代理传递一个指向 jclass*的指针。 返回时,jclass*指向一个新分配的大小为*interface_count_ptr的数组。 应使用Deallocate释放数组。 GetImplementedInterfaces() 返回的对象是 JNI 本地引用,必须进行 管理。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_CLASS_NOT_PREPAREDklass未准备好。JVMTI_ERROR_INVALID_CLASSklass不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTERinterface_count_ptr为NULL。JVMTI_ERROR_NULL_POINTERinterfaces_ptr为NULL。
获取类版本号
返回由jvmtiError GetClassVersionNumbers(jvmtiEnv* env, jclass klass, jint* minor_version_ptr, jint* major_version_ptr)klass指示的类的次要和主要版本号,如 Java™虚拟机规范第4章 中定义。能力可选功能:可能不适用于所有虚拟机。要使用此函数,必须返回由GetCapabilities返回的以下功能。参数 名称 类型 描述 klassjclass要查询的类。 constant_pool_count_ptrjint*返回时,指向常量池表中条目数加一。这对应于类文件格式的 constant_pool_count项。 代理传递一个指向jint的指针。返回时,jint已被设置。constant_pool_byte_count_ptrjint*返回时,指向返回的原始常量池中的字节数。 代理传递一个指向 jint的指针。返回时,jint已被设置。constant_pool_bytes_ptrunsigned char**返回时,指向原始常量池,即类文件格式的 constant_pool项定义的字节 代理传递一个指向unsigned char*的指针。返回时,unsigned char*指向一个新分配的大小为*constant_pool_byte_count_ptr的数组。应使用Deallocate释放数组。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_get_constant_pool能力。使用AddCapabilities。JVMTI_ERROR_ABSENT_INFORMATION该类是原始类或数组类。 JVMTI_ERROR_INVALID_CLASSklass不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTERconstant_pool_count_ptr为NULL。JVMTI_ERROR_NULL_POINTERconstant_pool_byte_count_ptr为NULL。JVMTI_ERROR_NULL_POINTERconstant_pool_bytes_ptr为NULL。
是否为接口
确定类对象引用是否表示接口。如果“类”实际上是一个接口,则jvmtiError IsInterface(jvmtiEnv* env, jclass klass, jboolean* is_interface_ptr)jboolean结果为JNI_TRUE,否则为JNI_FALSE。能力所需功能参数 名称 类型 描述 klassjclass要查询的类。 is_interface_ptrjboolean*返回时,指向此函数的布尔结果。 代理传递一个指向 jboolean的指针。返回时,jboolean已被设置。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_CLASSklass不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTERis_interface_ptr为NULL。
是否为数组类
确定类对象引用是否表示数组。如果类是数组,则jvmtiError IsArrayClass(jvmtiEnv* env, jclass klass, jboolean* is_array_class_ptr)jboolean结果为JNI_TRUE,否则为JNI_FALSE。能力所需功能参数 名称 类型 描述 klassjclass要查询的类。 is_array_class_ptrjboolean*返回时,指向此函数的布尔结果。 代理传递一个指向 jboolean的指针。返回时,jboolean已被设置。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_CLASSklass不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTERis_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)、数组类和一些实现定义的类永远不可修改。能力所需功能可选特性 能力 效果 can_redefine_any_class如果拥有此能力,则所有类(除了基本类型、数组和一些实现定义的类)都可以使用 RedefineClasses进行修改。can_retransform_any_class如果拥有此能力,则所有类(除了基本类型、数组和一些实现定义的类)都可以使用 RetransformClasses进行修改。can_redefine_classes对函数结果没有影响。但必须额外拥有此能力才能使用 RedefineClasses修改类。can_retransform_classes对函数结果没有影响。但必须额外拥有此能力才能使用 RetransformClasses修改类。参数名称 类型 描述 klassjclass要查询的类。 is_modifiable_class_ptrjboolean*返回时,指向此函数的布尔结果。 代理传递一个指向 jboolean的指针。返回时,jboolean已被设置。错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_INVALID_CLASSklass不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTERis_modifiable_class_ptr为NULL。
获取类加载器
对于由jvmtiError GetClassLoader(jvmtiEnv* env, jclass klass, jobject* classloader_ptr)klass指示的类,通过classloader_ptr返回加载该类的类加载器的引用。能力所需功能参数名称 类型 描述 klassjclass要查询的类。 classloader_ptrjobject*返回时,指向加载此类的类加载器。如果类不是由类加载器创建或类加载器是引导类加载器,则指向 NULL。 代理传递一个指向jobject的指针。返回时,jobject已被设置。由classloader_ptr返回的对象是 JNI 本地引用,必须进行 管理。错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_INVALID_CLASSklass不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTERclassloader_ptr为NULL。
获取源代码调试扩展
对于由jvmtiError GetSourceDebugExtension(jvmtiEnv* env, jclass klass, char** source_debug_extension_ptr)klass指示的类,通过source_debug_extension_ptr返回调试扩展。返回的字符串精确包含klass的类文件中存在的调试扩展信息。能力可选功能: 可能不适用于所有虚拟机。必须具有以下能力(由GetCapabilities返回)才能使用此函数。能力 效果 can_get_source_debug_extension可以获取类的源代码调试扩展 参数名称 类型 描述 klassjclass要查询的类。 source_debug_extension_ptrchar**返回时,指向类的调试扩展,编码为 修改的 UTF-8 字符串。 代理传递一个指向 char*的指针。返回时,char*指向一个新分配的数组。应使用Deallocate释放数组。错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_get_source_debug_extension能力。使用AddCapabilities。JVMTI_ERROR_ABSENT_INFORMATION类信息不包括调试扩展。 JVMTI_ERROR_INVALID_CLASSklass不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTERsource_debug_extension_ptr为NULL。
重新转换类
此函数便于对已加载的类进行字节码注入。要替换类定义而不参考现有字节码,就像在重新编译源代码进行修复和继续调试时所做的那样,应改用jvmtiError RetransformClasses(jvmtiEnv* env, jint class_count, const jclass* classes)RedefineClasses函数。 当类最初加载或重新定义时,初始类文件字节可以通过ClassFileLoadHook事件进行转换。此函数重新运行转换过程(无论之前是否已发生过转换)。此重新转换遵循以下步骤:- 从初始类文件字节开始
- 对于每个 无法重新转换
- 的代理,其在上一次加载或重新定义期间收到
- 事件返回的字节(通过
- 参数)将被重用作为转换的输出;请注意,这等同于重新应用先前的转换,未更改。除了不会向这些代理发送
- 事件之外
- 对于每个 可以重新转换
- 的代理,将发送
- 事件,允许应用新的转换
- 转换后的类文件字节将安装为类的新定义
ClassFileLoadHooknew_class_dataClassFileLoadHookClassFileLoadHookClassFileLoadHook事件。 初始类文件字节表示传递给ClassLoader.defineClass或RedefineClasses(在应用任何转换之前),但它们可能不完全匹配。常量池可能以GetConstantPool中描述的方式不同。方法字节码中的常量池索引将对应。某些属性可能不存在。例如,对于不具有意义的顺序,例如方法的顺序,可能不会保留顺序。 重新转换可能导致安装新版本的方法。旧方法版本可能会变得过时新方法版本将在新调用中使用。如果方法具有活动堆栈帧,则这些活动帧将继续运行原始方法版本的字节码。 此函数不会引起任何初始化,除非按照通常的JVM语义进行。换句话说,重新转换类不会导致其初始化器运行。静态字段的值将保持调用之前的状态。 线程无需暂停。 类中的所有断点都将被清除。 所有属性都将被更新。 重新转换后的类的实例不受影响--字段保留其先前的值。 实例上的标签也不受影响。 对于此调用,除了ClassFileLoadHook事件之外,不会发送任何其他事件。 重新转换可能会更改方法体、常量池和属性(除非明确禁止)。重新转换不能添加、删除或重命名字段或方法,更改方法的签名,更改修饰符,或更改继承。重新转换不能更改NestHost、NestMembers、Record或PermittedSubclasses属性。这些限制可能在将来的版本中取消。有关尝试不受支持的重新转换时返回的错误代码的信息,请参阅下面的错误返回描述。在通过ClassFileLoadHook链传递之前,类文件字节不会被验证或安装,因此返回的错误代码反映了转换的结果。如果返回的错误代码不是JVMTI_ERROR_NONE,则将不会安装要重新转换的任何类的新定义。当此函数返回(带有错误代码为JVMTI_ERROR_NONE)时,所有要重新转换的类都将安装其新定义。能力可选功能:可能不会为所有虚拟机实现。必须满足以下能力(由GetCapabilities返回)才能使用此函数。能力 效果 can_retransform_classes可以使用 RetransformClasses重新转换类。除了特定实现对此能力施加的限制(请参阅能力部分),此能力必须在此环境中首次启用ClassFileLoadHook事件之前设置。在首次启用ClassFileLoadHook时具有此能力的环境被称为重新转换能力。在首次启用ClassFileLoadHook时不具备此能力的环境被称为重新转换无能。可选特性 can_retransform_any_classRetransformClasses可在任何可修改的类上调用。请参阅IsModifiableClass。(还必须设置can_retransform_classes)。参数 名称 类型 描述 class_countjint要重新转换的类的数量。 classesconst jclass*要重新转换的类的数组。 代理传入一个由 jclass元素组成的长度为class_count的数组。
重新定义类
根据提供的定义重新定义所有给定的类。此函数用于用新定义替换类的定义,例如在修复和继续调试中可能需要。例如,如果要转换现有的类文件字节,应使用字节码插装,应使用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。 重新定义可能导致安装新版本的方法。旧方法版本可能会变得过时新方法版本将在新调用中使用。如果方法具有活动堆栈帧,则这些活动帧将继续运行原始方法版本的字节码。如果需要重置堆栈帧,请使用PopFrame弹出具有过时方法版本的帧。 此函数不会引起任何初始化,除非按照通常的JVM语义进行。换句话说,重新定义类不会导致其初始化器运行。静态字段的值将保持调用之前的状态。 线程无需暂停。 类中的所有断点都将被清除。 所有属性都将被更新。 重新定义的类的实例不受影响 - 字段保留其先前的值。 标签在实例上也不受影响。 响应此调用,JVM TI事件Class File Load Hook将被发送(如果已启用),但不会发送其他JVM TI事件。 重新定义可能会更改方法体、常量池和属性(除非明确禁止)。重新定义不得添加、删除或重命名字段或方法,更改方法的签名、更改修饰符或更改继承。重新定义不得更改NestHost、NestMembers、Record或PermittedSubclasses属性。这些限制可能在将来的版本中取消。有关尝试不受支持的重新定义时返回的错误代码的信息,请参阅下面的错误返回描述。类文件字节在通过ClassFileLoadHook事件链传递之前不会被验证或安装,因此返回的错误代码反映了应用于传递到class_definitions的字节的转换的结果。如果返回的错误代码不是JVMTI_ERROR_NONE,则将不会安装任何要重新定义的类的新定义。当此函数返回(带有错误代码JVMTI_ERROR_NONE)时,所有要重新定义的类都将安装其新定义。能力可选功能:可能不适用于所有虚拟机。必须通过GetCapabilities返回的以下能力才能使用此功能。能力 效果 can_redefine_classes可以使用 RedefineClasses重新定义类。可选特性 can_redefine_any_classRedefineClasses可在任何可修改的类上调用。请参阅IsModifiableClass。(can_redefine_classes也必须设置)jvmtiClassDefinition- 类重新定义描述字段 类型 描述 klassjclass此类的类对象 class_byte_countjint定义类的字节数(以下) class_bytesconst unsigned char*定义类的字节(在Java™虚拟机规范第4章中) 参数 名称 类型 描述 class_countjint在 class_definitions中指定的类的数量class_definitionsconst jvmtiClassDefinition*新类定义的数组 代理传入一个包含 class_count个jvmtiClassDefinition元素的数组。
对象
对象函数: 对象类型:jvmtiMonitorUsage- 对象监视器使用信息
获取对象大小
返回jvmtiError GetObjectSize(jvmtiEnv* env, jobject object, jlong* size_ptr)object指示的对象的大小,通过size_ptr返回对象的大小。这个大小是对该对象消耗的存储空间的实现特定近似值。它可能包括对象的一部分或全部开销,因此对于在一个实现内部进行比较很有用,但不适用于不同实现之间的比较。在JVM的单个调用期间,估计值可能会发生变化。能力所需功能参数 名称 类型 描述 objectjobject要查询的对象。 size_ptrjlong*返回时,指向对象的大小(以字节为单位)。 代理传递一个指向 jlong的指针。返回时,jlong已设置。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_OBJECTobject不是对象。JVMTI_ERROR_NULL_POINTERsize_ptr是NULL。
获取对象哈希码
返回jvmtiError GetObjectHashCode(jvmtiEnv* env, jobject object, jint* hash_code_ptr)object指示的对象的哈希码,通过hash_code_ptr返回哈希码。这个哈希码可用于维护对象引用的哈希表,但在某些实现中,这可能会导致显著的性能影响--在大多数情况下,标签将是与对象关联信息的更有效手段。此函数保证特定对象的相同哈希码值在其整个生命周期中保持不变。能力所需功能参数 名称 类型 描述 objectjobject要查询的对象。 hash_code_ptrjint*返回时,指向对象的哈希码。 代理传递一个指向 jint的指针。返回时,jint已被设置。错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_INVALID_OBJECTobject不是一个对象。JVMTI_ERROR_NULL_POINTERhash_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结构的字段将填充有关监视器使用情况的信息。能力可选功能: 可能并非所有虚拟机都实现了。必须通过GetCapabilities返回的以下能力为真才能使用此函数。能力 效果 can_get_monitor_info可以 GetObjectMonitorUsagejvmtiMonitorUsage- 对象监视器使用信息字段 类型 描述 ownerjthread拥有此监视器的线程,如果未使用则为 NULLentry_countjint拥有线程进入监视器的次数 waiter_countjint等待拥有此监视器的线程数 waitersjthread*waiter_count个等待线程notify_waiter_countjint等待由此监视器通知的线程数 notify_waitersjthread*notify_waiter_count个等待被通知的线程参数 名称 类型 描述 objectjobject要查询的对象。 info_ptrjvmtiMonitorUsage*返回时,填充指定对象的监视器信息。 代理传递一个指向 jvmtiMonitorUsage的指针。返回时,jvmtiMonitorUsage已被设置。jvmtiMonitorUsage中owner字段返回的对象是 JNI 本地引用,必须进行 管理。jvmtiMonitorUsage中waiters字段返回的指针是新分配的数组。应使用Deallocate释放数组。jvmtiMonitorUsage中waiters字段返回的对象是 JNI 本地引用,必须进行 管理。jvmtiMonitorUsage中notify_waiters字段返回的指针是新分配的数组。应使用Deallocate释放数组。jvmtiMonitorUsage中notify_waiters字段返回的对象是 JNI 本地引用,必须进行 管理。错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_get_monitor_info能力。使用AddCapabilities。JVMTI_ERROR_INVALID_OBJECTobject不是一个对象。JVMTI_ERROR_NULL_POINTERinfo_ptr是NULL。
字段
字段函数:
获取字段名称(和签名)
对由jvmtiError GetFieldName(jvmtiEnv* env, jclass klass, jfieldID field, char** name_ptr, char** signature_ptr, char** generic_ptr)klass和field指示的字段,通过name_ptr返回字段名称,通过signature_ptr返回字段签名。 字段签名在 JNI 规范 中定义,并在 Java™ 虚拟机规范,第 4.3.2 章节 中称为字段描述符。能力所需功能参数 名称 类型 描述 klassjclass要查询的字段的类。 fieldjfieldID要查询的字段。 name_ptrchar **返回时,指向字段名称,编码为修改后的UTF-8字符串。 代理传递一个指向 char*的指针。 返回时,char*指向一个新分配的数组。 该数组应使用Deallocate释放。 如果name_ptr为NULL,则不返回名称。signature_ptrchar **返回时,指向字段签名,编码为修改后的UTF-8字符串。 代理传递一个指向 char*的指针。 返回时,char*指向一个新分配的数组。 该数组应使用Deallocate释放。 如果signature_ptr为NULL,则不返回签名。generic_ptrchar **返回时,指向字段的通用签名,编码为修改后的UTF-8字符串。 如果字段没有通用签名属性,则返回时指向 NULL。 代理传递一个指向char*的指针。 返回时,char*指向一个新分配的数组。 该数组应使用Deallocate释放。 如果generic_ptr为NULL,则不返回通用签名。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_CLASSklass不是类对象或类已被卸载。JVMTI_ERROR_INVALID_FIELDIDfield不是jfieldID。
获取字段声明类
返回由jvmtiError GetFieldDeclaringClass(jvmtiEnv* env, jclass klass, jfieldID field, jclass* declaring_class_ptr)klass和field指示的字段的定义类,通过declaring_class_ptr。 声明类将是klass、一个超类或一个实现的接口。能力所需功能参数 名称 类型 描述 klassjclass要查询的类。 fieldjfieldID要查询的字段。 declaring_class_ptrjclass*返回时,指向声明类 代理传递一个指向 的指针。 返回时, 已被设置。 declaring_class_ptr返回的对象是JNI本地引用,必须 管理。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_CLASSklass不是类对象或类已被卸载。JVMTI_ERROR_INVALID_FIELDIDfield不是jfieldID。JVMTI_ERROR_NULL_POINTERdeclaring_class_ptr为NULL。
获取字段修饰符
返回由jvmtiError GetFieldModifiers(jvmtiEnv* env, jclass klass, jfieldID field, jint* modifiers_ptr)klass和field指示的字段的访问标志,通过modifiers_ptr。 访问标志在Java™虚拟机规范,第4章中定义。能力所需功能参数 名称 类型 描述 klassjclass要查询的类。 fieldjfieldID要查询的字段。 modifiers_ptrjint*返回时,指向访问标志。 代理传递一个指向 的指针。 返回时, 已被设置。 错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_CLASSklass不是类对象或类已被卸载。JVMTI_ERROR_INVALID_FIELDIDfield不是jfieldID。JVMTI_ERROR_NULL_POINTERmodifiers_ptr为NULL。
字段是否合成
返回由jvmtiError IsFieldSynthetic(jvmtiEnv* env, jclass klass, jfieldID field, jboolean* is_synthetic_ptr)klass和field指示的字段是否合成的值,通过is_synthetic_ptr。 合成字段由编译器生成,但不在原始源代码中存在。能力可选功能:可能并非所有虚拟机都实现了。必须满足以下能力(由GetCapabilities返回)才能使用此功能。能力 效果 can_get_synthetic_attribute可以测试字段或方法是否是合成的 - IsFieldSynthetic和IsMethodSynthetic参数 名称 类型 描述 klassjclass要查询的字段的类。 fieldjfieldID要查询的字段。 is_synthetic_ptrjboolean*返回时,指向此函数的布尔结果。 代理传递指向 jboolean的指针。返回时,jboolean已设置。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_get_synthetic_attribute能力。使用AddCapabilities。JVMTI_ERROR_INVALID_CLASSklass不是类对象或类已被卸载。JVMTI_ERROR_INVALID_FIELDIDfield不是jfieldID。JVMTI_ERROR_NULL_POINTERis_synthetic_ptr为NULL。
方法
方法函数:- 获取方法名称(及签名)
- 获取方法声明类
- 获取方法修饰符
- 获取最大本地变量数
- 获取参数大小
- 获取行号表
- 获取方法位置
- 获取本地变量表
- 获取字节码
- 方法是否为本地方法
- 方法是否为合成方法
- 方法是否已过时
- 设置本地方法前缀
- 设置本地方法前缀
jvmtiLineNumberEntry- 行号表条目jvmtiLocalVariableEntry- 本地变量表条目
jmethodID)的信息,并设置方法的处理方式。已过时的方法
函数RetransformClasses和RedefineClasses可能导致安装新版本的方法。如果原始版本的方法与新版本等效,则认为原始版本的方法等效于新版本:- 它们的字节码相同,除了常量池中的索引
- 引用的常量相等。
IsMethodObsolete测试方法ID是否过时。
获取方法名称(及签名)
返回由jvmtiError GetMethodName(jvmtiEnv* env, jmethodID method, char** name_ptr, char** signature_ptr, char** generic_ptr)method指示的方法的方法名称通过name_ptr和方法签名通过signature_ptr。 方法签名在JNI规范中定义,并在Java™虚拟机规范,第4.3.3章节中称为方法描述符。请注意,这与Java语言规范中定义的方法签名不同。能力所需功能参数 名称 类型 描述 methodjmethodIDname_ptrchar **返回时,指向方法名称,编码为修改的UTF-8字符串。 代理传递指向 char*的指针。返回时,char*指向新分配的数组。应使用Deallocate释放数组。如果name_ptr为NULL,则不返回名称。signature_ptrchar **返回时,指向方法签名,编码为修改的UTF-8字符串。 代理传递指向 char*的指针。返回时,char*指向新分配的数组。应使用Deallocate释放数组。如果signature_ptr为NULL,则不返回签名。generic_ptrchar **返回时,指向方法的通用签名,编码为修改的UTF-8字符串。如果方法没有通用签名属性,则返回时指向 NULL。 代理传递指向char*的指针。返回时,char*指向新分配的数组。应使用Deallocate释放数组。如果generic_ptr为NULL,则不返回通用签名。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_METHODIDmethod不是jmethodID。
获取方法声明类
返回由jvmtiError GetMethodDeclaringClass(jvmtiEnv* env, jmethodID method, jclass* declaring_class_ptr)method指示的方法的定义类通过declaring_class_ptr。能力所需功能参数 名称 类型 描述 methodjmethodID要查询的方法。 declaring_class_ptrjclass*返回指向声明类的指针 代理传递一个指向 jclass的指针。返回时,jclass已被设置。由declaring_class_ptr返回的对象是 JNI 本地引用,必须进行 管理。错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_INVALID_METHODIDmethod不是 jmethodID。JVMTI_ERROR_NULL_POINTERdeclaring_class_ptr是NULL。
获取方法修饰符
返回由jvmtiError GetMethodModifiers(jvmtiEnv* env, jmethodID method, jint* modifiers_ptr)method指示的方法的访问标志,通过modifiers_ptr。访问标志在 Java™ 虚拟机规范,第 4 章 中定义。能力所需功能参数 名称 类型 描述 methodjmethodID要查询的方法。 modifiers_ptrjint*返回指向访问标志的指针。 代理传递一个指向 jint的指针。返回时,jint已被设置。错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_INVALID_METHODIDmethod不是 jmethodID。JVMTI_ERROR_NULL_POINTERmodifiers_ptr是NULL。
获取最大本地变量数
返回由jvmtiError GetMaxLocals(jvmtiEnv* env, jmethodID method, jint* max_ptr)method指示的方法使用的本地变量槽的数量,包括用于将参数传递给方法的本地变量。 参见max_locals在 Java™ 虚拟机规范,第 4.7.3 章。能力所需功能参数 名称 类型 描述 methodjmethodID要查询的方法。 max_ptrjint*返回指向最大本地槽数的指针。 代理传递一个指向 jint的指针。返回时,jint已被设置。错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_INVALID_METHODIDmethod不是 jmethodID。JVMTI_ERROR_NATIVE_METHODmethod是本地方法。JVMTI_ERROR_NULL_POINTERmax_ptr是NULL。
获取参数大小
返回由jvmtiError GetArgumentsSize(jvmtiEnv* env, jmethodID method, jint* size_ptr)method指示的方法的参数使用的本地变量槽数,通过max_ptr。请注意,两个字长的参数使用两个槽。能力所需功能参数 名称 类型 描述 methodjmethodID要查询的方法。 size_ptrjint*返回指向参数槽数的指针。 代理传递一个指向 jint的指针。返回时,jint已被设置。错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_INVALID_METHODIDmethod不是 jmethodID。JVMTI_ERROR_NATIVE_METHODmethod是本地方法。JVMTI_ERROR_NULL_POINTERsize_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返回。能力可选功能:可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此功能。能力 效果 can_get_line_numbers可以获取方法的行号表 jvmtiLineNumberEntry- 行号表条目字段 类型 描述 start_locationjlocation行开始的 jlocationline_numberjint行号 参数 名称 类型 描述 methodjmethodID要查询的方法。 entry_count_ptrjint*返回时,指向表中的条目数 代理传递一个指向 jint的指针。返回时,jint已设置。table_ptrjvmtiLineNumberEntry**返回时,指向行号表指针。 代理传递一个指向 jvmtiLineNumberEntry*的指针。返回时,jvmtiLineNumberEntry*指向一个新分配的大小为*entry_count_ptr的数组。应使用Deallocate释放数组。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_get_line_numbers。使用AddCapabilities。JVMTI_ERROR_ABSENT_INFORMATION类信息不包括行号。 JVMTI_ERROR_INVALID_METHODIDmethod不是jmethodID。JVMTI_ERROR_NATIVE_METHODmethod是本地方法。JVMTI_ERROR_NULL_POINTERentry_count_ptr为NULL。JVMTI_ERROR_NULL_POINTERtable_ptr为NULL。
获取方法位置
返回由jvmtiError GetMethodLocation(jvmtiEnv* env, jmethodID method, jlocation* start_location_ptr, jlocation* end_location_ptr)method指示的方法的开始和结束地址,通过start_location_ptr和end_location_ptr。在传统的字节码索引方案中,start_location_ptr始终指向零,end_location_ptr始终指向字节码计数减一。能力必需功能参数 名称 类型 描述 methodjmethodID要查询的方法。 start_location_ptrjlocation*返回时,指向第一个位置,或 -1如果位置信息不可用。如果信息可用且GetJLocationFormat返回JVMTI_JLOCATION_JVMBCI,则此值始终为零。 代理传递一个指向jlocation的指针。返回时,jlocation已设置。end_location_ptrjlocation*返回时,指向最后一个位置,或 -1如果位置信息不可用。 代理传递一个指向jlocation的指针。返回时,jlocation已设置。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_ABSENT_INFORMATION类信息不包括方法大小。 JVMTI_ERROR_INVALID_METHODIDmethod不是jmethodID。JVMTI_ERROR_NATIVE_METHODmethod是本地方法。JVMTI_ERROR_NULL_POINTERstart_location_ptr为NULL。JVMTI_ERROR_NULL_POINTERend_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)能力可选功能:可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此功能。能力 效果 can_access_local_variables可以设置和获取局部变量 jvmtiLocalVariableEntry- 本地变量表条目字段 类型 描述 start_locationjlocation本地变量首次有效的代码数组索引(即必须具有值的位置)。 lengthjint本地变量有效部分的长度。本地变量有效的最后一个代码数组索引为 start_location + length。namechar*本地变量名称,编码为 修改过的 UTF-8 字符串。 signaturechar*本地变量的类型签名,编码为 修改过的 UTF-8 字符串。签名格式与《Java™虚拟机规范》第4.3.2章节中定义的相同。 generic_signaturechar*本地变量的通用签名,编码为 修改过的 UTF-8 字符串。对于没有通用类型的任何本地变量,此字段的值将为 NULL。slotjint本地变量的槽位。参见 本地变量。 参数 名称 类型 描述 methodjmethodID要查询的方法。 entry_count_ptrjint*返回时,指向表中条目的数量 代理传递一个指向 jint的指针。返回时,jint已被设置。table_ptrjvmtiLocalVariableEntry**返回时,指向本地变量表条目数组 代理传递一个指向 jvmtiLocalVariableEntry*的指针。返回时,jvmtiLocalVariableEntry*指向一个新分配的大小为*entry_count_ptr的数组。数组应使用Deallocate释放。在jvmtiLocalVariableEntry的name字段中返回的指针是新分配的数组。这些数组应使用Deallocate释放。在jvmtiLocalVariableEntry的signature字段中返回的指针是新分配的数组。这些数组应使用Deallocate释放。在jvmtiLocalVariableEntry的generic_signature字段中返回的指针是新分配的数组。这些数组应使用Deallocate释放。错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_access_local_variables能力。使用AddCapabilities。JVMTI_ERROR_ABSENT_INFORMATION类信息不包括本地变量信息。 JVMTI_ERROR_INVALID_METHODIDmethod不是 jmethodID。JVMTI_ERROR_NATIVE_METHODmethod是本地方法。JVMTI_ERROR_NULL_POINTERentry_count_ptr为NULL。JVMTI_ERROR_NULL_POINTERtable_ptr为NULL。
获取字节码
返回实现方法的字节码的方法指示的jvmtiError GetBytecodes(jvmtiEnv* env, jmethodID method, jint* bytecode_count_ptr, unsigned char** bytecodes_ptr)method。通过bytecode_count_ptr返回字节码的数量。通过bytecodes_ptr返回字节码本身。能力可选功能: 可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此函数。能力 效果 can_get_bytecodes可以获取方法的字节码 GetBytecodes参数 名称 类型 描述 methodjmethodID要查询的方法。 bytecode_count_ptrjint*返回时,指向字节码数组的长度 代理传递一个指向 jint的指针。返回时,jint已被设置。bytecodes_ptrunsigned char**返回时,指向字节码数组的指针 代理传递一个指向 unsigned char*的指针。返回时,unsigned char*指向一个新分配的大小为*bytecode_count_ptr的数组。数组应使用Deallocate释放。错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_get_bytecodes能力。使用AddCapabilities。JVMTI_ERROR_INVALID_METHODIDmethod不是 jmethodID。JVMTI_ERROR_NATIVE_METHODmethod是本地方法。JVMTI_ERROR_NULL_POINTERbytecode_count_ptr为NULL。JVMTI_ERROR_NULL_POINTERbytecodes_ptr为NULL。
方法是否为本地方法
返回由jvmtiError IsMethodNative(jvmtiEnv* env, jmethodID method, jboolean* is_native_ptr)method指示的方法是否为本地方法的值通过is_native_ptr能力必需功能参数 名称 类型 描述 方法jmethodID要查询的方法。 is_native_ptrjboolean*返回时,指向此函数的布尔结果的指针。 代理传递一个指向 jboolean的指针。返回时,jboolean已被设置。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_METHODID方法不是 jmethodID。JVMTI_ERROR_NULL_POINTERis_native_ptr是NULL。
方法是否合成
对由jvmtiError IsMethodSynthetic(jvmtiEnv* env, jmethodID method, jboolean* is_synthetic_ptr)方法指示的方法,通过is_synthetic_ptr返回一个值,指示方法是否是合成的。合成方法是编译器生成的,但不在原始源代码中存在。能力可选功能: 可能不适用于所有虚拟机。必须使用此功能的以下功能(由GetCapabilities返回)必须为真。能力 效果 can_get_synthetic_attribute可以测试字段或方法是否是合成的 - IsFieldSynthetic和IsMethodSynthetic参数 名称 类型 描述 方法jmethodID要查询的方法。 is_synthetic_ptrjboolean*返回时,指向此函数的布尔结果的指针。 代理传递一个指向 jboolean的指针。返回时,jboolean已被设置。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_get_synthetic_attribute能力。使用AddCapabilities。JVMTI_ERROR_INVALID_METHODID方法不是 jmethodID。JVMTI_ERROR_NULL_POINTERis_synthetic_ptr是NULL。
方法是否过时
确定方法 ID 是否指向一个 过时 方法版本。jvmtiError IsMethodObsolete(jvmtiEnv* env, jmethodID method, jboolean* is_obsolete_ptr)能力必需功能参数 名称 类型 描述 方法jmethodID要查询的方法 ID。 is_obsolete_ptrjboolean*返回时,指向此函数的布尔结果的指针。 代理传递一个指向 jboolean的指针。返回时,jboolean已被设置。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_METHODID方法不是 jmethodID。JVMTI_ERROR_NULL_POINTERis_obsolete_ptr是NULL。
设置本地方法前缀
此函数通过允许应用前缀重试来修改本地方法解析的失败处理。与 ClassFileLoadHook 事件 一起使用时,它使本地方法能够被 插装。 由于本地方法不能直接被插装(它们没有字节码),它们必须被包装在一个可以被插装的非本地方法中。例如,如果我们有:jvmtiError SetNativeMethodPrefix(jvmtiEnv* env, const char* prefix)
我们可以通过类文件转换(使用 ClassFileLoadHook 事件)使其变为:native boolean foo(int x);
其中 foo 成为实际本地方法的包装器,附加前缀 "wrapped_"。请注意,"wrapped_" 将是一个不好的前缀选择,因为它可能形成现有方法的名称,因此像 "$$$MyAgentWrapped$$$_" 这样的前缀会更好,但会使这些示例不太可读。 包装器将允许在调用本地方法时收集数据,但现在的问题是如何将包装方法与本地实现链接起来。也就是说,方法boolean foo(int x) { ... 记录进入 foo ... return wrapped_foo(x); } native boolean wrapped_foo(int x);wrapped_foo需要解析为foo的本地实现,可能是:
此函数允许指定前缀并进行正确的解析。具体来说,当标准解析失败时,将考虑前缀进行重试。解析有两种方式进行,使用 JNI 函数Java_somePackage_someClass_foo(JNIEnv* env, jint x)
RegisterNatives进行显式解析和正常的自动解析。对于RegisterNatives,VM 将尝试进行以下关联:
当此失败时,将使用指定的前缀重新尝试解析方法名,从而得到正确的解析:method(foo) -> nativeImplementation(foo)
对于自动解析,VM 将尝试:method(wrapped_foo) -> nativeImplementation(foo)
当此失败时,将删除指定前缀并重新尝试解析,从而得到正确的解析:method(wrapped_foo) -> nativeImplementation(wrapped_foo)
请注意,由于前缀仅在标准解析失败时使用,因此可以有选择地包装本机方法。 由于每个JVM TI环境是独立的,并且可以对字节码进行自己的转换,因此可以应用多层包装。因此,每个环境都需要自己的前缀。由于转换是按顺序应用的,如果应用了前缀,那么前缀将按相同的顺序应用。转换应用的顺序在method(wrapped_foo) -> nativeImplementation(foo)
ClassFileLoadHook事件中描述。因此,如果三个环境应用了包装器,foo可能会变成$env3_$env2_$env1_foo。但是,如果,例如,第二个环境没有对foo应用包装器,那么它将只是$env3_$env1_foo。为了能够有效地确定前缀的顺序,只有在其非本机包装器存在时才应用中间前缀。因此,在最后一个示例中,即使$env1_foo不是本机方法,也会应用$env1_前缀,因为$env1_foo存在。 由于前缀在解析时使用,而解析可能会任意延迟,因此只要存在相应的带前缀的本机方法,本机方法前缀必须保持设置。能力可选功能:可能不适用于所有虚拟机。必须通过GetCapabilities返回的以下能力才能使用此功能。能力 效果 can_set_native_method_prefix可以设置在无法解析本机方法时应用的前缀 - SetNativeMethodPrefix和SetNativeMethodPrefixes参数 名称 类型 描述 前缀const char *要应用的前缀,编码为修改后的UTF-8字符串。 代理以 char数组传入。如果prefix为NULL,则取消此环境中的任何现有前缀。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_set_native_method_prefix。请使用AddCapabilities。
设置本机方法前缀
对于普通代理,jvmtiError SetNativeMethodPrefixes(jvmtiEnv* env, jint prefix_count, char** prefixes)SetNativeMethodPrefix将提供所有所需的本机方法前缀。对于执行多个独立类文件转换的元代理(例如作为另一层代理的代理),此函数允许每个转换具有自己的前缀。前缀按提供的顺序应用,并且与在多个JVM TI环境中描述的前缀应用方式相同。 任何先前的前缀都将被替换。因此,在此环境中使用prefix_count为0调用此函数将禁用前缀。SetNativeMethodPrefix和此函数是设置前缀的两种方式。使用带前缀调用SetNativeMethodPrefix与使用prefix_count为1调用此函数相同。使用NULL调用prefix_count为0调用此函数相同。能力可选功能:可能不适用于所有虚拟机。必须通过GetCapabilities返回的以下能力才能使用此功能。能力 效果 can_set_native_method_prefix可以设置在无法解析本机方法时应用的前缀 - SetNativeMethodPrefix和SetNativeMethodPrefixes参数 名称 类型 描述 prefix_countjint要应用的前缀数量。 prefixeschar **要应用于此环境的前缀,每个都编码为修改后的UTF-8字符串。 错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_set_native_method_prefix。请使用AddCapabilities。JVMTI_ERROR_ILLEGAL_ARGUMENTprefix_count小于0。JVMTI_ERROR_NULL_POINTERprefixes为NULL。
原始监视器
原始监视器函数:
创建原始监视器
创建一个原始监视器。jvmtiError CreateRawMonitor(jvmtiEnv* env, const char* name, jrawMonitorID* monitor_ptr)只能在OnLoad或live阶段调用311.0能力所需功能修改后的UTF-8字符串。 代理传入一个 char数组。代理传递一个指向 jrawMonitorID的指针。返回时,jrawMonitorID已设置。参数 名称 类型 描述 nameconst char*monitor_ptrjrawMonitorID*错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERname为NULL。JVMTI_ERROR_NULL_POINTERmonitor_ptr为NULL。
销毁原始监视器
销毁原始监视器。如果要销毁的监视器已被此线程进入,则在销毁之前将退出该监视器。如果要销毁的监视器已被另一个线程进入,则将返回错误,并且监视器不会被销毁。jvmtiError DestroyRawMonitor(jvmtiEnv* env, jrawMonitorID monitor)只能在OnLoad或live阶段调用321.0能力所需功能参数 名称 类型 描述 monitorjrawMonitorID监视器 错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_NOT_MONITOR_OWNER非监视器所有者 JVMTI_ERROR_INVALID_MONITORmonitor不是jrawMonitorID。
进入原始监视器
获得原始监视器的独占所有权。同一线程可以多次进入监视器。线程必须退出与进入次数相同的监视器。如果在jvmtiError RawMonitorEnter(jvmtiEnv* env, jrawMonitorID monitor)OnLoad期间(在附加线程存在之前)进入监视器,并且在附加线程出现时尚未退出,则认为进入是在主线程上发生的。可以在任何阶段调用331.0能力所需功能参数 名称 类型 描述 monitorjrawMonitorID监视器 错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_MONITORmonitor不是jrawMonitorID。
退出原始监视器
释放对原始监视器的独占所有权。jvmtiError RawMonitorExit(jvmtiEnv* env, jrawMonitorID monitor)可以在任何阶段调用341.0能力所需功能参数 名称 类型 描述 monitorjrawMonitorID监视器 错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_NOT_MONITOR_OWNER非监视器所有者 JVMTI_ERROR_INVALID_MONITORmonitor不是jrawMonitorID。
等待原始监视器
等待原始监视器的通知。 导致当前线程等待,直到另一个线程调用jvmtiError RawMonitorWait(jvmtiEnv* env, jrawMonitorID monitor, jlong millis)RawMonitorNotify或RawMonitorNotifyAll用于指定的原始监视器,或指定的 超时 已经过去。可在任何阶段调用此函数可以从对 Heap 迭代函数的回调中调用,也可以从GarbageCollectionStart、GarbageCollectionFinish和ObjectFree事件的事件处理程序中调用。351.0能力所需功能参数 名称 类型 描述 monitorjrawMonitorID监视器 millisjlong超时时间,以毫秒为单位。如果超时时间为零,则不考虑实时时间,线程将等待直到收到通知。 错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_NOT_MONITOR_OWNER非监视器所有者 JVMTI_ERROR_INTERRUPT等待被中断,请重试 JVMTI_ERROR_INVALID_MONITORmonitor不是 jrawMonitorID。
原始监视器通知
通知等待原始监视器的单个线程。jvmtiError RawMonitorNotify(jvmtiEnv* env, jrawMonitorID monitor)可在任何阶段调用此函数可以从对 Heap 迭代函数的回调中调用,也可以从GarbageCollectionStart、GarbageCollectionFinish和ObjectFree事件的事件处理程序中调用。361.0能力所需功能参数 名称 类型 描述 monitorjrawMonitorID监视器 错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_NOT_MONITOR_OWNER非监视器所有者 JVMTI_ERROR_INVALID_MONITORmonitor不是 jrawMonitorID。
原始监视器通知所有
通知所有等待原始监视器的线程。jvmtiError RawMonitorNotifyAll(jvmtiEnv* env, jrawMonitorID monitor)可在任何阶段调用此函数可以从对 Heap 迭代函数的回调中调用,也可以从GarbageCollectionStart、GarbageCollectionFinish和ObjectFree事件的事件处理程序中调用。371.0能力所需功能参数 名称 类型 描述 monitorjrawMonitorID监视器 错误此函数返回一个 通用错误 或以下错误之一错误 描述 JVMTI_ERROR_NOT_MONITOR_OWNER非监视器所有者 JVMTI_ERROR_INVALID_MONITORmonitor不是 jrawMonitorID。
JNI函数拦截
JNI函数拦截函数: 通过操纵JNI函数表提供拦截和重新发送Java本机接口(JNI)函数调用的能力。请参阅 JNI函数 在 Java本机接口规范 中。 以下示例说明拦截NewGlobalRefJNI调用以计算引用创建次数。
在调用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代码,该代码会调用创建新全局引用的调用。该调用不会转到正常的JNI实现,而是转到myNewGlobalRef。请注意,保留原始函数表的副本,以便在收集数据后可以调用正常的JNI函数。还请注意,任何未被覆盖的JNI函数将正常工作。
设置JNI函数表
在所有当前和未来的JNI环境中设置JNI函数表。因此,所有未来的JNI调用都将指向指定的函数。使用jvmtiError SetJNIFunctionTable(jvmtiEnv* env, const jniNativeInterface* function_table)GetJNIFunctionTable获取要传递给此函数的函数表。为使此函数生效,必须使用更新后的表条目的JNI客户端。由于表被定义为const,一些编译器可能会优化掉对表的访问,从而阻止此函数生效。表被复制--对表的本地副本的更改不会产生影响。此函数仅影响函数表,环境的所有其他方面不受影响。请参见上面的示例 above。能力所需功能参数 名称 类型 描述 function_tableconst jniNativeInterface *指向新的JNI函数表。代理传递指向 jniNativeInterface的指针。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERfunction_table为NULL。
获取JNI函数表
获取JNI函数表。JNI函数表被复制到分配的内存中。如果jvmtiError GetJNIFunctionTable(jvmtiEnv* env, jniNativeInterface** function_table)SetJNIFunctionTable已被调用,则返回修改后的(而不是原始的)函数表。只复制函数表,不复制环境的其他方面。参见上面的示例。能力所需功能参数 名称 类型 描述 function_tablejniNativeInterface **返回时, *function_table指向新分配的JNI函数表的副本。代理传递指向jniNativeInterface*的指针。返回时,jniNativeInterface*指向新分配的数组。应使用Deallocate释放数组。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERfunction_table为NULL。
事件管理
事件管理函数: 事件管理类型:jvmtiEventMode- 事件启用/禁用
设置事件回调
为每个事件设置要调用的函数。通过提供替换函数表来指定回调。函数表被复制--对表的本地副本的更改不会产生影响。这是一个原子操作,所有回调一次设置。在调用此函数之前不会发送任何事件。当条目为jvmtiError SetEventCallbacks(jvmtiEnv* env, const jvmtiEventCallbacks* callbacks, jint size_of_callbacks)NULL或事件超出size_of_callbacks时,不会发送任何事件。有关事件的详细信息在本文档的后面描述。为了发送事件,事件必须被启用并具有回调--调用此函数和SetEventNotificationMode的顺序不会影响结果。能力所需功能参数 名称 类型 描述 callbacksconst jvmtiEventCallbacks *新的事件回调。代理传递指向 jvmtiEventCallbacks的指针。如果callbacks为NULL,则删除现有的回调。size_of_callbacksjintsizeof(jvmtiEventCallbacks)--用于版本兼容性。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_ILLEGAL_ARGUMENTsize_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)常量 值 描述 JVMTI_ENABLE1 如果 mode为JVMTI_ENABLE,则事件event_type将被启用JVMTI_DISABLE0 如果 mode为JVMTI_DISABLE,则事件event_type将被禁用event_thread为NULL,则事件在全局范围内启用或禁用;否则,它将针对特定线程启用或禁用。如果在线程级别或全局级别启用了事件,则为特定线程生成事件。 有关特定事件的信息,请参见 下面。 以下事件无法通过此函数在线程级别进行控制。VMInitVMStartVMDeathThreadStartVirtualThreadStartCompiledMethodLoadCompiledMethodUnloadDynamicCodeGeneratedDataDumpRequest
参数 名称 类型 描述 模式jvmtiEventModeJVMTI_ENABLE或JVMTI_DISABLE事件类型jvmtiEvent要控制的事件 事件线程jthread要控制的线程 如果 event_thread是NULL,则在全局级别控制事件。......用于未来扩展 错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_INVALID_THREADevent_thread非NULL且不是有效线程。JVMTI_ERROR_THREAD_NOT_ALIVEevent_thread非NULL且不活动(未启动或已终止)。JVMTI_ERROR_ILLEGAL_ARGUMENT尝试对不允许线程级别控制的事件进行线程级别控制。 JVMTI_ERROR_MUST_POSSESS_CAPABILITY未拥有所需的事件启用能力。 JVMTI_ERROR_ILLEGAL_ARGUMENTmode不是jvmtiEventMode。JVMTI_ERROR_INVALID_EVENT_TYPEevent_type不是jvmtiEvent。
生成事件
生成事件以表示VM的当前状态。例如,如果jvmtiError GenerateEvents(jvmtiEnv* env, jvmtiEvent event_type)event_type是JVMTI_EVENT_COMPILED_METHOD_LOAD,则将为每个当前编译的方法发送一个CompiledMethodLoad事件。已加载并现在已卸载的方法不会发送。先前发送的事件历史不会影响此函数发送的事件--例如,每次调用此函数时都会发送所有当前编译的方法。 当代理程序在程序执行开始后附加时可能错过事件时,此函数非常有用;此函数生成错过的事件。 尝试执行Java编程语言代码或JNI函数可能会暂停,直到此函数返回 - 因此不应从发送事件的线程调用任何一个。此函数仅在错过的事件已发送、处理并返回后才返回。事件可能在与事件发生的线程不同的线程上发送。事件的回调必须使用SetEventCallbacks设置,并且必须使用SetEventNotificationMode启用事件,否则事件将不会发生。如果VM不再具有生成所请求事件的某些或全部信息,则简单地不发送这些事件 - 不会返回错误。 仅支持以下事件:能力所需功能可选功能 能力 效果 can_generate_compiled_method_load_events可以在方法编译或卸载时生成事件 参数 名称 类型 描述 event_typejvmtiEvent要生成的事件类型。必须是以下之一:
扩展机制
扩展机制函数: 扩展机制函数类型: 扩展机制类型:jvmtiParamTypes- 扩展函数/事件参数类型jvmtiParamKind- 扩展函数/事件参数种类jvmtiParamInfo- 扩展函数/事件参数信息jvmtiExtensionFunctionInfo- 扩展函数信息jvmtiExtensionEventInfo- 扩展事件信息
扩展函数/事件参数类型( jvmtiParamTypes)常量 值 描述 JVMTI_TYPE_JBYTE101 Java编程语言基本类型 - byte。JNI类型jbyte。JVMTI_TYPE_JCHAR102 Java编程语言基本类型 - char。JNI类型jchar。JVMTI_TYPE_JSHORT103 Java编程语言基本类型 - short。JNI类型jshort。JVMTI_TYPE_JINT104 Java编程语言基本类型 - int。JNI类型jint。JVMTI_TYPE_JLONG105 Java编程语言基本类型 - long。JNI类型jlong。JVMTI_TYPE_JFLOAT106 Java编程语言基本类型 - float。JNI类型jfloat。JVMTI_TYPE_JDOUBLE107 Java编程语言基本类型 - double。JNI类型jdouble。JVMTI_TYPE_JBOOLEAN108 Java编程语言基本类型 - boolean。JNI类型jboolean。JVMTI_TYPE_JOBJECT109 Java编程语言对象类型 - java.lang.Object。JNI类型jobject。返回值是JNI本地引用,必须进行管理。JVMTI_TYPE_JTHREAD110 Java编程语言对象类型 - java.lang.Thread。JVM TI类型jthread。返回值是JNI本地引用,必须进行管理。JVMTI_TYPE_JCLASS111 Java编程语言对象类型 - java.lang.Class。JNI类型jclass。返回值是JNI本地引用,必须进行管理。JVMTI_TYPE_JVALUE112 所有Java编程语言基本和对象类型的联合 - JNI类型 jvalue。表示对象类型的返回值是JNI本地引用,必须进行管理。JVMTI_TYPE_JFIELDID113 Java编程语言字段标识符 - JNI类型 jfieldID。JVMTI_TYPE_JMETHODID114 Java编程语言方法标识符 - JNI类型 jmethodID。JVMTI_TYPE_CCHAR115 C编程语言类型 - char。JVMTI_TYPE_CVOID116 C编程语言类型 - void。JVMTI_TYPE_JNIENV117 JNI环境 - JNIEnv。应与正确的jvmtiParamKind一起使用,使其成为指针类型。扩展函数/事件参数种类( jvmtiParamKind)常量 值 描述 JVMTI_KIND_IN91 传入参数 - foo。JVMTI_KIND_IN_PTR92 传入指针参数 - const foo*。JVMTI_KIND_IN_BUF93 传入数组参数 - const foo*。JVMTI_KIND_ALLOC_BUF94 输出分配的数组参数 - foo**。使用Deallocate释放。JVMTI_KIND_ALLOC_ALLOC_BUF95 输出分配的数组的分配数组参数 - foo***。使用Deallocate释放。JVMTI_KIND_OUT96 输出参数 - foo*。JVMTI_KIND_OUT_BUF97 输出数组参数(由代理预先分配) - foo*。不要Deallocate。扩展函数/事件参数信息
typedef struct { char* 名称; jvmtiParamKind 种类; jvmtiParamTypes 基本类型; jboolean 可空; } jvmtiParamInfo;jvmtiParamInfo- 扩展函数/事件参数信息字段 类型 描述 名称char*参数名称,编码为修改过的UTF-8字符串 种类jvmtiParamKind参数的种类 - 类型修饰符 基本类型jvmtiParamTypes参数的基本类型 - 被 kind修改可空jboolean是否允许 NULL参数?仅适用于指针和对象类型。
扩展函数
这是特定于实现的扩展函数。typedef jvmtiError (JNICALL *jvmtiExtensionFunction) (jvmtiEnv* jvmti_env, ...);参数 名称 类型 描述 jvmti_envjvmtiEnv *JVM 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)能力所需功能jvmtiExtensionFunctionInfo- 扩展函数信息字段 类型 描述 funcjvmtiExtensionFunction要调用的实际函数 idchar*扩展函数的标识符,编码为修改过的UTF-8字符串。使用包名约定。例如, com.sun.hotspot.barshort_descriptionchar*函数的一句话描述,编码为修改过的UTF-8字符串。 param_countjint参数数量,不包括 jvmtiEnv *jvmti_envparamsjvmtiParamInfo *包含 param_count个参数的数组(不包括jvmtiEnv *jvmti_env)error_countjint可能的错误返回数量(不包括通用错误) errorsjvmtiError *包含 error_count个可能错误的数组错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERextension_count_ptr为NULL。JVMTI_ERROR_NULL_POINTERextensions为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)能力所需功能jvmtiExtensionEventInfo- 扩展事件信息字段 类型 描述 extension_event_indexjint事件的标识索引 idchar*扩展事件的标识符,编码为修改后的UTF-8字符串。使用包名约定。例如, com.sun.hotspot.barshort_descriptionchar*事件的一句描述,编码为修改后的UTF-8字符串。 param_countjint参数数量,不包括 jvmtiEnv *jvmti_envparamsjvmtiParamInfo *包含 param_count个参数的数组(不包括jvmtiEnv *jvmti_env)参数 名称 类型 描述 extension_count_ptrjint*返回扩展事件数量的指针 代理传递一个 jint的指针。返回时,jint已被设置。extensionsjvmtiExtensionEventInfo**返回一个扩展事件信息数组,每个事件一个 代理传递一个 jvmtiExtensionEventInfo*的指针。返回时,jvmtiExtensionEventInfo*指向一个新分配的大小为*extension_count_ptr的数组。数组应使用Deallocate释放。在jvmtiExtensionEventInfo的id字段中返回的指针是新分配的数组。数组应使用Deallocate释放。在jvmtiExtensionEventInfo的short_description字段中返回的指针是新分配的数组。数组应使用Deallocate释放。在jvmtiExtensionEventInfo的params字段中返回的指针是新分配的数组。数组应使用Deallocate释放。在jvmtiParamInfo的name字段中返回的指针是新分配的数组。数组应使用Deallocate释放。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERextension_count_ptr为NULL。JVMTI_ERROR_NULL_POINTERextensions为NULL。
扩展事件
这是特定于实现的事件。事件处理程序通过typedef void (JNICALL *jvmtiExtensionEvent) (jvmtiEnv* jvmti_env, ...);SetExtensionEventCallback设置。 扩展事件的事件处理程序必须声明为可变参数以匹配此定义。否则可能导致在某些平台上调用约定不匹配和未定义行为。 例如,如果GetExtensionEvents返回的jvmtiParamInfo指示存在一个jint参数,则事件处理程序应声明为:
注意末尾的"void JNICALL myHandler(jvmtiEnv* jvmti_env, ...)
..."表示可变参数。在myHandler内部需要使用C编程语言的va_*语法提取jint参数。参数 名称 类型 描述 jvmti_envjvmtiEnv *JVM TI环境是扩展事件的唯一固定参数。 ......扩展事件特定的参数
设置扩展事件回调
设置扩展事件的回调函数并启用该事件。或者,如果回调为jvmtiError SetExtensionEventCallback(jvmtiEnv* env, jint extension_event_index, jvmtiExtensionEvent callback)NULL,则禁用该事件。请注意,与标准事件不同,设置回调和启用事件是一个操作。能力所需功能参数 名称 类型 描述 extension_event_indexjint标识要设置的回调。此索引是 extension_event_index字段的jvmtiExtensionEventInfo。callbackjvmtiExtensionEvent如果 callback不为NULL,则将callback设置为事件回调函数并启用事件。 如果callback为NULL,则禁用事件。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_ILLEGAL_ARGUMENTextension_event_index不是extension_event_index由GetExtensionEvents返回的索引。
能力
能力函数: 能力类型:jvmtiCapabilities- 能力结构
- 永远不会被添加
- 可以在OnLoad或任何环境中的live阶段添加
- 仅可在OnLoad阶段添加
- 一次只能由一个环境拥有
- 一次只能由一个环境拥有,并且仅在OnLoad阶段拥有
- 等等...
- 一个虚拟机可能通过将字节码编译成本机代码来执行所有操作,并且无法生成单步执行指令。在这种实现中,无法添加该功能。
- 另一个虚拟机可以随时将执行切换到单步执行解释器。在这种实现中,拥有该功能没有开销,可以随时添加。
- 另一个虚拟机可能能够在启动时选择字节码编译或单步执行能力的解释执行引擎,但无法在它们之间切换。在这种实现中,该功能需要在
OnLoad阶段(在字节码执行开始之前)添加,并且即使从未使用单步执行,它也会对执行速度产生很大影响。 - 另一个虚拟机可能能够在编译的字节码或生成的解释器中添加“单步执行是否开启”的检查。同样,在这种实现中,该功能需要在
OnLoad阶段添加,但开销(在每条指令上进行测试和分支)会大大减少。
OnLoad阶段添加。对于大多数虚拟机,某些功能需要为虚拟机进行特殊设置,并且这些设置必须在虚拟机开始执行之前的OnLoad阶段完成。一旦添加了功能,只有在环境明确放弃时才能移除它。 代理可以确定此VM可能提供的功能,添加要使用的功能,释放不再需要的功能,并检查当前可用的功能。功能示例
例如,一个刚启动的代理(在OnLoad函数中)希望启用所有可能的功能。请注意,一般来说,这是不建议的,因为代理可能会因为未使用的功能而遭受性能损失。代码可能如下所示(使用C语言):
例如,如果代理想要检查是否可以获取方法的字节码(即,它想要检查是否先前添加了此功能并且未放弃),代码可能如下所示(使用C语言):jvmtiCapabilities capa; jvmtiError err; err = (*jvmti)->GetPotentialCapabilities(jvmti, &capa); if (err == JVMTI_ERROR_NONE) { err = (*jvmti)->AddCapabilities(jvmti, &capa);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字段 描述 自 can_tag_objects可以设置和获取标签,如在Heap类别中描述的。 1.0 can_generate_field_modification_events可以在字段修改时设置监视点 - SetFieldModificationWatch1.0 can_generate_field_access_events可以在字段访问时设置监视点 - SetFieldAccessWatch1.0 can_get_bytecodes可以获取方法的字节码 GetBytecodes1.0 can_get_synthetic_attribute可以测试字段或方法是否是合成的 - IsFieldSynthetic和IsMethodSynthetic1.0 can_get_owned_monitor_info可以获取有关监视器所有权的信息 - GetOwnedMonitorInfo1.0 can_get_current_contended_monitor可以 GetCurrentContendedMonitor1.0 can_get_monitor_info可以 GetObjectMonitorUsage1.0 can_pop_frame可以从堆栈中弹出帧 - PopFrame1.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可以 设置 并获取 FramePop事件1.0 can_generate_breakpoint_events可以 设置 并获取 Breakpoint事件1.0 can_suspend可以暂停和恢复线程 1.0 can_redefine_any_classRedefineClasses可以在任何可修改的类上调用。参见IsModifiableClass。(还必须设置can_redefine_classes)1.0 can_get_current_thread_cpu_time可以 获取 当前线程的CPU时间 1.0 can_get_thread_cpu_time可以 获取 线程的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可以从方法中提前返回,如在 Force Early Return类别中描述的。 1.1 can_get_owned_monitor_stack_depth_info可以获取具有堆栈深度的拥有监视器的信息 - GetOwnedMonitorStackDepthInfo1.1 can_get_constant_pool可以获取类的常量池 - GetConstantPool1.1 can_set_native_method_prefix可以设置在无法解析本地方法时应用的前缀 - SetNativeMethodPrefix和SetNativeMethodPrefixes1.1 can_retransform_classes可以使用 RetransformClasses重新转换类。除了特定实现对此功能施加的限制(请参阅 Capability 部分),此功能必须在此环境中首次启用ClassFileLoadHook事件之前设置。在首次启用ClassFileLoadHook时具有此功能的环境被称为 重新转换能力。在首次启用ClassFileLoadHook时不具备此功能的环境被称为 重新转换无能。1.1 can_retransform_any_classRetransformClasses可以在任何可修改的类上调用。参见IsModifiableClass。(还必须设置can_retransform_classes)1.1 can_generate_resource_exhaustion_heap_events可以在VM无法从JavaTM平台堆中分配内存时生成事件。请参见 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可以支持虚拟线程。如果启用了此功能,则可以调用以下函数: SuspendAllVirtualThreads,ResumeAllVirtualThreads,并且可以启用以下事件:VirtualThreadStart,VirtualThreadEnd。21
获取潜在功能
通过jvmtiError 获取潜在功能(jvmtiEnv* env, jvmtiCapabilities* capabilities_ptr)capabilities_ptr返回此环境当前可能拥有的JVM TI功能。返回的功能与VM实现的完整功能集在两种情况下不同:另一个环境拥有只能被一个环境拥有的功能,或者当前阶段是活动的,并且某些功能只能在OnLoad阶段添加。可以使用AddCapabilities函数来设置任何或所有这些功能。当前拥有的功能也会被包括在内。 通常此函数在OnLoad函数中使用。一些虚拟机可能允许在活动阶段添加有限的功能集。在这种情况下,可能可用的功能集可能与OnLoad阶段设置的功能集不同。 参见功能示例。功能所需功能参数 名称 类型 描述 capabilities_ptrjvmtiCapabilities*返回时,指向可能添加的JVM TI功能的指针。 代理传递一个指向 jvmtiCapabilities的指针。返回时,jvmtiCapabilities已被设置。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERcapabilities_ptr为NULL。
添加功能
通过在jvmtiError 添加功能(jvmtiEnv* env, const jvmtiCapabilities* capabilities_ptr)*capabilities_ptr中将值设置为一(1)来设置新功能。所有先前的功能都将保留。通常此函数在OnLoad函数中使用。一些虚拟机可能允许在活动阶段添加有限的功能集。 参见功能示例。功能所需功能参数 名称 类型 描述 capabilities_ptrconst jvmtiCapabilities*指向要添加的JVM TI功能的指针。 代理传递一个指向 jvmtiCapabilities的指针。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_NOT_AVAILABLE所需功能甚至可能不可用。 JVMTI_ERROR_NULL_POINTERcapabilities_ptr为NULL。
放弃功能
通过在jvmtiError 放弃功能(jvmtiEnv* env, const jvmtiCapabilities* capabilities_ptr)*capabilities_ptr中将值设置为一(1)来放弃功能。一些实现可能只允许一个环境拥有一个功能(参见功能介绍)。此函数释放功能,以便其他代理可以使用。所有其他功能都将保留。该功能将不再存在于GetCapabilities中。尝试放弃代理不拥有的功能不会导致错误。功能所需功能参数 名称 类型 描述 capabilities_ptrconst jvmtiCapabilities*指向要放弃的JVM TI功能的指针。 代理传递一个指向 jvmtiCapabilities的指针。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERcapabilities_ptr为NULL。
获取功能
通过jvmtiError 获取功能(jvmtiEnv* env, jvmtiCapabilities* capabilities_ptr)capabilities_ptr返回此环境当前拥有的可选JVM TI功能。每个拥有的功能在功能结构的相应字段中用一(1)表示。除非使用AddCapabilities成功添加,否则环境不拥有功能。只有通过RelinquishCapabilities放弃功能后,环境才会失去功能的拥有权。因此,此函数返回已进行的AddCapabilities和RelinquishCapabilities调用的净结果。 参见功能示例。能力所需功能参数 名称 类型 描述 capabilities_ptrjvmtiCapabilities*返回时,指向JVM TI能力。 代理传递指向 jvmtiCapabilities的指针。返回时,jvmtiCapabilities已设置。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERcapabilities_ptr为NULL。
计时器
计时器函数: 计时器类型:jvmtiTimerInfo- 计时器信息jvmtiTimerKind- 计时器种类
计时器信息
每个计时器的信息函数返回此数据结构。
计时器种类为 --typedef struct { jlong max_value; jboolean may_skip_forward; jboolean may_skip_backward; jvmtiTimerKind kind; jlong reserved1; jlong reserved2; } jvmtiTimerInfo;jvmtiTimerInfo- 计时器信息字段 类型 描述 max_valuejlong计时器可以达到的最大值。达到此值后,计时器将回到零。这是一个无符号值。如果作为jlong(有符号值)进行测试或打印,它可能看起来是一个负数。 may_skip_forwardjboolean如果为true,则计时器可以被外部调整,从而向前跳过。如果为false,则计时器值永远不会比实时增加得更快。 may_skip_backwardjboolean如果为true,则计时器可以被外部调整,从而向后跳过。如果为false,则计时器值将单调增加。 kindjvmtiTimerKind计时器的种类。在不区分用户和系统时间的平台上,返回 JVMTI_TIMER_TOTAL_CPU。reserved1jlong保留供将来使用。 reserved2jlong保留供将来使用。 计时器种类( jvmtiTimerKind)常量 值 描述 JVMTI_TIMER_USER_CPU30 线程在用户模式下的CPU时间。 JVMTI_TIMER_TOTAL_CPU31 线程在用户或系统模式下的CPU时间。 JVMTI_TIMER_ELAPSED32 经过的时间。
获取当前线程CPU计时器信息
获取有关jvmtiError GetCurrentThreadCpuTimerInfo(jvmtiEnv* env, jvmtiTimerInfo* info_ptr)GetCurrentThreadCpuTime计时器的信息。填充jvmtiTimerInfo结构的字段,其中包含有关计时器的详细信息。此信息特定于平台和GetCurrentThreadCpuTime的实现,因此不会因线程或VM的特定调用而变化。 请注意,GetCurrentThreadCpuTime和GetThreadCpuTime的实现可能不同,因此GetCurrentThreadCpuTimerInfo返回的值可能与GetThreadCpuTimerInfo返回的值不同 -- 有关更多信息,请参阅GetCurrentThreadCpuTime。能力可选功能:可能不适用于所有虚拟机。必须具备以下能力(由GetCapabilities返回)才能使用此函数。能力 效果 can_get_current_thread_cpu_time可以获取当前线程CPU时间。 参数 名称 类型 描述 info_ptrjvmtiTimerInfo*返回时,填充有关由 GetCurrentThreadCpuTime返回的时间的信息。 代理传递指向jvmtiTimerInfo的指针。返回时,jvmtiTimerInfo已设置。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_get_current_thread_cpu_time能力。使用AddCapabilities。JVMTI_ERROR_NULL_POINTERinfo_ptr为NULL。
获取当前线程CPU时间
返回当前线程使用的CPU时间。 请注意,jvmtiError GetCurrentThreadCpuTime(jvmtiEnv* env, jlong* nanos_ptr)GetThreadCpuTime函数为任何线程提供CPU时间,包括当前线程。GetCurrentThreadCpuTime用于支持无法为除当前线程外的其他线程提供CPU时间或对当前线程具有更准确信息的平台(请参见GetCurrentThreadCpuTimerInfo与GetThreadCpuTimerInfo)。当当前线程是虚拟线程时,不需要支持此函数的实现,在这种情况下将返回JVMTI_ERROR_UNSUPPORTED_OPERATION。在许多平台上,此调用将等效于:GetThreadCpuTime(env, NULL, nanos_ptr)
只能在启动或活动阶段调用1351.0能力可选功能:可能不会为所有虚拟机实现。必须通过GetCapabilities返回的以下能力才能使用此函数。能力 效果 can_get_current_thread_cpu_time可以获取当前线程的CPU时间。 如果在线程启动后启用此功能,则实现可以选择任何时间,直到并包括启用功能的时间作为CPU时间收集开始的时间点。 此功能必须在任何可能支持 can_get_thread_cpu_time的平台上潜在可用。参数 名称 类型 描述 nanos_ptrjlong*返回时,指向线程使用的CPU时间(以纳秒为单位)。这是一个无符号值。如果作为jlong(有符号值)进行测试或打印,它可能看起来是一个负数。 代理传递一个指向 的指针。返回时, 已设置。 错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_get_current_thread_cpu_time。使用AddCapabilities。JVMTI_ERROR_UNSUPPORTED_OPERATION当前线程是虚拟线程,且实现不支持在当前线程为虚拟线程时获取当前线程的CPU时间。 JVMTI_ERROR_NULL_POINTERnanos_ptr为NULL。
获取线程CPU计时器信息
获取有关jvmtiError GetThreadCpuTimerInfo(jvmtiEnv* env, jvmtiTimerInfo* info_ptr)GetThreadCpuTime计时器的信息。jvmtiTimerInfo结构的字段将填充有关计时器的详细信息。此信息特定于平台和GetThreadCpuTime的实现,因此不会因线程而异,也不会在VM的特定调用期间变化。 请注意,GetCurrentThreadCpuTime和GetThreadCpuTime的实现可能不同,因此GetCurrentThreadCpuTimerInfo和GetThreadCpuTimerInfo返回的值可能不同--请参见GetCurrentThreadCpuTime获取更多信息。能力可选功能:可能不会为所有虚拟机实现。必须通过GetCapabilities返回的以下能力才能使用此函数。能力 效果 can_get_thread_cpu_time可以获取线程CPU时间。 参数 名称 类型 描述 info_ptrjvmtiTimerInfo*返回时,填充有关 GetThreadCpuTime返回的时间的信息。 代理传递一个指向的指针。返回时, 已设置。 错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备能力 can_get_thread_cpu_time。使用AddCapabilities。JVMTI_ERROR_NULL_POINTERinfo_ptr为NULL。
获取线程CPU时间
返回指定线程使用的CPU时间。 使用jvmtiError GetThreadCpuTime(jvmtiEnv* env, jthread thread, jlong* nanos_ptr)GetThreadCpuTimerInfo获取有关此计时器的信息。能力可选功能:可能不会为所有虚拟机实现。必须通过GetCapabilities返回的以下能力才能使用此函数。能力 效果 can_get_thread_cpu_time可以获取线程CPU时间。 如果在线程启动后启用此功能,则实现可以选择任何时间,直到并包括启用功能的时间作为CPU时间收集开始的时间。 参数 名称 类型 描述 线程jthread要查询的线程。当给定线程是虚拟线程时,实现不需要支持此功能,此时将返回 JVMTI_ERROR_UNSUPPORTED_OPERATION。如果thread为NULL,则使用当前线程。nanos_ptrjlong*返回指定线程使用的CPU时间(以纳秒为单位)。这是一个无符号值。如果作为jlong(有符号值)进行测试或打印,它可能看起来是一个负数。 代理传递一个指向 jlong的指针。返回时,jlong已被设置。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_get_thread_cpu_time能力。使用AddCapabilities。JVMTI_ERROR_UNSUPPORTED_OPERATIONthread是虚拟线程,且实现不支持获取虚拟线程的线程CPU时间。JVMTI_ERROR_INVALID_THREADthread不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVEthread不活动(尚未启动或已终止)。JVMTI_ERROR_NULL_POINTERnanos_ptr为NULL。
获取计时器信息
获取有关jvmtiError GetTimerInfo(jvmtiEnv* env, jvmtiTimerInfo* info_ptr)GetTime计时器的信息。jvmtiTimerInfo结构的字段将填充有关计时器的详细信息。此信息在VM的特定调用期间不会更改。可在任何阶段调用1381.0能力所需功能参数 名称 类型 描述 info_ptrjvmtiTimerInfo*返回时,填充有关 GetTime返回的时间的信息。 代理传递一个指向jvmtiTimerInfo的指针。返回时,jvmtiTimerInfo已被设置。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERinfo_ptr为NULL。
获取时间
返回系统计时器的当前值,以纳秒为单位。 返回的值表示自某个固定但任意的时间以来的纳秒数(也许是未来的某个时间,因此值可能为负)。此函数提供纳秒精度,但不一定提供纳秒精确度。不保证值的变化频率。 使用jvmtiError GetTime(jvmtiEnv* env, jlong* nanos_ptr)GetTimerInfo获取有关此计时器的信息。可在任何阶段调用1391.0能力所需功能参数 名称 类型 描述 nanos_ptrjlong*返回时,指向纳秒时间的指针。这是一个无符号值。如果作为jlong(有符号值)进行测试或打印,它可能看起来是一个负数。 代理传递一个指向 jlong的指针。返回时,jlong已被设置。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERnanos_ptr为NULL。
获取可用处理器数
返回Java虚拟机可用的处理器数量。 此值可能在虚拟机的特定调用期间更改。因此,对处理器数量敏感的应用程序应偶尔轮询此属性。jvmtiError GetAvailableProcessors(jvmtiEnv* env, jint* processor_count_ptr)能力所需功能参数 名称 类型 描述 processor_count_ptrjint*返回时,指向虚拟机可用的处理器数量的最大值;永远不会小于一。 代理传递一个指向 jint的指针。返回时,jint已被设置。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERprocessor_count_ptr为NULL。
类加载器搜索
类加载器搜索函数: 这些函数允许代理程序添加类加载器搜索类的位置。这对于在正确的类加载器下安装仪器很有用。
添加到引导类加载器搜索
此函数可用于使仪器类由引导类加载器定义。参见 Java™虚拟机规范,第5.3.1章。在引导类加载器未成功搜索类之后,还将搜索指定的平台相关搜索路径jvmtiError AddToBootstrapClassLoaderSearch(jvmtiEnv* env, const char* segment)segment。只能在segment中指定一个段。可以多次调用此函数以添加多个段,这些段将按照调用此函数的顺序进行搜索。 在OnLoad阶段,此函数可用于指定在引导类加载器未成功搜索类之后要搜索的任何平台相关搜索路径段。该段通常是目录或JAR文件。 在实时阶段,segment可用于指定任何平台相关路径到 JAR文件。代理程序应注意,JAR文件不应包含任何除了为仪器目的而由引导类加载器定义的类或资源之外的内容。 Java™虚拟机规范 指定,对先前未能成功解析的符号引用进行后续尝试始终会以与初始解析尝试导致的错误相同的错误失败。因此,如果JAR文件包含与Java虚拟机先前未能成功解析引用相对应的条目,则后续尝试解析该引用将以与初始尝试相同的错误失败。功能所需功能参数 名称 类型 描述 segmentconst char*平台相关的搜索路径段,编码为修改的UTF-8字符串。 代理程序传入一个 char数组。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_ILLEGAL_ARGUMENTsegment是无效路径。在实时阶段,除了现有的JAR文件之外的任何内容都是无效路径。JVMTI_ERROR_NULL_POINTERsegment为NULL。
添加到系统类加载器搜索
此函数可用于使仪器类由系统类加载器定义。参见 Java™虚拟机规范,第5.3.2章。在类加载器未成功搜索类之后,还将搜索指定的平台相关搜索路径jvmtiError AddToSystemClassLoaderSearch(jvmtiEnv* env, const char* segment)segment。只能在segment中指定一个段。可以多次调用此函数以添加多个段,这些段将按照调用此函数的顺序进行搜索。 在OnLoad阶段,此函数可用于指定在系统类加载器未成功搜索类之后要搜索的任何平台相关搜索路径段。该段通常是目录或JAR文件。 在实时阶段,segment是一个平台相关的路径到 JAR文件,用于在系统类加载器未成功搜索类之后进行搜索。代理程序应注意,JAR文件不应包含任何除了为系统类加载器定义的类或资源之外的内容。 在实时阶段,系统类加载器支持添加要搜索的JAR文件,如果系统类加载器实现了一个名为appendToClassPathForInstrumentation的方法,该方法接受一个类型为java.lang.String的参数。该方法不需要具有public访问权限。 Java™虚拟机规范 指定,对先前未能成功解析的符号引用进行后续尝试始终会以与初始解析尝试导致的错误相同的错误失败。因此,如果JAR文件包含与Java虚拟机先前未能成功解析引用相对应的条目,则后续尝试解析该引用将以与初始尝试相同的错误失败。功能所需功能错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_ILLEGAL_ARGUMENTsegment是无效路径。在实时阶段,除了现有的JAR文件之外的任何内容都是无效路径。JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED系统类加载器不支持此操作。 JVMTI_ERROR_NULL_POINTERsegment为NULL。
系统属性
系统属性函数: 这些函数获取和设置系统属性。
获取系统属性
可用于与jvmtiError GetSystemProperties(jvmtiEnv* env, jint* count_ptr, char*** property_ptr)GetSystemProperty被返回。强烈建议虚拟机提供以下属性键:java.vm.vendorjava.vm.versionjava.vm.namejava.vm.infojava.library.pathjava.class.path
java.lang.System.getProperties中的属性集不同。JNI方法调用可用于访问java.lang.System.getProperties。 属性集在执行过程中可能会增长。能力所需功能参数 名称 类型 描述 count_ptrjint*返回时,指向返回的属性键数。 代理传递一个指向 jint的指针。返回时,jint已设置。property_ptrchar***返回时,指向以 修改的UTF-8 字符串编码的属性键数组。 代理传递一个指向 char**的指针。返回时,char**指向一个新分配的大小为*count_ptr的数组,其中每个元素也是新分配的。应使用Deallocate释放数组。每个元素应使用Deallocate释放。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERcount_ptr为NULL。JVMTI_ERROR_NULL_POINTERproperty_ptr为NULL。
获取系统属性
根据属性键返回VM系统属性值。 函数jvmtiError GetSystemProperty(jvmtiEnv* env, const char* property, char** value_ptr)GetSystemProperties返回可用的属性键集。可以在执行过程中获取的属性可能会增长。 由于这是系统属性的虚拟机视图,属性的值可能与java.lang.System.getProperty(String)返回的值不同。典型的虚拟机可能会在该类的初始化期间将VM系统属性的值复制到java.lang.System持有的Properties中。此后,对VM系统属性(使用SetSystemProperty)或java.lang.System系统属性(使用java.lang.System.setProperty(String,String))的任何更改都会导致值不同。JNI方法调用可用于访问java.lang.System.getProperty(String)。能力所需功能修改的UTF-8 字符串。 代理传递一个 char数组。参数 名称 类型 描述 propertyconst char*value_ptrchar**返回时,指向属性值,编码为 修改的UTF-8 字符串。 代理传递一个指向 char*的指针。返回时,char*指向一个新分配的数组。应使用Deallocate释放数组。GetSystemProperties查找可用属性。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_NOT_AVAILABLEJVMTI_ERROR_NULL_POINTERproperty为NULL。JVMTI_ERROR_NULL_POINTERvalue_ptr为NULL。
设置系统属性
设置VM系统属性值。 函数jvmtiError SetSystemProperty(jvmtiEnv* env, const char* property, const char* value_ptr)GetSystemProperties返回属性键集,其中一些可能是可设置的。请参见GetSystemProperty。能力所需功能修改的UTF-8 字符串。 代理传递一个 char数组。修改的UTF-8 字符串。 代理传递一个 char数组。如果value_ptr为NULL,则不设置该值,但如果属性不可写,则返回JVMTI_ERROR_NOT_AVAILABLE。参数 名称 类型 描述 propertyconst char*value_ptrconst char *错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_NOT_AVAILABLEJVMTI_ERROR_NULL_POINTERproperty为NULL。
通用
通用函数: 通用类型:jvmtiPhase- 执行阶段jvmtiVerboseFlag- 详细标志枚举jvmtiJlocationFormat- JLocation格式枚举
获取阶段
返回当前VM执行阶段。阶段按顺序进行: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)常量 值 描述 JVMTI_PHASE_ONLOAD1 OnLoad阶段: 在Agent_OnLoad或者对于静态链接的代理,在Agent_OnLoad_<agent-lib-name>函数中。JVMTI_PHASE_PRIMORDIAL2 原始阶段: 在 Agent_OnLoad或者Agent_OnLoad_<agent-lib-name>返回后,以及VMStart事件之前。JVMTI_PHASE_START6 开始阶段: 当发送 VMStart事件时,直到发送VMInit事件为止。JVMTI_PHASE_LIVE4 活动阶段: 当发送 VMInit事件时,直到VMDeath事件返回为止。JVMTI_PHASE_DEAD8 死亡阶段: 在 VMDeath事件返回后或者启动失败后。VMInit事件,也不会发送VMDeath事件。 大多数JVM TI函数仅在活动阶段操作。以下函数在OnLoad或活动阶段操作:- CreateRawMonitor
- DestroyRawMonitor
- SetEventCallbacks
- SetEventNotificationMode
- GetExtensionFunctions
- GetExtensionEvents
- SetExtensionEventCallback
- GetPotentialCapabilities
- AddCapabilities
- RelinquishCapabilities
- AddToBootstrapClassLoaderSearch
- AddToSystemClassLoaderSearch
- GetSystemProperties
- GetSystemProperty
- SetHeapSamplingInterval
OnLoad阶段操作: 以下函数在启动或活动阶段操作:- GetCurrentThread
- SetThreadLocalStorage
- GetThreadLocalStorage
- GetTag
- SetTag
- GetClassSignature
- GetClassStatus
- GetSourceFileName
- GetClassModifiers
- GetClassMethods
- GetClassFields
- GetImplementedInterfaces
- GetClassVersionNumbers
- GetConstantPool
- IsInterface
- IsArrayClass
- IsModifiableClass
- GetClassLoader
- GetSourceDebugExtension
- GetObjectSize
- GetObjectHashCode
- GetFieldName
- GetFieldDeclaringClass
- GetFieldModifiers
- IsFieldSynthetic
- GetMethodName
- GetMethodDeclaringClass
- GetMethodModifiers
- GetMaxLocals
- GetArgumentsSize
- GetLineNumberTable
- GetMethodLocation
- GetBytecodes
- IsMethodNative
- IsMethodSynthetic
- IsMethodObsolete
- SetJNIFunctionTable
- GetJNIFunctionTable
- GetCurrentThreadCpuTimerInfo
- GetCurrentThreadCpuTime
- Allocate
- Deallocate
- SetNativeMethodPrefix
- SetNativeMethodPrefixes
- RawMonitorEnter
- RawMonitorExit
- RawMonitorWait
- RawMonitorNotify
- RawMonitorNotifyAll
- GetCapabilities
- GetTimerInfo
- GetTime
- GetAvailableProcessors
- 获取阶段
- 销毁环境
- 设置环境本地存储
- 获取环境本地存储
- 获取版本号
- 获取错误名称
- 设置详细标志
- 获取JLocation格式
- ThreadStart
- ThreadEnd
- VirtualThreadStart
- VirtualThreadEnd
- ClassLoad
- ClassPrepare
- VMStart
- CompiledMethodLoad
- CompiledMethodUnload
能力所需功能参数 名称 类型 描述 phase_ptrjvmtiPhase*返回时,指向阶段。 代理传递指向 jvmtiPhase的指针。返回时,jvmtiPhase已设置。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERphase_ptr为NULL。
释放环境
关闭JVM 通过JNI创建的TI连接jvmtiError DisposeEnvironment(jvmtiEnv* env)
GetEnv(参见JVM TI环境)。释放环境持有的任何资源。此环境挂起的线程不会在此调用中恢复,代理必须显式地执行此操作。通过此环境调用JVM分配的内存不会被释放,代理可以通过调用Deallocate来显式释放。通过此环境创建的原始监视器不会被销毁,代理可以通过调用DestroyRawMonitor来显式销毁。等待此环境创建的原始监视器的线程状态不受影响。 此环境的任何本地方法前缀将被取消设置;代理必须在调用dispose之前删除任何带前缀的本地方法。 此环境持有的任何功能将被放弃。 由此环境启用的事件将不再发送,但当前正在运行的事件处理程序将继续运行。在设计事件处理程序时必须谨慎,因为它们的环境可能在执行过程中被释放,从而变得无效。 此调用后不得再使用此环境。此调用返回给调用者。功能所需功能参数无错误此函数返回一个通用错误
设置环境本地存储
VM存储与每个环境关联的指针值。此指针值称为环境本地存储。除非使用此函数设置,否则此值为jvmtiError SetEnvironmentLocalStorage(jvmtiEnv* env, const void* data)NULL。代理可以分配内存来存储特定于环境的信息。通过设置环境本地存储,可以使用GetEnvironmentLocalStorage来访问它。 代理调用此函数来设置JVM TI环境本地存储的值。JVM TI向代理提供一个指针大小的环境本地存储,可用于记录每个环境的信息。可在任何阶段调用1481.0功能所需功能参数 名称 类型 描述 dataconst void *要输入到环境本地存储中的值。 代理传入一个指针。如果 data为NULL,则值设置为NULL。错误此函数返回一个通用错误
获取环境本地存储
代理调用此函数以获取JVM TI环境本地存储的值。jvmtiError GetEnvironmentLocalStorage(jvmtiEnv* env, void** data_ptr)可在任何阶段调用1471.0功能所需功能参数 名称 类型 描述 data_ptrvoid**用于返回环境本地存储值的指针。如果未使用 SetEnvironmentLocalStorage设置环境本地存储,则返回的指针为NULL。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERdata_ptr为NULL。
获取版本号
通过jvmtiError GetVersionNumber(jvmtiEnv* env, jint* version_ptr)version_ptr返回JVM TI版本。返回值是版本标识符。版本标识符包括主要、次要和微版本号以及接口类型。版本接口类型 常量 值 描述 JVMTI_VERSION_INTERFACE_JNI0x00000000 JVMTI_VERSION_MASK_INTERFACE_TYPE用于JNI的值。JVMTI_VERSION_INTERFACE_JVMTI0x30000000 JVMTI_VERSION_MASK_INTERFACE_TYPE用于JVM TI的值。版本掩码 常量 值 描述 JVMTI_VERSION_MASK_INTERFACE_TYPE0x70000000 用于提取接口类型的掩码。此函数返回的版本值与 JVMTI_VERSION_MASK_INTERFACE_TYPE掩码相与的值始终为JVMTI_VERSION_INTERFACE_JVMTI,因为这是一个JVM TI函数。JVMTI_VERSION_MASK_MAJOR0x0FFF0000 用于提取主要版本号的掩码。 JVMTI_VERSION_MASK_MINOR0x0000FF00 用于提取次要版本号的掩码。 JVMTI_VERSION_MASK_MICRO0x000000FF 用于提取微版本号的掩码。 版本转换 常量 数值 描述 JVMTI_VERSION_SHIFT_MAJOR16 用于提取主版本号。 JVMTI_VERSION_SHIFT_MINOR8 用于提取次版本号。 JVMTI_VERSION_SHIFT_MICRO0 用于提取微版本号。 能力所需功能参数 名称 类型 描述 version_ptrjint*返回时,指向JVM TI版本的指针。 代理传递一个指向 jint的指针。 返回时,jint已被设置。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERversion_ptr为NULL。
获取错误名称
返回一个 错误代码 的符号名称。 例如jvmtiError GetErrorName(jvmtiEnv* env, jvmtiError error, char** name_ptr)GetErrorName(env, JVMTI_ERROR_NONE, &err_name)将在err_name中返回字符串"JVMTI_ERROR_NONE"。能力所需功能参数 名称 类型 描述 errorjvmtiError错误代码。 name_ptrchar**返回时,指向错误名称。 名称被编码为修改的UTF-8字符串,但限制为ASCII子集。 代理传递一个指向 char*的指针。 返回时,char*指向一个新分配的数组。 应使用Deallocate释放数组。错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_ILLEGAL_ARGUMENTerror不是jvmtiError。JVMTI_ERROR_NULL_POINTERname_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)常量 数值 描述 JVMTI_VERBOSE_OTHER0 除以下内容之外的详细输出。 JVMTI_VERBOSE_GC1 详细的垃圾收集器输出,类似于使用 -verbose:gc指定的内容。JVMTI_VERBOSE_CLASS2 详细的类加载输出,类似于使用 -verbose:class指定的内容。JVMTI_VERBOSE_JNI4 详细的JNI输出,类似于使用 -verbose:jni指定的内容。stderr的输出。能力所需功能参数 名称 类型 描述 flagjvmtiVerboseFlag要设置的详细标志。 valuejboolean标志的新值。 错误此函数返回一个通用错误或以下错误之一错误 描述 JVMTI_ERROR_ILLEGAL_ARGUMENTflag不是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)常量 值 描述 JVMTI_JLOCATION_JVMBCI1 jlocation值表示虚拟机字节码索引--即方法的虚拟机代码偏移量。JVMTI_JLOCATION_MACHINEPC2 jlocation值表示本机机器程序计数器值。JVMTI_JLOCATION_OTHER0 jlocation值具有其他表示。能力所需功能参数 名称 类型 描述 format_ptrjvmtiJlocationFormat*返回时,指向 jlocation值的格式标识符。 代理传递一个指向jvmtiJlocationFormat的指针。返回时,jvmtiJlocationFormat已设置。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_NULL_POINTERformat_ptr为NULL。
堆监控
堆监控函数:
设置堆采样间隔
当分配对象时生成一个jvmtiError SetHeapSamplingInterval(jvmtiEnv* env, jint sampling_interval)SampledObjectAlloc事件。每个线程保留一个已分配字节的计数器。仅当该计数器超过自上次采样以来的平均sampling_interval时,才会生成事件。 将sampling_interval设置为 0 将导致每次分配都会生成一个事件,一旦新间隔生效。 请注意,更新新的采样间隔可能需要各种分配次数来引发内部数据结构的更新。因此,重要的是将采样间隔视为平均值。这包括间隔为 0 的情况,即事件可能不会立即为每次分配生成。能力可选功能: 可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此函数。能力 效果 can_generate_sampled_object_alloc_events可以生成采样分配事件。如果启用了此功能,则可以调用堆采样方法 SetHeapSamplingInterval并生成SampledObjectAlloc事件。参数 名称 类型 描述 sampling_intervaljint以字节为单位的采样间隔。采样器使用统计方法,平均每个给定线程分配的内存字节数为 sampling_interval时生成一个事件。 一旦考虑了新的采样间隔,将 0 作为采样间隔将为每次分配生成一个样本。 注意:此功能的开销与采样间隔直接相关。较高的采样间隔,例如 1024 字节,将产生较高的开销。较低的间隔,例如 1024KB,将具有较低的开销。采样应仅在了解可能影响性能的情况下使用。错误此函数返回通用错误或以下错误之一错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY环境不具备 can_generate_sampled_object_alloc_events能力。请使用AddCapabilities。JVMTI_ERROR_ILLEGAL_ARGUMENTsampling_interval小于零。
错误
每个 JVM TI 函数都返回一个jvmtiError错误代码。 代理有责任使用有效参数并在正确的上下文(调用线程已附加,阶段正确等)调用 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) - 提供的 JVM 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返回以下错误 TI函数。在代理传递的参数无效或在无效上下文中使用时,将返回这些错误。不需要检测这些错误的实现。-
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) - 此实现中不支持该功能。
Data Types
JVM TI扩展了JNI定义的数据类型。JVM工具接口中使用的JNI类型 类型 描述 jbooleanjcharjintjlongjfloatjdoublejobjectjclassjvaluejfieldIDjmethodIDJNIEnvJVM工具接口基本类型 类型 描述 jvmtiEnvjthreadjobject的子类型,保存线程。typedef jobject jthread;
jthreadGroupjobject的子类型,保存线程组。typedef jobject jthreadGroup;
jlocationtypedef jlong jlocation;
jrawMonitorIDstruct _jrawMonitorID; typedef struct _jrawMonitorID *jrawMonitorID;
jvmtiError保存错误返回代码。查看可能的值的错误部分。typedef enum { JVMTI_ERROR_NONE = 0, JVMTI_ERROR_INVALID_THREAD = 10, ... } jvmtiError;jvmtiEvent事件类型的标识符。查看可能的值的事件部分。保证此规范的未来版本永远不会将零分配为事件类型标识符。typedef enum { JVMTI_EVENT_SINGLE_STEP = 1, JVMTI_EVENT_BREAKPOINT = 2, ... } jvmtiEvent;jvmtiEventCallbacks用于事件的回调。
查看完整结构的事件回调。 例如,VM初始化回调的定义如下:typedef struct { jvmtiEventVMInit VMInit; jvmtiEventVMDeath VMDeath; ... } jvmtiEventCallbacks;
查看各个事件以获取回调函数定义。typedef void (JNICALL *jvmtiEventVMInit) (jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread);jniNativeInterfacetypedef struct JNINativeInterface_ jniNativeInterface;
结构类型定义 类型 描述 jvmtiAddrLocationMap本机地址到位置条目 jvmtiCapabilities功能结构 jvmtiClassDefinition类重定义描述 jvmtiExtensionEventInfo扩展事件信息 jvmtiExtensionFunctionInfo扩展函数信息 jvmtiFrameInfo堆栈帧信息结构 jvmtiHeapCallbacks堆回调函数结构 jvmtiHeapReferenceInfo引用信息结构 jvmtiHeapReferenceInfoArray数组引用信息结构 jvmtiHeapReferenceInfoConstantPool常量池引用信息结构 jvmtiHeapReferenceInfoField字段引用信息结构 jvmtiHeapReferenceInfoJniLocalJNI本地引用信息结构 jvmtiHeapReferenceInfoReserved其他引用信息结构 jvmtiHeapReferenceInfoStackLocal本地变量引用信息结构 jvmtiLineNumberEntry行号表条目 jvmtiLocalVariableEntry本地变量表条目 jvmtiMonitorStackDepthInfo监视器堆栈深度信息结构 jvmtiMonitorUsage对象监视器使用信息 jvmtiParamInfo扩展函数/事件参数信息 jvmtiStackInfo堆栈信息结构 jvmtiThreadGroupInfo线程组信息结构 jvmtiThreadInfo线程信息结构 jvmtiTimerInfo定时器信息 函数类型定义 类型 描述 jvmtiArrayPrimitiveValueCallback数组原始值回调 jvmtiExtensionEvent扩展事件 jvmtiExtensionFunction扩展函数 jvmtiHeapIterationCallback堆迭代回调 jvmtiHeapObjectCallback堆对象回调 jvmtiHeapReferenceCallback堆引用回调 jvmtiHeapRootCallback堆根对象回调 jvmtiObjectReferenceCallback对象引用回调 jvmtiPrimitiveFieldCallback原始字段回调 jvmtiReservedCallback保留供将来使用回调 jvmtiStackReferenceCallback堆栈引用对象回调 jvmtiStartFunction代理启动函数 jvmtiStringPrimitiveValueCallback字符串原始值回调 枚举定义 类型 描述 jvmtiEventMode事件启用/禁用 jvmtiHeapObjectFilter堆对象过滤枚举 jvmtiHeapReferenceKind堆引用枚举 jvmtiHeapRootKind堆根种类枚举 jvmtiIterationControl迭代控制枚举 jvmtiJlocationFormatJLocation格式枚举 jvmtiObjectReferenceKind对象引用枚举 jvmtiParamKind扩展函数/事件参数种类 jvmtiParamTypes扩展函数/事件参数类型 jvmtiPhase执行阶段 jvmtiPrimitiveType原始类型枚举 jvmtiTimerKind计时器种类 jvmtiVerboseFlag详细标志枚举 功能表布局 位置 功能 声明 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 获取本地变量 - 整数 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 获取本地变量 - 浮点数 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 设置本地变量 - 整数 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 设置本地变量 - 浮点数 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 强制提前返回 - 整数 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 添加到引导类加载器搜索路径 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指定一组回调函数。对于每个事件,将调用相应的回调函数。回调函数的参数提供有关事件的其他信息。 回调函数通常从应用程序线程内调用。 JVM TI 实现不以任何方式排队事件。这意味着事件回调函数必须小心编写。以下是一些一般指导原则。有关更多建议,请参阅各个事件描述。- 在执行事件回调期间抛出的任何异常都可以覆盖当前应用程序线程中的任何当前挂起异常。在事件回调函数进行可能生成异常的 JNI 调用时,必须小心保留挂起异常。
- 事件回调函数必须是可重入的。JVM TI 实现不排队事件。如果代理需要逐个处理事件,可以在事件回调函数内部使用原始监视器来序列化事件处理。
- 执行 JNI 的 FindClass 函数以加载类的事件回调函数需要注意,FindClass 定位与当前本机方法关联的类加载器。对于类加载而言,将包含 JNI 环境作为回调函数参数的事件回调函数将被视为是本机调用,其中本机方法位于事件线程当前帧的类中。
SuspendThread明确挂起线程。 如果一个事件在多个环境中启用,则事件将按照创建环境的顺序发送给每个代理。启用事件
所有事件最初都是禁用的。为了接收任何事件:- 如果事件需要某种能力,则必须使用
AddCapabilities添加该能力。 - 必须使用
SetEventCallbacks设置事件的回调。 - 必须使用
SetEventNotificationMode启用事件。
多个共同位置的事件
在许多情况下,可能会在一个线程中的同一位置发生多个事件。当这种情况发生时,所有事件都按照本节中指定的顺序通过事件回调报告。 如果当前位置位于方法的入口点,则MethodEntry事件将在同一线程中当前位置的任何其他事件之前报告。 如果在当前位置检测到异常捕获,要么是因为它是 catch 子句的开始,要么是清除了挂起异常的本机方法已返回,则exceptionCatch事件将在同一线程中当前位置的任何其他事件之前报告。 如果在当前位置触发了singleStep事件或breakpoint事件,则事件被定义为在执行当前位置的代码之前立即发生。这些事件将在同一线程中当前位置的代码执行触发的任何事件之前报告(具体来说:exception、fieldAccess和fieldModification)。如果为同一线程和位置触发了步进和断点事件,则步进事件将在断点事件之前报告。 如果当前位置是方法的退出点(即,在返回到调用者之前的最后位置),则MethodExit事件和FramePop事件(如果已请求)将在同一线程中当前位置的所有其他事件之后报告。这两个事件之间没有指定的顺序。 在同一线程中的同一位置的某些其他事件处理期间,可以触发共同位置的事件。如果在处理类型为 y 的事件时触发了类型为 x 的事件,并且 x 在上述指定的顺序中位于 y 之前,则将为当前线程和位置报告共同位置的事件 y。如果 x 不在 y 之前,则不会为当前线程和位置报告 y。例如,在处理SingleStep时设置断点,该断点将在线程移动到当前位置之前报告。 以下事件永远不被视为与其他事件共同位置。VMStartVMInitVMDeathThreadStartThreadEndVirtualThreadStartVirtualThreadEndClassLoadClassPrepare
事件回调
下面的事件回调结构用于指定事件的处理程序函数。它使用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;
事件索引
- 断点
- 类文件加载挂钩
- 类加载
- 类准备
- 编译方法加载
- 编译方法卸载
- 数据转储请求
- 动态生成代码
- 异常
- 异常捕获
- 字段访问
- 字段修改
- 帧弹出
- 垃圾回收完成
- 垃圾回收开始
- 方法进入
- 方法退出
- 监视器争用进入
- 监视器争用已进入
- 监视器等待
- 监视器等待完成
- 本机方法绑定
- 对象释放
- 资源耗尽
- 采样对象分配
- 单步
- 线程结束
- 线程开始
- 虚拟线程结束
- 虚拟线程开始
- VM 死亡事件
- VM 初始化事件
- VM 对象分配
- VM 启动事件
单步
单步事件允许代理以VM允许的最细粒度跟踪线程执行。每当线程到达新位置时,将生成单步事件。通常,单步事件代表了如《Java™虚拟机规范》中定义的一个VM指令的完成。然而,一些实现可能会以不同方式定义位置。无论如何,void JNICALL SingleStep(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method, jlocation location)method和location参数唯一标识当前位置,并在可用时允许将其映射到源文件和行号。 Java™虚拟机规范。没有单步事件会从本地方法内部生成。 单步事件不会从本地方法内部生成。能力可选功能:可能并非所有虚拟机都实现了。必须通过GetCapabilities返回的以下能力才能使用此事件。能力 效果 can_generate_single_step_events可以获取单步事件 参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境 threadjthread即将执行新指令的线程 methodjmethodID即将执行新指令的方法 locationjlocation新指令的位置
断点
每当线程到达被指定为断点的位置时,将生成断点事件。方法和位置参数唯一标识当前位置,并在可用时允许将其映射到源文件和行号。void JNICALL Breakpoint(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method, jlocation location)SetBreakpoint。能力可选功能:可能并非所有虚拟机都实现了。必须通过GetCapabilities返回的以下能力才能使用此事件。能力 效果 can_generate_breakpoint_events可以设置并获取 Breakpoint事件参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境。 threadjthread触发断点的线程 methodjmethodID触发断点的方法 locationjlocation断点的位置
字段访问
每当线程访问被指定为观察点的字段时,将生成字段访问事件。方法和位置参数唯一标识当前位置,并在可用时允许将其映射到源文件和行号。void JNICALL FieldAccess(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method, jlocation location, jclass field_klass, jobject object, jfieldID field)SetFieldAccessWatch。能力可选功能:可能并非所有虚拟机都实现了。必须通过GetCapabilities返回的以下能力才能使用此事件。能力 效果 can_generate_field_access_events可以在字段访问上设置观察点 - SetFieldAccessWatch参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境 threadjthread访问字段的线程 methodjmethodID发生访问的方法 locationjlocation发生访问的位置 field_klassjclass被访问字段的类 objectjobject访问字段的对象(如果字段是实例字段);否则为 NULLfieldjfieldID被访问的字段
字段修改
每当线程修改被指定为观察点的字段时,将生成字段修改事件。方法和位置参数唯一标识当前位置,并在可用时允许将其映射到源文件和行号。void JNICALL FieldModification(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method, jlocation location, jclass field_klass, jobject object, jfieldID field, char signature_type, jvalue new_value)SetFieldModificationWatch。方法和位置参数唯一标识当前位置,并在可用时允许将其映射到源文件和行号。能力可选功能:可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此事件。能力 效果 can_generate_field_modification_events可以在字段修改上设置监视点 - SetFieldModificationWatch参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境 threadjthread修改字段的线程 methodjmethodID发生修改的方法 locationjlocation发生修改的位置 field_klassjclass正在修改的字段的类 objectjobject如果字段是实例字段,则具有被修改字段的对象;否则为 NULLfieldjfieldID正在修改的字段 signature_typechar新值的签名类型 new_valuejvalue新值
帧弹出
帧弹出事件在从单个帧中的单个方法退出时生成,如在调用void JNICALL FramePop(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method, jboolean was_popped_by_exception)NotifyFramePop中指定的那样。无论是通过执行其返回指令还是通过向其调用者抛出异常(请参见was_popped_by_exception)引起的终止,都是如此。但是,由PopFrame函数引起的帧弹出不会报告。 由GetFrameLocation报告的深度为0的位置标识返回方法中的可执行位置,即在返回之前。能力可选功能:可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此事件。能力 效果 can_generate_frame_pop_events可以设置并因此获取 FramePop事件参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境 threadjthread弹出帧的线程 methodjmethodID正在弹出的方法 was_popped_by_exceptionjboolean如果帧是由抛出的异常弹出的,则为真。如果方法通过其返回指令退出,则为假。
方法进入
方法进入事件在进入Java编程语言方法(包括本地方法)时生成。 由void JNICALL MethodEntry(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method)GetFrameLocation报告的深度为0的位置标识方法中的初始可执行位置。 启用方法进入或退出事件将显著降低许多平台的性能,因此不建议用于性能关键的用途(如性能分析)。 字节码插装应在这些情况下使用。能力可选功能:可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此事件。能力 效果 can_generate_method_entry_events可以在进入方法时生成方法进入事件 参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境 threadjthread进入方法的线程 methodjmethodID正在进入的方法
方法退出
方法退出事件在退出Java编程语言方法(包括本地方法)时生成。无论是通过执行其返回指令还是通过向其调用者抛出异常来引起终止,都会生成此事件(请参见void JNICALL MethodExit(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method, jboolean was_popped_by_exception, jvalue return_value)was_popped_by_exception)。 由GetFrameLocation报告的深度为0的位置标识着在返回方法中的可执行位置,即在返回之前。 启用方法进入或退出事件将严重降低许多平台的性能,因此不建议在对性能至关重要的用途(如分析)中使用。 字节码插装应在这些情况下使用。能力可选功能:可能并非所有虚拟机都实现了。要使用此事件,必须使以下能力(由GetCapabilities返回)为真。能力 效果 can_generate_method_exit_events可以在退出方法时生成方法退出事件 参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境 threadjthread退出方法的线程 methodjmethodID正在退出的方法 was_popped_by_exceptionjboolean如果帧是由抛出的异常弹出的,则为真。如果方法通过其返回指令退出,则为假。 return_valuejvalue正在退出的方法的返回值。如果 was_popped_by_exception为真,则未定义且不应使用。
本地方法绑定
当虚拟机将Java编程语言本地方法绑定到实现本地方法的函数地址时,将发送本地方法绑定事件。这将在第一次调用本地方法时发生,也会在调用JNI函数void JNICALL NativeMethodBind(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method, void* address, void** new_address_ptr)RegisterNatives时发生。此事件允许将绑定重定向到代理函数。当本地方法解绑时,不会发送此事件。通常,此代理函数将需要针对特定方法或处理一般情况,自动生成汇编代码,因为在执行插装代码后,通常会调用原始绑定地址处的函数。可以通过使用JNI函数RegisterNatives来恢复原始绑定或更改重定向。在原始阶段、JNI和大多数JVM期间可能会发送一些事件 ,此时无法使用TI,但可以保存方法和地址以供以后使用。能力可选功能:可能并非所有虚拟机都实现了。要使用此事件,必须使以下能力(由GetCapabilities返回)为真。能力 效果 can_generate_native_method_bind_events可以在将本地方法绑定到其实现时生成事件 参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境。如果在原始阶段发送,则为 NULL。threadjthread请求绑定的线程 methodjmethodID正在绑定的本地方法 addressvoid*虚拟机即将绑定到的地址,即本地方法实现的地址 new_address_ptrvoid**如果引用的地址更改(即设置了 *new_address_ptr),则绑定将改为绑定到提供的地址。
异常
在Java编程语言方法中首次检测到异常时生成异常事件。这里的“异常”指的是任何void JNICALL Exception(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method, jlocation location, jobject exception, jmethodID catch_method, jlocation catch_location)java.lang.Throwable。异常可能由Java编程语言方法或本地方法抛出,但在本地方法的情况下,直到异常首次被Java编程语言方法看到才会生成事件。如果在本地方法中设置并清除异常(因此从不对Java编程语言代码可见),则不会生成异常事件。method和location参数唯一标识当前位置(检测到异常的位置),并允许在可用时将其映射到源文件和行号。exception字段标识抛出的异常对象。catch_method和catch_location标识处理抛出异常的catch子句的位置(如果有)。如果没有这样的catch子句,则每个字段都设置为0。不能保证线程将达到此catch子句。如果在抛出位置和catch子句之间的调用堆栈上有本地方法,则异常可能会被其中一个本地方法重置。同样,作为未捕获报告的异常(catch_klass等设置为0)实际上可能被本地代码捕获。代理可以通过监视ExceptionCatch事件来检查这些情况。请注意,finally子句被实现为catch和重新抛出。因此,它们将在catch位置报告。能力可选功能:可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此事件。能力 效果 can_generate_exception_events可以获取抛出异常和捕获异常事件 参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境 threadjthread生成异常的线程 methodjmethodID生成异常的方法 locationjlocation异常发生的位置 exceptionjobject正在抛出的异常 catch_methodjmethodID将捕获异常的方法,如果没有已知的捕获则为 NULLcatch_locationjlocation将捕获异常的位置,如果没有已知的捕获则为零
异常捕获
每当捕获到抛出的异常时,将生成异常捕获事件。这里的“异常”指的是任何void JNICALL ExceptionCatch(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method, jlocation location, jobject exception)java.lang.Throwable。如果异常在Java编程语言方法中被捕获,事件将在到达捕获子句时生成。如果异常在本地方法中被捕获,事件将在控制返回到Java编程语言方法时生成。对于在Java编程语言方法中检测到抛出的任何异常,都会生成异常捕获事件。请注意,finally子句被实现为捕获和重新抛出。因此,它们将生成异常捕获事件。method和location参数唯一标识当前位置,并在可用时允许将其映射到源文件和行号。对于在Java编程语言方法中捕获的异常,exception对象标识异常对象。在本地方法中捕获的异常在报告异常捕获时不一定可用,因此exception字段设置为NULL。能力可选功能:可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此事件。能力 效果 can_generate_exception_events可以获取抛出异常和异常捕获事件 参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境 threadjthread捕获异常的线程 methodjmethodID捕获异常的方法 locationjlocation正在捕获异常的位置 exceptionjobject正在捕获的异常
线程启动
新线程在其初始方法执行之前由新线程生成线程启动事件。 此事件由平台线程生成。虚拟线程不会生成此事件。 具有void JNICALL ThreadStart(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread)can_support_virtual_threads能力的代理可以启用VirtualThreadStart事件,以便被新启动的虚拟线程通知。 平台线程可能在其线程启动事件生成之前在由GetAllThreads返回的数组中列出。在生成线程启动事件之前,可能会为线程生成其他事件。 事件发送到新启动的thread。能力必需功能参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境。 threadjthread正在启动的线程
线程结束
终止线程在其初始方法执行完毕后生成线程结束事件。 此事件由平台线程生成。虚拟线程不会生成此事件。 具有void JNICALL ThreadEnd(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread)can_support_virtual_threads能力的代理可以启用VirtualThreadEnd事件,以便被终止的虚拟线程通知。 平台线程可能在其线程结束事件生成后在由GetAllThreads返回的数组中列出。在线程结束事件生成后,不会在线程上生成任何事件。 事件发送到正在终止的thread。能力所需功能参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境。 threadjthread结束的线程
虚拟线程启动
在其初始方法执行之前生成虚拟线程启动事件。 事件发送到新启动的void JNICALL VirtualThreadStart(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread virtual_thread)virtual_thread。能力可选功能: 可能并非所有虚拟机都实现。要使用此事件,必须通过GetCapabilities返回的以下能力为真。能力 效果 can_support_virtual_threads可以支持虚拟线程 参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境。 virtual_threadjthread用于执行的虚拟线程。
虚拟线程结束
在其初始方法执行完成后生成虚拟线程结束事件。 事件发送到终止的void JNICALL VirtualThreadEnd(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread virtual_thread)virtual_thread。能力可选功能: 可能并非所有虚拟机都实现。要使用此事件,必须通过GetCapabilities返回的以下能力为真。能力 效果 can_support_virtual_threads可以支持虚拟线程 参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境。 virtual_threadjthread正在结束的虚拟线程。
类加载
当创建类或接口时生成类加载事件。 数组类的创建不会生成类加载事件。创建原始类(例如,java.lang.Integer.TYPE)不会生成类加载事件。 特定线程生成的类加载事件的顺序保证与该线程内的类加载顺序相匹配。 此事件在加载类的早期阶段发送。因此,应谨慎使用类。请注意,例如,方法和字段尚未加载,因此对方法、字段、子类等的查询将不会给出正确的结果。请参阅《Java语言规范》中的“类和接口的加载”。对于大多数情况,void JNICALL ClassLoad(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jclass klass)ClassPrepare事件将更有用。能力所需功能参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境 threadjthread加载类的线程 klassjclass正在加载的类
类准备
当类准备完成时生成类准备事件。此时,类字段、方法和实现的接口可用,并且尚未执行类的任何代码。由于数组类永远不会有字段或方法,因此不会为它们生成类准备事件。原始类(例如,void JNICALL ClassPrepare(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jclass klass)java.lang.Integer.TYPE)不会生成类准备事件。能力所需功能参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境 threadjthread生成类准备的线程 klassjclass正在准备的类
类文件加载钩子
在虚拟机获取类文件数据但尚未构建该类的内存表示之前发送此事件。当类被void JNICALL ClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jclass class_being_redefined, jobject loader, const char* name, jobject protection_domain, jint class_data_len, const unsigned char* class_data, jint* new_class_data_len, unsigned char** new_class_data)RetransformClasses函数或RedefineClasses函数修改时,也会发送此事件,可在任何JVM TI环境中调用。代理可以对虚拟机发送的现有类文件数据进行仪表化/调试挂钩。有关使用信息,请参阅 字节码仪表化 的描述。 当启用can_generate_early_class_hook_events和can_generate_all_class_hook_events时,此事件可能在原始阶段发送。否则,此事件可能在虚拟机初始化之前发送(启动 阶段)。某些类可能与该函数不兼容(例如ROM化类或实现定义的类),对于这些类不会生成此事件。 代理必须使用内存分配函数Allocate为修改后的类文件数据缓冲区分配空间,因为虚拟机负责使用Deallocate释放新的类文件数据缓冲区。 如果代理希望修改类文件,则必须将new_class_data设置为指向新仪表化类文件数据缓冲区,并在从此调用返回之前将new_class_data_len设置为该缓冲区的长度。如果不希望进行修改,则代理只需不设置new_class_data。如果多个代理已启用此事件,则结果将被链接。也就是说,如果已设置new_class_data,它将成为下一个代理的class_data。 在运行阶段处理类加载时,可以使用GetNamedModule函数将类加载器和包名称映射到模块。当类被重新定义或重新转换时,class_being_redefined不为空,因此JNIGetModule函数也可用于获取模块。 发送此事件到每个环境的顺序与其他事件不同。此事件按以下顺序发送到环境: 当由RetransformClasses触发时,此事件仅发送到 可重新转换 的环境。能力所需功能可选特性 能力 效果 can_generate_all_class_hook_events可以为每个加载的类生成ClassFileLoadHook事件。 can_generate_early_class_hook_events可以在原始阶段生成 ClassFileLoadHook事件。如果启用此能力和can_generate_all_class_hook_events,则ClassFileLoadHook事件可以发布用于原始阶段加载的类。请参阅ClassFileLoadHook。参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境。 class_being_redefinedjclass正在 重新定义 或 重新转换 的类。如果由类加载发送,则为 NULL。loaderjobject加载类的类加载器。如果是引导类加载器,则为 NULL。nameconst char*作为VM内部限定名称加载的类的名称(例如,“java/util/List”),编码为 修改的UTF-8 字符串。注意:如果类以 NULL名称定义或未指定名称,则name将为NULL。protection_domainjobject类的 ProtectionDomain。class_data_lenjint当前类文件数据缓冲区的长度。 class_dataconst unsigned char*指向当前类文件数据缓冲区的指针。 new_class_data_lenjint*指向新类文件数据缓冲区的长度的指针。 new_class_dataunsigned char**指向仪表化类文件数据缓冲区的指针。
虚拟机启动事件
虚拟机启动事件表示虚拟机的启动。此时JNI是活动的,但虚拟机尚未完全初始化。生成此事件后,代理可以自由调用任何JNI函数。此事件标志着启动阶段的开始,允许在启动阶段调用的JVM TI函数。 此事件的时机可能取决于代理是否添加了void JNICALL VMStart(jvmtiEnv *jvmti_env, JNIEnv* jni_env)can_generate_early_vmstart能力或不具备。如果已添加该功能,则VM尽早发布事件。VM能够执行字节码,但可能尚未初始化到可以在除java.base之外的模块中加载类,甚至在java.base中加载任意类的程度。在此阶段进行加载时的代理必须在对可能在此阶段执行的代码进行插装时格外小心。对JNIFindClass也应该格外小心,因为可能无法加载类,尝试加载类可能导致一些VM实现中的不可预测行为,甚至可能导致稳定性问题。如果未添加该功能,则VM将延迟发布此事件,直到能够在除java.base之外的模块中加载类或VM完成初始化。创建多个具有该功能的JVM TI环境的代理,其中对某些环境添加了该功能,而对另一些环境未添加,可能会观察到具有该功能的JVM TI环境中开始阶段开始得更早。 在VM启动失败的情况下,将不会发送此事件。能力所需功能参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境。
VM 初始化事件
VM初始化事件表示VM初始化的完成。一旦生成此事件,代理就可以自由调用任何JNI或JVM TI函数。VM初始化事件可以在其他事件之前或与其他事件同时发生,但如果有其他事件发生,则应小心处理,因为VM尚未完成初始化。主应用程序线程的线程启动事件保证在处理VM初始化事件的处理程序返回之后才会发生。 在VM启动失败的情况下,将不会发送此事件。void JNICALL VMInit(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread)能力所需功能参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境。 threadjthread初始线程
VM 死亡事件
VM死亡事件通知代理VM的终止。在VMDeath事件之后不会发生任何事件。 在VM启动失败的情况下,将不会发送此事件。请注意,在这些情况下仍将调用 Agent_OnUnload。void JNICALL VMDeath(jvmtiEnv *jvmti_env, JNIEnv* jni_env)能力所需功能参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境
已编译方法加载
当VM编译并将方法加载到内存中时发送。如果卸载,则会发送typedef struct { const void* start_address; jlocation location; } jvmtiAddrLocationMap;void JNICALL CompiledMethodLoad(jvmtiEnv *jvmti_env, jmethodID method, jint code_size, const void* code_addr, jint map_length, const jvmtiAddrLocationMap* map, const void* compile_info)CompiledMethodUnload事件。如果移动,则会发送CompiledMethodUnload事件,然后是新的CompiledMethodLoad事件。请注意,单个方法可能具有多个编译形式,对于每种形式都会发送此事件。还请注意,几种方法可能被内联到单个地址范围中,对于每种方法都会发送此事件。 这些事件可以在初始发生后使用GenerateEvents再次发送。jvmtiAddrLocationMap- 本机地址到位置条目字段 类型 描述 start_addressconst void*与位置对应的代码的起始本机地址 locationjlocation对应的位置。有关位置含义,请参阅 GetJLocationFormat。能力可选功能: 可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此事件。能力 效果 can_generate_compiled_method_load_events可以在方法编译或卸载时生成事件 参数 名称 类型 描述 methodjmethodID正在编译和加载的方法 code_sizejint编译代码的大小 code_addrconst void*编译方法代码加载的地址 map_lengthjint地址映射中的 jvmtiAddrLocationMap条目数。如果无法提供映射信息,则为零。mapconst jvmtiAddrLocationMap*从本机地址到位置的映射。每个条目的本机地址范围从 start_address到下一个条目的start_address-1。如果无法提供映射信息,则为NULL。compile_infoconst void*VM特定的编译信息。引用的编译信息由VM管理,不得依赖代理程序进行收集。VM实现定义信息的内容和生命周期。
编译方法卸载
当从内存中卸载编译方法时发送。此事件可能不会在执行卸载的线程上发送。此事件可能在卸载发生后的某个时间发送,但会在内存被新生成的编译方法重用之前发送。此事件可能在类被卸载后发送。void JNICALL CompiledMethodUnload(jvmtiEnv *jvmti_env, jmethodID method, const void* code_addr)能力可选功能:可能不会为所有虚拟机实现。必须通过GetCapabilities返回的以下能力才能使用此事件。能力 效果 can_generate_compiled_method_load_events可以在方法编译或卸载时生成事件 参数 名称 类型 描述 methodjmethodID正在卸载的编译方法。仅用于标识编译方法 -- 类可能已被卸载,因此不应将方法用作进一步JNI或JVM TI函数的参数。 code_addrconst void*编译方法代码加载的地址。仅用于标识编译方法 -- 空间可能已被回收。
动态生成的代码
当虚拟机的组件动态生成时发送。这不对应于已编译的Java编程语言代码--请参见void JNICALL DynamicCodeGenerated(jvmtiEnv *jvmti_env, const char* name, const void* address, jint length)CompiledMethodLoad。这是用于本机代码--例如,根据命令行选项生成不同的解释器。 请注意,此事件没有控制能力。如果VM无法生成这些事件,则不会发送任何事件。 这些事件可以在初始发生后使用GenerateEvents再次发送。能力所需功能参数 名称 类型 描述 nameconst char*代码的名称,编码为修改的UTF-8字符串。用于向最终用户显示。名称可能不是唯一的。 addressconst void*代码的本机地址 lengthjint代码的字节长度
数据转储请求
由VM发送给代理程序以请求其转储数据。这只是一个提示,代理程序不需要对此事件做出反应。这对于处理用户的命令行信号很有用。例如,在Java 2 SDK中,Win32上的CTRL-Break和Linux上的CTRL-\会导致VM向代理程序发送此事件。void JNICALL DataDumpRequest(jvmtiEnv *jvmti_env)
能力所需功能参数无
争用监视器进入
当线程尝试进入另一个线程已经获取的Java编程语言监视器时发送。void JNICALL MonitorContendedEnter(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jobject object)能力可选功能:可能并非所有虚拟机都实现。必须使用此事件时,以下能力(由GetCapabilities返回)必须为真。能力 效果 can_generate_monitor_events可以在监视器活动上生成事件 参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境 threadjthread尝试进入监视器的线程的JNI本地引用 objectjobject监视器的JNI本地引用
监视器争用进入
当线程在等待另一个线程释放Java编程语言监视器后进入监视器时发送。void JNICALL MonitorContendedEntered(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jobject object)能力可选功能:可能并非所有虚拟机都实现。必须使用此事件时,以下能力(由GetCapabilities返回)必须为真。能力 效果 can_generate_monitor_events可以在监视器活动上生成事件 参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境 threadjthread完成等待进入监视器的线程的JNI本地引用 objectjobject监视器的JNI本地引用
监视器等待
当线程即将等待对象时发送。void JNICALL MonitorWait(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jobject object, jlong timeout)能力可选功能:可能并非所有虚拟机都实现。必须使用此事件时,以下能力(由GetCapabilities返回)必须为真。能力 效果 can_generate_monitor_events可以在监视器活动上生成事件 参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境 threadjthread即将等待的线程的JNI本地引用 objectjobject监视器的JNI本地引用 timeoutjlong线程将等待的毫秒数
监视器等待完成
当线程完成等待对象时发送。void JNICALL MonitorWaited(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jobject object, jboolean timed_out)能力可选功能:可能并非所有虚拟机都实现。必须使用此事件时,以下能力(由GetCapabilities返回)必须为真。能力 效果 can_generate_monitor_events可以在监视器活动上生成事件 参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境 threadjthread完成等待的线程的JNI本地引用 objectjobject监视器的JNI本地引用 timed_outjboolean如果监视器超时则为真
资源耗尽
当运行应用程序所需的VM资源耗尽时发送。除非可选功能要求,报告耗尽的资源集是实现相关的。 以下位标志定义资源耗尽的属性:void JNICALL ResourceExhausted(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jint flags, const void* reserved, const char* description)资源耗尽标志 常量 值 描述 JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR0x0001 此事件返回后,虚拟机将抛出一个 java.lang.OutOfMemoryError。JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP0x0002 虚拟机无法从JavaTM平台的堆中分配内存。 堆是运行时数据区,用于为所有类实例和数组分配内存。 JVMTI_RESOURCE_EXHAUSTED_THREADS0x0004 虚拟机无法创建线程。 能力所需功能可选特性 能力 效果 can_generate_resource_exhaustion_heap_events当虚拟机无法从堆中分配内存时,可以生成事件。 can_generate_resource_exhaustion_threads_events当虚拟机无法创建线程时,可以生成事件。 参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境 flagsjint由资源耗尽标志指定的资源耗尽属性的标志。 reservedconst void*保留。 descriptionconst char*资源耗尽的描述,编码为修改的UTF-8字符串。
虚拟机对象分配
当方法导致虚拟机直接为Java编程语言代码分配可见对象时发送。通常,应通过检测分配方法的字节码来检测对象分配。通过JNI函数调用在本机代码中生成的对象分配应使用JNI函数拦截。有些方法可能没有关联的字节码,也不是本机方法,而是由虚拟机直接执行的。这些方法应发送此事件。对于某些或所有方法无法进行字节码检测的虚拟机可以发送此事件。请注意,SampledObjectAlloc事件会触发所有Java对象分配,包括由字节码方法执行、JNI方法执行以及虚拟机方法直接引起的对象分配。 可能发送此事件的典型示例:void JNICALL VMObjectAlloc(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jobject object, jclass object_klass, jlong size)- 反射 - 例如,
java.lang.Class.newInstance() - 不由字节码表示的方法 - 例如,VM内部函数和J2ME预加载类
- 由于字节码而分配 - 例如,
new和newarray虚拟机指令 - 由JNI函数调用导致的分配 - 例如,
AllocObject - 虚拟机初始化期间的分配
- 虚拟机内部对象
能力可选功能:可能并非所有虚拟机都实现。要使用此事件,必须返回由GetCapabilities返回的以下能力为真。能力 效果 can_generate_vm_object_alloc_events可以生成对象的虚拟机分配事件 参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境 threadjthread分配对象的线程。 objectjobject分配的对象的JNI本地引用。 object_klassjclass对象的类的JNI本地引用。 sizejlong对象的大小(以字节为单位)。请参阅 GetObjectSize。
采样对象分配
当对分配的对象进行采样时发送。默认情况下,采样间隔设置为512KB。采样是半随机的,以避免基于模式的偏差,并在长时间的采样期间提供近似的总体平均间隔。 每个线程跟踪自上次发送事件以来分配的字节数。当字节数超过采样间隔时,将发送另一个事件。这意味着平均每当线程分配512KB字节时,将对一个对象进行采样。 请注意,采样器是伪随机的:它不会精确地每隔512KB进行采样。这样做的目的是确保即使分配按固定模式进行(即,每隔512KB分配相同的对象集),也能获得高质量的采样。 如果需要其他采样间隔,用户可以调用void JNICALL SampledObjectAlloc(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jobject object, jclass object_klass, jlong size)SetHeapSamplingInterval,并提供严格正整数值,表示新的采样间隔。 一旦执行了采样分配,将发送此事件。它提供了对象、分配的堆栈跟踪、分配对象的线程、分配的大小和对象的类。 此系统的典型用例是确定堆分配的来源。结合弱引用和函数GetStackTrace,用户可以跟踪哪些对象是从哪个堆栈跟踪分配的,哪些对象在程序执行期间仍然存活。能力可选功能:可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此事件。能力 效果 can_generate_sampled_object_alloc_events可以生成采样分配事件。如果启用了此能力,则可以调用堆采样方法 SetHeapSamplingInterval,并生成SampledObjectAlloc事件。参数 名称 类型 描述 jni_envJNIEnv *事件(当前)线程的JNI环境。 threadjthread分配对象的线程。 objectjobject分配的对象的JNI本地引用。 object_klassjclass对象的类的JNI本地引用 sizejlong对象的大小(以字节为单位)。请参阅 GetObjectSize。
对象释放
当垃圾收集器释放对象时,将发送对象释放事件。仅为带有标记的对象发送事件--请参见堆函数。 事件处理程序不得使用JNI函数,也不得使用JVM TI函数,除非专门允许此类使用(请参阅原始监视器、内存管理和环境本地存储函数)。void JNICALL ObjectFree(jvmtiEnv *jvmti_env, jlong tag)能力可选功能:可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此事件。能力 效果 can_generate_object_free_events可以在垃圾收集器释放对象时生成事件 参数 名称 类型 描述 tagjlong被释放对象的标记
垃圾收集开始
当垃圾收集暂停开始时,将发送垃圾收集开始事件。仅报告全线程停止修改Java虚拟机状态的停止-世界收集--这意味着某些收集器永远不会生成这些事件。此事件在VM仍处于停止状态时发送,因此事件处理程序不得使用JNI函数,也不得使用JVM TI函数,除非专门允许此类使用(请参阅原始监视器、内存管理和环境本地存储函数)。 此事件始终作为匹配对发送void JNICALL GarbageCollectionStart(jvmtiEnv *jvmti_env)
GarbageCollectionFinish(假设两个事件都已启用),并且它们之间不会发生垃圾收集事件。能力可选功能:可能并非所有虚拟机都实现。必须通过GetCapabilities返回的以下能力才能使用此事件。能力 效果 can_generate_garbage_collection_events可以在垃圾收集开始或结束时生成事件 参数无
垃圾收集完成
当垃圾收集暂停结束时,将发送垃圾收集完成事件。此事件在VM仍处于停止状态时发送,因此事件处理程序不得使用JNI函数,也不得使用JVM TI函数,除非专门允许此类使用(请参阅原始监视器、内存管理和环境本地存储函数)。 某些代理可能需要执行需要使用不允许的JVM TI或JNI函数的垃圾收集后操作。对于这些情况,可以创建一个代理线程,该线程等待原始监视器,并且垃圾收集完成事件的处理程序仅通知原始监视器 此事件始终作为匹配对发送void JNICALL GarbageCollectionFinish(jvmtiEnv *jvmti_env)
GarbageCollectionStart(假设两个事件都已启用)。能力可选功能: 可能并非所有虚拟机都实现。要使用此事件,必须使以下能力(由GetCapabilities返回)为真。能力 效果 can_generate_garbage_collection_events可以在垃圾回收开始或结束时生成事件 参数无
常量索引
JVMTI_CLASS_STATUS_ARRAYJVMTI_CLASS_STATUS_ERRORJVMTI_CLASS_STATUS_INITIALIZEDJVMTI_CLASS_STATUS_PREPAREDJVMTI_CLASS_STATUS_PRIMITIVEJVMTI_CLASS_STATUS_VERIFIEDJVMTI_DISABLEJVMTI_ENABLEJVMTI_HEAP_FILTER_CLASS_TAGGEDJVMTI_HEAP_FILTER_CLASS_UNTAGGEDJVMTI_HEAP_FILTER_TAGGEDJVMTI_HEAP_FILTER_UNTAGGEDJVMTI_HEAP_OBJECT_EITHERJVMTI_HEAP_OBJECT_TAGGEDJVMTI_HEAP_OBJECT_UNTAGGEDJVMTI_HEAP_REFERENCE_ARRAY_ELEMENTJVMTI_HEAP_REFERENCE_CLASSJVMTI_HEAP_REFERENCE_CLASS_LOADERJVMTI_HEAP_REFERENCE_CONSTANT_POOLJVMTI_HEAP_REFERENCE_FIELDJVMTI_HEAP_REFERENCE_INTERFACEJVMTI_HEAP_REFERENCE_JNI_GLOBALJVMTI_HEAP_REFERENCE_JNI_LOCALJVMTI_HEAP_REFERENCE_MONITORJVMTI_HEAP_REFERENCE_OTHERJVMTI_HEAP_REFERENCE_PROTECTION_DOMAINJVMTI_HEAP_REFERENCE_SIGNERSJVMTI_HEAP_REFERENCE_STACK_LOCALJVMTI_HEAP_REFERENCE_STATIC_FIELDJVMTI_HEAP_REFERENCE_SUPERCLASSJVMTI_HEAP_REFERENCE_SYSTEM_CLASSJVMTI_HEAP_REFERENCE_THREADJVMTI_HEAP_ROOT_JNI_GLOBALJVMTI_HEAP_ROOT_JNI_LOCALJVMTI_HEAP_ROOT_MONITORJVMTI_HEAP_ROOT_OTHERJVMTI_HEAP_ROOT_STACK_LOCALJVMTI_HEAP_ROOT_SYSTEM_CLASSJVMTI_HEAP_ROOT_THREADJVMTI_ITERATION_ABORTJVMTI_ITERATION_CONTINUEJVMTI_ITERATION_IGNOREJVMTI_JAVA_LANG_THREAD_STATE_BLOCKEDJVMTI_JAVA_LANG_THREAD_STATE_MASKJVMTI_JAVA_LANG_THREAD_STATE_NEWJVMTI_JAVA_LANG_THREAD_STATE_RUNNABLEJVMTI_JAVA_LANG_THREAD_STATE_TERMINATEDJVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITINGJVMTI_JAVA_LANG_THREAD_STATE_WAITINGJVMTI_JLOCATION_JVMBCIJVMTI_JLOCATION_MACHINEPCJVMTI_JLOCATION_OTHERJVMTI_KIND_ALLOC_ALLOC_BUFJVMTI_KIND_ALLOC_BUFJVMTI_KIND_INJVMTI_KIND_IN_BUFJVMTI_KIND_IN_PTRJVMTI_KIND_OUTJVMTI_KIND_OUT_BUFJVMTI_PHASE_DEADJVMTI_PHASE_LIVEJVMTI_PHASE_ONLOADJVMTI_PHASE_PRIMORDIALJVMTI_PHASE_STARTJVMTI_PRIMITIVE_TYPE_BOOLEANJVMTI_PRIMITIVE_TYPE_BYTEJVMTI_PRIMITIVE_TYPE_CHARJVMTI_PRIMITIVE_TYPE_DOUBLEJVMTI_PRIMITIVE_TYPE_FLOATJVMTI_PRIMITIVE_TYPE_INTJVMTI_PRIMITIVE_TYPE_LONGJVMTI_PRIMITIVE_TYPE_SHORTJVMTI_REFERENCE_ARRAY_ELEMENTJVMTI_REFERENCE_CLASSJVMTI_REFERENCE_CLASS_LOADERJVMTI_REFERENCE_CONSTANT_POOLJVMTI_REFERENCE_FIELDJVMTI_REFERENCE_INTERFACEJVMTI_REFERENCE_PROTECTION_DOMAINJVMTI_REFERENCE_SIGNERSJVMTI_REFERENCE_STATIC_FIELDJVMTI_RESOURCE_EXHAUSTED_JAVA_HEAPJVMTI_RESOURCE_EXHAUSTED_OOM_ERRORJVMTI_RESOURCE_EXHAUSTED_THREADSJVMTI_THREAD_MAX_PRIORITYJVMTI_THREAD_MIN_PRIORITYJVMTI_THREAD_NORM_PRIORITYJVMTI_THREAD_STATE_ALIVEJVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTERJVMTI_THREAD_STATE_IN_NATIVEJVMTI_THREAD_STATE_IN_OBJECT_WAITJVMTI_THREAD_STATE_INTERRUPTEDJVMTI_THREAD_STATE_PARKEDJVMTI_THREAD_STATE_RUNNABLEJVMTI_THREAD_STATE_SLEEPINGJVMTI_THREAD_STATE_SUSPENDEDJVMTI_THREAD_STATE_TERMINATEDJVMTI_THREAD_STATE_VENDOR_1JVMTI_THREAD_STATE_VENDOR_2JVMTI_THREAD_STATE_VENDOR_3JVMTI_THREAD_STATE_WAITINGJVMTI_THREAD_STATE_WAITING_INDEFINITELYJVMTI_THREAD_STATE_WAITING_WITH_TIMEOUTJVMTI_TIMER_ELAPSEDJVMTI_TIMER_TOTAL_CPUJVMTI_TIMER_USER_CPUJVMTI_TYPE_CCHARJVMTI_TYPE_CVOIDJVMTI_TYPE_JBOOLEANJVMTI_TYPE_JBYTEJVMTI_TYPE_JCHARJVMTI_TYPE_JCLASSJVMTI_TYPE_JDOUBLEJVMTI_TYPE_JFIELDIDJVMTI_TYPE_JFLOATJVMTI_TYPE_JINTJVMTI_TYPE_JLONGJVMTI_TYPE_JMETHODIDJVMTI_TYPE_JNIENVJVMTI_TYPE_JOBJECTJVMTI_TYPE_JSHORTJVMTI_TYPE_JTHREADJVMTI_TYPE_JVALUEJVMTI_VERBOSE_CLASSJVMTI_VERBOSE_GCJVMTI_VERBOSE_JNIJVMTI_VERBOSE_OTHERJVMTI_VERSION_INTERFACE_JNIJVMTI_VERSION_INTERFACE_JVMTIJVMTI_VERSION_MASK_INTERFACE_TYPEJVMTI_VERSION_MASK_MAJORJVMTI_VERSION_MASK_MICROJVMTI_VERSION_MASK_MINORJVMTI_VERSION_SHIFT_MAJORJVMTI_VERSION_SHIFT_MICROJVMTI_VERSION_SHIFT_MINORJVMTI_VISIT_ABORTJVMTI_VISIT_OBJECTS
变更历史
最后更新日期:09/05/07
版本:21.0.0 JVM TI规范是一个不断发展的文档,具有主要、次要和微小版本号。规范的发布版本通过其主要和次要版本唯一标识。本规范中的函数、事件和功能指示了一个“自”值,即其引入的主要和次要版本。VM实现的规范版本可以在运行时使用GetVersionNumber函数检索。版本
日期更改 2002年11月14日 转换为XML文档。 2002年11月14日 省略了堆转储功能(暂时)因为原有内容有误。 2002年11月18日 在整个文档中添加了细节。 2002年11月18日 将JVMTI_THREAD_STATUS_RUNNING更改为JVMTI_THREAD_STATUS_RUNNABLE。 2002年11月19日 添加了AsyncGetStackTrace。 2002年11月19日 在GetStackTrace中添加了jframeID返回。 2002年11月19日 省略了GetCurrentFrame和GetCallingFrame函数(暂时)因为它们与GetStackTrace重复。 2002年11月19日 省略了ClearAllBreakpoints因为它一直是多余的。 2002年11月19日 添加了GetSystemProperties。 2002年11月19日 将线程本地存储函数更改为使用jthread。 2002年11月20日 添加了GetJLocationFormat。 2002年11月22日 添加了事件和介绍性文本。 2002年11月22日 交叉引用类型和常量定义。 2002年11月24日 添加了DTD。 2002年11月24日 添加了功能函数部分。 2002年11月29日 为每个函数和事件分配功能。 2002年11月29日 添加JNI拦截函数。 2002年11月30日 自动生成SetEventNotificationMode功能。 2002年11月30日 添加 VMObjectAlloc事件。2002年11月30日 添加 DynamicCodeGenerated事件。2002年11月30日 为声明添加const。 2002年11月30日 将方法退出和帧弹出更改为在异常时发送。 2002年12月1日 添加ForceGarbageCollection。 2002年12月2日 重新设计Xrun部分;澄清GetStackTrace并添加示例;修复宽度问题;一致使用"agent"。 2002年12月8日 删除先前的启动介绍。添加JVM TI环境部分。 2002年12月8日 添加 DisposeEnvironment。2002年12月9日 大量更新。 2002年12月15日 添加堆分析功能:获取/设置注释、迭代活动对象/堆。添加堆分析功能占位符:堆根。添加堆分析事件:对象释放。重新设计堆分析事件:VM对象分配。添加堆分析事件占位符:垃圾回收开始/完成。添加本地方法绑定事件。 2002年12月19日 改进挂起/恢复函数。在jvmdi标签中添加原始信息。杂项修复。 2002年12月24日 为类型添加语义。 2002年12月27日 添加本地引用部分。从类型自动生成参数描述。 2002年12月28日 说明RunAgentThread发送threadStart。 2002年12月29日 删除多余的本地引用和dealloc警告。将GetRawMonitorName转换为分配的缓冲区。添加GenerateEvents。 2002年12月30日 将原始监视器作为类型,并重命名为"jrawMonitorID"。 2003年1月1日 包含原始信息。清理JVMDI问题引用。删除现在自动生成的Deallocate警告。 2003年1月2日 修复jthread的表示问题。 2003年1月3日 将功能能力缓冲区化为64位,并自动执行。 2003年1月4日 将枚举为常量的常量转换为枚举类型。参数现在为枚举类型。清理和索引类型部分。用回调替换剩余的datadef实体。 2003年1月7日 更正GenerateEvents描述。更多内部语义工作。 2003年1月9日 用使用分配信息的两个函数替换先前的GetSystemProperties。添加SetSystemProperty。更多内部语义工作。 2003年1月12日 在SetEventNotificationMode末尾添加可变参数。 2003年1月20日 完成修复规范,以反映分配大小为jlong。 2003年1月22日 允许在OnLoad期间销毁原始监视器。 2003年1月22日 将名称更改为标准命名约定,删除AsyncGetStackTrace。 2003年1月29日 由于使用jthread,删除GetThread。 2003年1月31日 更改GetFieldName以允许像GetMethodName一样的NULL。 v40
2003年2月29日重写介绍性文本,添加关于启动、环境和字节码插装的部分。根据EG讨论更改命令行参数。在功能部分添加介绍性内容。添加扩展机制类别和函数。标记删除,但仍然澄清了SuspendAllThreads。将IterateOverLiveObjects重命名为IterateOverReachableObjects,并相应更改文本。澄清IterateOverHeap。澄清CompiledMethodLoad。讨论调用函数的先决状态。澄清SetAllocationHooks。添加问题(“待解决:”)等。 v41
2003年3月6日从调用GetOwnedMonitorInfo中删除结构。自动生成大多数错误文档,删除(相当错误的)手工编写的错误文档。更好地描述功能使用(空初始集)。将jint参数的最小值添加到参数中。删除can_access_thread_local_storage功能。将错误JVMTI_ERROR_NOT_IMPLEMENTED更名为JVMTI_ERROR_MUST_POSSESS_CAPABILITY;对*NOT_IMPLEMENTED也是如此。描述修复。 v42
2003年3月8日将GetClassSignature重命名为GetClassName。将IterateOverClassObjects重命名为IterateOverInstancesOfClass。删除GetMaxStack(操作数栈在JVM TI中未使用)。描述修复:定义启动时间,从PopFrame中删除本机帧弹出,并进行各种澄清。 v43
2003年3月8日修复了一个小的编辑问题。 v44
2003年3月10日添加阶段信息。重新映射(紧凑)事件编号。 v45
2003年3月11日更多阶段信息-允许“任何”。省略原始监视器查询和事件。小的描述修复。 v46
2003年3月12日添加GetPhase。在整个文档中使用“phase”。省略GetRawMonitorName。省略GetObjectMonitors。 v47
2003年3月12日来自链接、XML和拼写检查的修复。自动生成回调结构。 v48
2003年3月13日一个字符的XML修复。 v49
2003年3月13日将函数参数名称与事件参数保持一致(fooBarBaz变为foo_bar_baz)。 v50
2003年3月14日修复破损的链接。修复线程标记。 v51
2003年3月14日更改常量,使其在128以下以解决编译器问题。 v52
2003年3月23日彻底改进功能能力。将GetStackTrace分离为GetStackTrace和GetStackFrames。 v54
2003年4月8日使用深度而不是jframeID引用帧。删除现在不相关的GetCurrentFrame、GetCallerFrame和GetStackFrames。从事件中删除帧参数。 v55
2003年4月9日删除GetObjectWithAnnotation,因为测试显示缓冲方法更有效。向GetObjectsWithAnnotations添加缺失的annotation_count v56
2003年4月10日在GetObjectsWithAnnotations中删除令人困惑的括号语句 v58
2003年4月13日用简单的jmethodID替换方法的jclass/jmethodID表示;将JvmtiEnv*作为每个事件的第一个参数传递;在不适当的地方删除JNIEnv*。将can_access_frames替换为can_access_local_variables;从纯粹的堆栈访问中删除。使用can_get_synthetic_attribute;修复描述。澄清零长度数组必须被释放。澄清RelinquishCapabilities。将JVMTI_ERROR_VM_DEAD概括为JVMTI_ERROR_WRONG_PHASE。 v59
2003年4月27日删除对OBSOLETE_METHOD_ID的间接引用。 v60
2003年5月4日允许在OnLoad期间销毁DestroyRawMonitor。 v61
2003年5月7日在DestroyRawMonitor中添加未监视所有者错误返回。 v62
2003年5月13日澄清原始监视器的语义。更改 GetThreadStatus上的标志。对于引导类加载器,GetClassLoader返回NULL。添加GetClassName问题。定义本地变量签名。在GetObjectsWithAnnotations的注释数组中不允许零。在GetObjectsWithAnnotations中删除过度规范。省略SetAllocationHooks。省略SuspendAllThreads。v63
2003年5月14日定义数据类型 jvmtiEventCallbacks。零长度分配返回NULL。在JVMDI中保留SetAllocationHooks,但从JVM TI中删除。添加JVMTI_THREAD_STATUS_FLAG_INTERRUPTED。v64
2003年5月15日根据审查改进措辞。 v68
17 June 2003根据6月11日专家组会议的更改--彻底改造堆功能:单个回调,删除GetHeapRoots,添加可达迭代器,并将"annotation"重命名为"tag"。大多数函数的NULL线程参数为当前线程。添加计时器。删除ForceExit。添加GetEnvironmentLocalStorage。添加详细标志和事件。添加AddToBootstrapClassLoaderSearch。更新ClassFileLoadHook。 v69
18 June 2003清理问题部分。将GetClassName重命名为GetClassSignature并修复描述。为GetClassSignature、GetFieldSignature、GetMethodSignature和GetLocalVariableTable添加通用签名。省略EstimateCostOfCapabilities。澄清系统属性函数是在VM视图下操作系统属性。澄清Agent_OnLoad。在事件中从JNIEnv*中移除"const"。添加元数据访问器。 v70
18 June 2003为GetStackTrace添加start_depth。将系统属性移动到一个新类别。添加GetObjectSize。从命令行标志中删除"X"。XML、HTML和拼写检查更正。 v71
19 June 2003修复JVMTI_HEAP_ROOT_THREAD为6。使每个简介与函数名匹配。澄清措辞不清晰的地方。 v72
26 June 2003SetThreadLocalStorage和SetEnvironmentLocalStorage应允许将值设置为NULL。NotifyFramePop、GetFrameLocationm和所有本地变量操作需要修复有关帧的措辞。需要修复语法和清晰度。大小写和标点符号需要保持一致。需要微版本号和访问主要、次要和微版本的掩码。错误代码列表应指出哪些必须由实现返回。命令行属性应在属性函数中可见。禁止从当前线程弹出。允许实现在无法弹出时返回不透明帧错误。NativeMethodBind事件应在任何阶段发送。DynamicCodeGenerated事件应在任何阶段发送。以下函数应允许在VMInit之前操作:Set/GetEnvironmentLocalStorage GetMethodDeclaringClass GetClassSignature GetClassModifiers IsInterface IsArrayClass GetMethodName GetMethodModifiers GetMaxLocals GetArgumentsSize GetLineNumberTable GetMethodLocation IsMethodNative IsMethodSynthetic。其他更改(对XSL):参数描述应在指针之后显示星号而不是之前。NotifyFramePop、GetFrameLocationm和所有本地变量操作应添加NO_MORE_FRAMES错误。非活动线程应具有与无效线程不同的错误返回。 v73
7 July 2003VerboseOutput事件缺少消息参数。小修正。 v74
14 July 2003技术出版部更正。允许将线程和环境本地存储设置为NULL。 v75
23 July 2003使用新的Agent_OnLoad而不是重载的JVM_OnLoad。为回调函数添加JNICALL(XSL)。记录JNICALL对事件和回调函数的要求(XSL)。将RedefineClasses限制为方法和属性。省略VerboseOutput事件。VMObjectAlloc:限制何时发送事件并删除方法参数。完成技术出版编辑的松散部分。 v76
24 July 2003将ClassFileLoadHook事件更改为发送类而不是重新定义的布尔值。 v77
24 July 2003XML修复。微小的文本澄清和更正。 v78
24 July 2003从JVM TI中删除GetExceptionHandlerTable和GetThrownExceptions。澄清堆栈帧是JVM规范帧。将can_get_source_info拆分为can_get_source_file_name、can_get_line_numbers和can_get_source_debug_extension。PopFrame不能有本地调用方法。在GetClassloaderClasses中删除不正确的语句(参见Java™虚拟机规范,第4.4章)。 v79
24 July 2003XML和文本修复。将堆栈帧描述移入堆栈帧类别。 v80
26 July 2003允许NULL(表示引导加载器)用于GetClassloaderClasses。为从类引用添加新的堆引用种类。添加计时器信息结构和查询函数。添加AvailableProcessors。将GetOtherThreadCpuTime重命名为GetThreadCpuTime。明确将JVMTI_ERROR_INVALID_THREAD和JVMTI_ERROR_THREAD_NOT_ALIVE添加到SetEventNotification模式。将初始线程添加到VM_INIT事件。从AddToBootstrapClassLoaderSearch中删除平台假设。 v81
26 July 2003根据审查进行语法和清晰度更改。 v82
27 July 2003根据审查进行更多的语法和清晰度更改。添加Agent_OnUnload。 v83
28 July 2003将Agent_OnUnload的返回类型更改为void。 v84
28 July 2003将JVMTI_REFERENCE_ARRAY重命名为JVMTI_REFERENCE_ARRAY_ELEMENT。 v85
28 July 2003从java.lang.Runtime.availableProcessors()中借用AvailableProcessors()的措辞。保证零永远不会是事件ID。删除一些不再是问题的问题。根据审查,重命名并更完整地记录计时器信息函数。 v86
29 July 2003对XML控制的实现进行非规范可见更改:SetThreadLocalStorage必须在VM模式下运行。 0.1.87
5 August 2003添加GetErrorName。在jvmtiExtensionEvent中添加varargs警告。从jvmtiExtensionEvent的jvmtiEnv*中移除"const"。删除未使用的can_get_exception_info能力。将jvmtiEnv*和JNIEnv*传递给jvmtiStartFunction。修复jvmtiExtensionFunctionInfo.func声明类型。扩展函数返回错误代码。使用新的版本编号。 0.2.88
5 August 2003删除ClassUnload事件。 0.2.89
8 August 2003堆引用迭代器回调返回一个允许忽略外向对象引用的枚举。允许在扩展事件/函数中使用JNIEnv作为参数类型。 0.2.90
15 August 2003修复一个拼写错误。 0.2.91
2 September 2003删除所有元数据函数:GetClassMetadata、GetFieldMetadata和GetMethodMetadata。 0.2.92
1 October 2003将函数Allocate、Deallocate、RawMonitor*、SetEnvironmentLocalStorage和GetEnvironmentLocalStorage标记为在堆回调和GC事件中安全使用。 0.2.93
24 November 2003向堆迭代函数和回调传递不透明用户数据指针。在CompiledMethodUnload事件中,发送代码地址。添加GarbageCollectionOccurred事件。添加常量池引用种类。将函数CreateRawMonitor和DestroyRawMonitor标记为在堆回调和GC事件中安全使用。澄清:VMDeath、GetCurrentThreadCpuTimerInfo、GetThreadCpuTimerInfo、IterateOverReachableObjects、IterateOverObjectsReachableFromObject、GetTime和JVMTI_ERROR_NULL_POINTER。向GenerateEvents和AddToBootstrapClassLoaderSearch添加缺失的错误。修复ClassFileLoadHook名称参数的描述。在堆回调和GC/ObjectFree事件中,指定只能调用明确允许的函数。允许在回调期间调用GetCurrentThreadCpuTimerInfo、GetCurrentThreadCpuTime、GetTimerInfo和GetTime。允许在onload阶段调用SetTag/GetTag。在SetEventNotificationMode中添加:尝试不当的线程级控制错误。删除jvmtiExceptionHandlerEntry。修复对堆栈上的本地方法的处理--GetFrameLocation的location_ptr参数,从GetFrameLocation中删除JVMTI_ERROR_OPAQUE_FRAME,jvmtiFrameInfo.location和jlocation。删除拼写错误(来自JVMPI),暗示MonitorWaited事件在休眠时发送。 0.2.94
25 November 2003澄清和拼写错误。 0.2.95
3 December 2003允许在堆迭代器中使用NULL用户数据。 0.2.97
28 January 2004添加GetThreadState,弃用GetThreadStatus。 0.2.98
29 January 2004INVALID_SLOT和TYPE_MISMATCH错误应为可选。 0.2.102
12 February 2004删除MonitorContendedExit。向VMObjectAlloc添加JNIEnv参数。澄清堆回调的类标签和引用者索引参数的定义。 0.2.103
16 February 2004文档化JAVA_TOOL_OPTIONS。 0.2.105
17 February 2004将启动阶段分为原始和启动。更改函数和事件的阶段关联。 0.3.6
18 February 2004省略弃用的GetThreadStatus。将微版本号增加,从微版本中减去100 0.3.7
18 February 2004澄清计时器纳秒值为无符号。澄清与本地方法相关的文本。 0.3.8
19 February 2004修复拼写错误。删除省略的弃用GetThreadStatus。 0.3.9
23 February 2004要求NotifyFramePop在挂起线程上执行。 0.3.10
24 February 2004添加能力( can_redefine_any_class和can_generate_all_class_hook_events)和一个错误(JVMTI_ERROR_UNMODIFIABLE_CLASS),允许某些类不可修改。0.3.11
28 February 2004向SetEventNotificationMode添加JVMTI_ERROR_MUST_POSSESS_CAPABILITY。 0.3.12
8 March 2004澄清CompiledMethodUnload,以便清楚地表明在类卸载后可能发布事件。 0.3.13
2004年3月5日将VMObjectAlloc的大小参数更改为jlong以匹配GetObjectSize。 0.3.14
2004年3月13日添加了在事件回调函数中使用JNI FindClass函数的指导方针。 0.3.15
2004年3月15日添加了GetAllStackTraces和GetThreadListStackTraces。 0.3.16
2004年3月19日在启动阶段期间可以发布ClassLoad和ClassPrepare事件。 0.3.17
2004年3月25日在GetLineNumberTable、GetLocalVariableTable、GetMaxLocals、GetArgumentsSize、GetMethodLocation、GetBytecodes中添加JVMTI_ERROR_NATIVE_METHOD。 0.3.18
2004年3月29日在计时器信息结构中返回计时器类型。 0.3.19
2004年3月31日规范澄清:JVMTI_THREAD_STATE_IN_NATIVE可能不包括JNI或JVM TI。ForceGarbageCollection不会运行finalizers。规范的上下文是Java平台。警告提前进行仪器化。 0.3.20
2004年4月1日对上述澄清进行了细化,并澄清了Agent_OnLoad返回错误会终止VM的情况。 0.3.21
2004年4月1日数组类的创建不会生成类加载事件。 0.3.22
2004年4月7日将线程状态层次结构与java.lang.Thread.State更紧密地对齐。 0.3.23
2004年4月12日澄清线程状态的文档。 0.3.24
2004年4月19日移除GarbageCollectionOccurred事件--可以由代理执行。 0.3.25
2004年4月22日定义“命令行选项”。 0.3.26
2004年4月29日描述字节码仪器化的预期用途。修复扩展事件第一个参数的描述。 0.3.27
2004年4月30日澄清和拼写错误。 0.3.28
2004年5月18日移除DataDumpRequest事件。 0.3.29
2004年5月18日澄清零超时的RawMonitorWait。澄清RunAgentThread后的线程状态。 0.3.30
2004年5月24日清理:修复错误/旧链接等。 0.3.31
2004年5月30日澄清包括:所有字符字符串都是修改后的UTF-8。代理线程可见性。过时方法版本的含义。调用堆回调的线程。 1.0.32
2004年6月1日将主要.次要版本号提升为“1.0”。 1.0.33
2004年6月2日澄清ForceGarbageCollection和ObjectFree之间的交互。 1.0.34
2004年6月6日将AddToBootstrapClassLoaderSearch和SetSystemProperty限制为仅在OnLoad阶段使用。 1.0.35
2004年6月11日修复SetTag中的拼写错误。 1.0.36
2004年6月18日修复商标。在示例GetThreadState用法中添加缺少的参数。 1.0.37
2004年8月4日版权更新。 1.0.38
2004年11月5日添加缺失的函数表布局。添加对函数的C++成员函数格式的缺失描述。澄清CFLH中名称可以为NULL。作为J2SE 5.0的一部分发布。 1.1.47
2005年4月24日将主要.次要版本号提升为“1.1”。添加ForceEarlyReturn*函数。添加GetOwnedMonitorStackDepthInfo函数。添加GetCurrentThread函数。添加“since”版本标记。添加AddToSystemClassLoaderSearch。允许在实时阶段使用AddToBootstrapClassLoaderSearch。修复IterateOverHeap和IterateOverInstancesOfClass函数的heap_object_callback参数描述中的历史垃圾;不允许此参数为NULL。澄清、纠正和使一致:关于当前线程、不透明帧和PopFrame中帧数量不足的措辞。一致使用“当前帧”而不是“最顶层”。通过使其与ForceEarlyReturn*中的兼容,澄清GetLocal*和SetLocal*中的JVMTI_ERROR_TYPE_MISMATCH错误。许多其他澄清和措辞清理。 1.1.48
2005年4月25日添加GetConstantPool。将对VM规范第一版的引用更改为对第二版的引用。 1.1.49
2005年4月26日澄清GetConstantPool中的次要/主要版本顺序。 1.1.50
2005年4月26日添加SetNativeMethodPrefix和SetNativeMethodPrefixes。将GetOwnedMonitorStackDepthInfo重新分配到位置153。将类加载器搜索拆分为自己的文档类别。处理XML源中过长的行。 1.1.51
2005年4月29日允许代理在实时阶段启动。添加有关部署代理的段落。 1.1.52
2005年4月30日为SetNativeMethodPrefix(es)添加规范描述。更好地定义GetConstantPool的条件。 1.1.53
2005年4月30日从GetConstantPool中分离GetClassVersionNumber函数。清理对VM规范的引用。 1.1.54
2005年5月1日允许在任何阶段使用SetNativeMethodPrefix(es)。添加有关重定义对GetConstantPool影响的澄清。 1.1.56
2005年5月2日对SetNativeMethodPrefix(es)进行各种澄清。 1.1.57
2005年5月2日向方法入口事件添加缺失的性能警告。 1.1.58
2005年5月5日移除内部JVMDI支持。 1.1.59
2005年5月8日添加RetransformClasses。重新设计字节码仪器化文档。将IsMethodObsolete更改为不再需要can_redefine_classes功能。 1.1.63
2005年5月11日重新转换的澄清。 1.1.64
2005年5月11日重新转换的澄清,经过审查。在类加载启用时锁定“重新转换(不)能力”。 1.1.67
2005年6月4日添加支持报告原始值的新堆功能,允许设置引用标签,并具有更强大的过滤功能:FollowReferences、IterateThroughHeap及其相关的回调、结构、枚举和常量。 1.1.68
2005年6月4日澄清。 1.1.69
2005年6月6日FollowReferences、IterateThroughHeap:将回调放入结构中;添加缺失的错误代码;减少访问控制标志中的位数。 1.1.70
2005年6月14日关于新堆功能的更多内容:根据审查进行规范清理。 1.1.71
2005年6月15日关于新堆功能的更多内容:将旧堆部分重命名为Heap(1.0)。 1.1.72
2005年6月21日修复拼写错误。 1.1.73
2005年6月27日将引用者信息结构改为联合体。 1.1.74
2005年9月9日在新堆函数中:添加缺失的超类引用类型。使用单一方案计算字段索引。删除对基于结构的引用者信息的过时引用。 1.1.75
2005年9月12日在FollowReferences期间不要在无聊的java.lang.Object超类上进行回调。 1.1.76
2005年9月13日在字符串原始回调中,长度现在是Unicode长度。在数组和字符串原始回调中,值现在是“const”。注意在设置JNI函数表时可能对编译器产生的影响。 1.1.77
2005年9月13日GetClassVersionNumbers()和GetConstantPool()应在数组或原始类上返回错误。 1.1.78
2005年9月14日语法修正。 1.1.79
2005年9月26日添加IsModifiableClass查询。 1.1.81
2006年2月9日向jvmtiHeapReferenceCallback添加referrer_class_tag参数。 1.1.82
2006年2月13日文档修复:更新can_redefine_any_class以包括重转换。澄清异常事件涵盖所有Throwables。在GetStackTrace中,如果start_depth为零,则不会对start_depth过大进行测试。澄清原始字段回调中报告的字段--静态 vs 实例。修复混乱的堆类型名称,包括回调名称。要求在线程启动方法面临一致使用堆栈深度。注意JVM TI内存管理与其他系统的不兼容性。 1.1.85
2006年2月14日修复拼写错误和缺失的重命名。 1.1.86 1.1.88
2006年3月16日将对象引用回调中静态字段的referrer_index与参考实现(以及所有其他已知实现)匹配;即,使其与实例字段的定义相匹配。在GetThreadListStackTraces中,添加JVMTI_ERROR_INVALID_THREAD以覆盖列表中的无效线程;并指定未启动的线程返回空堆栈。 1.1.89
2006年3月17日拼写错误。 1.1.90
2006年3月25日拼写错误。 1.1.91
2006年4月6日移除对AddToBootstrapClassLoaderSearch和AddToSystemClassLoaderSearch的限制。 1.1.93
2006年5月1日更改规范,对于无法确定堆栈深度的实现,返回-1作为监视器堆栈深度。 1.1.94
2006年5月3日由IBM的Alan Pratt提供的可读性和准确性更正。列出在FollowReferences中报告的对象关系。 1.1.95
2006年5月5日澄清在FollowReferences中报告的对象关系。 1.1.98
2006年6月28日澄清DisposeEnvironment;添加警告。在SetLocalXXX中修正拼写错误“retrieve” => “set”。澄清原生方法前缀在使用时必须保持设置。澄清每个代理只调用一次Agent_OnXXX。澄清库加载与启动无关。在Agent_OnUnload规范中删除对Agent_OnLoad的模糊引用。 1.1.99
2006年7月31日澄清函数和异常之间的交互。澄清并举例说明字段索引。从MonitorWait和MonitorWaited事件中删除令人困惑的“即”句子。更新链接指向Java 6。 1.1.102
2006年8月6日添加ResourceExhaustedEvent。 1.2.2
2012年10月11日修复LinkCheck工具报告的“HTTP”和“Missing Anchor”错误。 1.2.3
2013年6月19日添加对静态链接代理的支持。 9.0.0
2016年10月13日支持模块:主要版本现在是9。在原始阶段不再发送ClassFileLoadHook事件。允许在启动阶段生成CompiledMethodLoad事件。添加新功能:can_generate_early_vmstart,can_generate_early_class_hook_events。添加新函数:GetAllModules,AddModuleReads,AddModuleExports,AddModuleOpens,AddModuleUses,AddModuleProvides,IsModifiableModule。澄清can_redefine_any_classes,can_retransform_any_classes和IsModifiableClass API,以禁止某些实现定义的类。 9.0.0
2017年2月12日GetCurrentThread函数的小更新:如果启用了can_generate_early_vmstart功能,则在启动阶段该函数可能返回NULL。 11.0.0
2018年2月7日新类文件NestHost和NestMembers属性的小更新:指定RedefineClasses和RetransformClasses不允许更改类文件NestHost和NestMembers属性;添加新错误JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_ATTRIBUTE_CHANGED,该错误可以由RedefineClasses和RetransformClasses返回。 11.0.0
2018年6月15日支持低开销堆采样:添加新功能:can_generate_sampled_object_alloc_events。添加新函数:SetHeapSamplingInterval。添加新事件类型:JVMTI_EVENT_SAMPLED_OBJECT_ALLOC。 13.0.0
2019年5月20日对“can_redefine_any_class”功能的小规范更新。现在说:“RedefineClasses可以在任何可修改的类上调用。”请参阅IsModifiableClass。(can_redefine_classes也必须设置) 13.0.0
2019年6月5日对PopFrame规范的小更新:指定线程必须暂停或必须是当前线程。(以前不允许是当前线程。) 14.0.0
2019年10月10日新类文件Record属性的小更新:指定RedefineClasses和RetransformClasses不允许更改类文件Record属性。 15.0.0
2020年5月13日新类文件PermittedSubclasses属性的小更新:指定RedefineClasses和RetransformClasses不允许更改类文件PermittedSubclasses属性。 17.0.0
2021年1月15日在“代理关闭”部分进行了小的澄清,指出如果Agent_OnAttach/Agent_OnAttach_L函数报告错误,则实现可能选择不调用Agent_OnUnload函数。 17.0.0
2021年6月8日对Heap函数1.0进行了小的更新以废弃。 19.0.0
2022年4月27日支持虚拟线程(预览):添加新功能:can_support_virtual_threads。添加新函数:SuspendAllVirtualThreads,ResumeAllVirtualThreads。添加新事件类型:JVMTI_EVENT_VIRTUAL_THREAD_START,JVMTI_EVENT_VIRTUAL_THREAD_END。添加新错误代码:JVMTI_ERROR_UNSUPPORTED_OPERATION。 21.0.0
2023年6月7日虚拟线程已最终确定为永久功能。现在规定在实时阶段代理启动将打印警告。