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语言中使用时:使用双重间接访问函数;环境指针提供上下文,并且是每个函数调用的第一个参数;例如:
在C++语言中使用时:函数作为jvmtiEnv *jvmti; ... jvmtiError err = (*jvmti)->GetLoadedClasses(jvmti, &class_count, &classes);
jvmtiEnv
的成员函数访问;环境指针不会传递给函数调用;例如:
除非另有说明,本规范中的所有示例和声明均使用C语言。 可以通过JNI调用APIjvmtiEnv *jvmti; ... jvmtiError err = jvmti->GetLoadedClasses(&class_count, &classes);
GetEnv
函数获取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与其他内存分配库和机制不兼容。
分配
jvmtiError Allocate(jvmtiEnv* env, jlong size, unsigned char** mem_ptr)
Deallocate
释放。可在任何阶段调用461.0参数 名称 类型 描述 size
jlong
要分配的字节数。 理由:
jlong
用于与JVMDI兼容。mem_ptr
unsigned char**
返回时,指向分配内存起始位置的指针。如果 size
为零,则返回NULL
。 代理传递一个指向unsigned char*
的指针。返回时,unsigned char*
指向一个新分配的大小为size
的数组。该数组应使用Deallocate
释放。错误 描述 JVMTI_ERROR_OUT_OF_MEMORY
无法满足内存请求。 JVMTI_ERROR_ILLEGAL_ARGUMENT
size
小于零。JVMTI_ERROR_NULL_POINTER
mem_ptr
为NULL
。
释放
jvmtiError Deallocate(jvmtiEnv* env, unsigned char* mem)
mem
。应使用此函数释放由JVM TI函数(包括使用Allocate
分配的内存)。必须释放所有分配的内存,否则无法回收内存。可在任何阶段调用471.0参数 名称 类型 描述 mem
unsigned 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 (
- 可运行 (
- 暂停?
- 未存活。
线程状态标志 常量 值 描述 JVMTI_THREAD_STATE_ALIVE
0x0001 线程存活。如果线程是新的(未启动)或已终止,则为零。 JVMTI_THREAD_STATE_TERMINATED
0x0002 线程已完成执行。 JVMTI_THREAD_STATE_RUNNABLE
0x0004 线程可运行。 JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER
0x0400 线程正在等待进入同步块/方法或在 Object.wait()
后等待重新进入同步块/方法。JVMTI_THREAD_STATE_WAITING
0x0080 线程正在等待。 JVMTI_THREAD_STATE_WAITING_INDEFINITELY
0x0010 线程正在无超时等待。例如, Object.wait()
。JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT
0x0020 线程正在等待指定的最大等待时间。例如, Object.wait(long)
。JVMTI_THREAD_STATE_SLEEPING
0x0040 线程正在睡眠 -- Thread.sleep
。JVMTI_THREAD_STATE_IN_OBJECT_WAIT
0x0100 线程正在等待对象监视器 -- Object.wait
。JVMTI_THREAD_STATE_PARKED
0x0200 线程被停放,例如: LockSupport.park
,LockSupport.parkUtil
和LockSupport.parkNanos
。正在睡眠的虚拟线程,在Thread.sleep
中,可能设置此状态标志,而不是JVMTI_THREAD_STATE_SLEEPING
。JVMTI_THREAD_STATE_SUSPENDED
0x100000 线程被挂起,由挂起函数(例如 SuspendThread
)挂起。如果设置了此位,其他位指的是挂起前的线程状态。JVMTI_THREAD_STATE_INTERRUPTED
0x200000 线程已被中断。 JVMTI_THREAD_STATE_IN_NATIVE
0x400000 线程在本地代码中 -- 即,正在运行尚未回调到VM或Java编程语言代码的本地方法。 运行VM编译的Java编程语言代码时不设置此标志,运行VM代码或VM支持代码时也不设置此标志。本地VM接口函数,如JNI和JVM TI函数,可能被实现为VM代码。 JVMTI_THREAD_STATE_VENDOR_1
0x10000000 由VM供应商定义。 JVMTI_THREAD_STATE_VENDOR_2
0x20000000 由VM供应商定义。 JVMTI_THREAD_STATE_VENDOR_3
0x40000000 由VM供应商定义。 java.lang.Thread.State
风格状态。java.lang.Thread.State 转换掩码 常量 值 描述 JVMTI_JAVA_LANG_THREAD_STATE_MASK
JVMTI_THREAD_STATE_TERMINATED | JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT 在比较之前使用此掩码对状态进行掩码处理 JVMTI_JAVA_LANG_THREAD_STATE_NEW
0 java.lang.Thread.State.NEW
JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED
JVMTI_THREAD_STATE_TERMINATED java.lang.Thread.State.TERMINATED
JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE
JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE java.lang.Thread.State.RUNNABLE
JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED
JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER java.lang.Thread.State.BLOCKED
JVMTI_JAVA_LANG_THREAD_STATE_WAITING
JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY java.lang.Thread.State.WAITING
JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING
JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT java.lang.Thread.State.TIMED_WAITING
JVMTI_THREAD_STATE_RUNNABLE
JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER
JVMTI_THREAD_STATE_WAITING
JVMTI_THREAD_STATE_ALIVE
,J2SETM兼容的实现将始终设置其中一个)。如果设置了其中任何一个,封闭答案JVMTI_THREAD_STATE_ALIVE
将被设置。不会同时设置以下任何一个:JVMTI_THREAD_STATE_WAITING_INDEFINITELY
JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT
JVMTI_THREAD_STATE_WAITING
,J2SETM兼容的实现将始终设置其中一个)。如果设置了任何一个,封闭答案JVMTI_THREAD_STATE_ALIVE
和JVMTI_THREAD_STATE_WAITING
将被设置。不会同时设置以下任何一个:JVMTI_THREAD_STATE_IN_OBJECT_WAIT
JVMTI_THREAD_STATE_PARKED
JVMTI_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
0
Object.wait(3000)
时的线程状态将是:JVMTI_THREAD_STATE_ALIVE + JVMTI_THREAD_STATE_WAITING + JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT + JVMTI_THREAD_STATE_MONITOR_WAITING
JVMTI_THREAD_STATE_ALIVE + JVMTI_THREAD_STATE_RUNNABLE + JVMTI_THREAD_STATE_SUSPENDED
jint state; jvmtiError err; err = (*jvmti)->GetThreadState(jvmti, thread, &state); if (err == JVMTI_ERROR_NONE) { if (state & JVMTI_THREAD_STATE_SLEEPING) { ...
Object.wait
,停放或睡眠中),代码将是:if (state & JVMTI_THREAD_STATE_WAITING) { ...
if ((state & (JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_TERMINATED)) == 0) { ...
Object.wait
:if (state & JVMTI_THREAD_STATE_IN_OBJECT_WAIT) { if (state & JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT) { printf("in Object.wait(long timeout)\n"); } else { printf("in Object.wait()\n"); } }
java.lang.Thread.State
的关系 从java.lang.Thread.getState()
返回的java.lang.Thread.State
表示的线程状态是从此函数返回的信息的子集。可以使用提供的转换掩码确定相应的java.lang.Thread.State
。例如,这将返回java.lang.Thread.State
线程状态的名称:err = (*jvmti)->GetThreadState(jvmti, thread, &state); abortOnError(err); switch (state & JVMTI_JAVA_LANG_THREAD_STATE_MASK) { case JVMTI_JAVA_LANG_THREAD_STATE_NEW: return "NEW"; case JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED: return "TERMINATED"; case JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE: return "RUNNABLE"; case JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED: return "BLOCKED"; case JVMTI_JAVA_LANG_THREAD_STATE_WAITING: return "WAITING"; case JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING: return "TIMED_WAITING"; }
参数 名称 类型 描述 thread
jthread
要查询的线程。如果 thread
为NULL
,则使用当前线程。thread_state_ptr
jint*
返回时,指向由线程状态标志定义的状态标志。代理传递指向 jint
的指针。返回时,jint
已设置。错误 描述 JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_NULL_POINTER
thread_state_ptr
为NULL
。
获取当前线程
jvmtiError GetCurrentThread(jvmtiEnv* env, jthread* thread_ptr)
can_generate_early_vmstart
功能并且尚未初始化java.lang.Thread
类,则在启动阶段该函数可能返回NULL
。 请注意,大多数接受线程作为参数的JVM TI函数将接受NULL
表示当前线程。参数 名称 类型 描述 thread_ptr
jthread*
返回时,指向当前线程或 NULL
。代理传递指向jthread
的指针。返回时,jthread
已设置。由thread_ptr
返回的对象是JNI本地引用,必须进行管理。错误 描述 JVMTI_ERROR_NULL_POINTER
thread_ptr
为NULL
。
获取所有线程
jvmtiError GetAllThreads(jvmtiEnv* env, jint* threads_count_ptr, jthread** threads_ptr)
java.lang.Thread.isAlive()
返回true
,即线程已启动但尚未终止。线程的范围由JVM的上下文确定 TI环境,通常是所有附加到VM的线程。参数 名称 类型 描述 threads_count_ptr
jint*
返回时,指向线程数。 代理传递一个指向 jint
的指针。返回时,jint
已设置。threads_ptr
jthread**
返回时,指向每个线程的引用数组。 代理传递一个指向 jthread*
的指针。返回时,jthread*
指向一个新分配的大小为*threads_count_ptr
的数组。该数组应使用Deallocate
释放。由threads_ptr
返回的对象是JNI本地引用,必须进行管理。错误 描述 JVMTI_ERROR_NULL_POINTER
threads_count_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
threads_ptr
为NULL
。
挂起线程
jvmtiError SuspendThread(jvmtiEnv* env, jthread thread)
ResumeThread
。如果线程当前已挂起,则此函数不执行任何操作并返回错误。能力 效果 can_suspend
可以挂起和恢复线程 参数 名称 类型 描述 thread
jthread
要挂起的线程。如果 thread
为NULL
,则使用当前线程。错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备 can_suspend
能力。使用AddCapabilities
。JVMTI_ERROR_THREAD_SUSPENDED
线程已经被挂起。 JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(尚未启动或已终止)。
挂起线程列表
jvmtiError SuspendThreadList(jvmtiEnv* env, jint request_count, const jthread* request_list, jvmtiError* results)
request_count
指定的线程,这些线程在request_list
数组中指定。线程可以使用ResumeThreadList
或ResumeThread
恢复。如果调用线程在request_list
数组中指定,则此函数将一直等到其他线程恢复它。在挂起线程时遇到的错误将在results
数组中返回,而不是在此函数的返回值中。当前已挂起的线程状态不会改变。能力 效果 can_suspend
可以挂起和恢复线程 request_count
个元素的数组。返回时,填充有相应线程挂起的错误代码。如果线程由此调用挂起,则错误代码将为JVMTI_ERROR_NONE
。可能的错误代码是为SuspendThread
指定的那些。 代理传入一个足够大以容纳request_count
个jvmtiError
元素的数组。数组元素的传入值将被忽略。返回时,元素被设置。参数 名称 类型 描述 request_count
jint
要挂起的线程数。 request_list
const jthread*
要挂起的线程列表。 代理传入一个包含 request_count
个jthread
元素的数组。results
jvmtiError*
暂停所有虚拟线程
jvmtiError SuspendAllVirtualThreads(jvmtiEnv* env, jint except_count, const jthread* except_list)
ResumeAllVirtualThreads
或ResumeThreadList
或ResumeThread
来恢复虚拟线程。能力 效果 can_suspend
可以暂停和恢复线程 can_support_virtual_threads
可以支持虚拟线程 名称 类型 描述 except_count
jint
except_list
const jthread *
不暂停的线程列表。 代理传入一个包含 except_count
个jthread
元素的数组。如果except_list
为NULL
,且except_count == 0
,则不是错误。
恢复线程
jvmtiError ResumeThread(jvmtiEnv* env, jthread thread)
SuspendThread
)当前暂停的任何线程将恢复执行;其他线程不受影响。能力 效果 can_suspend
可以暂停和恢复线程 名称 类型 描述 thread
jthread
要恢复的线程。 错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_suspend
。请使用AddCapabilities
。JVMTI_ERROR_THREAD_NOT_SUSPENDED
线程未被暂停。 JVMTI_ERROR_INVALID_TYPESTATE
线程的状态已被修改,现在不一致。 JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(尚未启动或已终止)。
恢复线程列表
jvmtiError ResumeThreadList(jvmtiEnv* env, jint request_count, const jthread* request_list, jvmtiError* results)
request_count
中指定的线程。request_list
数组。通过JVM暂停函数(例如SuspendThreadList
)暂停的任何线程将恢复执行。能力 效果 can_suspend
可以暂停和恢复线程 参数 名称 类型 描述 request_count
jint
要恢复的线程数。 request_list
const jthread*
要恢复的线程。 代理传入一个包含 request_count
个jthread
元素的数组。results
jvmtiError*
代理提供的一个包含 request_count
个元素的数组。返回时,填充有相应线程恢复的错误代码。如果线程是通过此调用暂停的,则错误代码将是JVMTI_ERROR_NONE
。可能的错误代码是为ResumeThread
指定的那些。 代理传入一个足够大以容纳request_count
个jvmtiError
元素的数组。数组元素的传入值将被忽略。返回时,这些元素将被设置。
恢复所有虚拟线程
jvmtiError ResumeAllVirtualThreads(jvmtiEnv* env, jint except_count, const jthread* except_list)
SuspendAllVirtualThreads
或SuspendThreadList
或SuspendThread
来暂停。能力 效果 can_suspend
可以暂停和恢复线程 can_support_virtual_threads
可以支持虚拟线程 参数 名称 类型 描述 except_count
jint
except_list
const jthread *
不要恢复的线程列表。 代理传入一个包含 except_count
个jthread
元素的数组。如果except_list
为NULL
,且except_count == 0
,则不是错误。
停止线程
jvmtiError StopThread(jvmtiEnv* env, jthread thread, jobject exception)
能力 效果 can_signal_thread
可以向线程发送停止或中断信号 参数 名称 类型 描述 thread
jthread
要停止的线程。当虚拟线程在事件中被暂停时, StopThread
函数可用于向虚拟线程发送异步异常。实现可能支持在其他情况下向暂停的虚拟线程发送异步异常。exception
jobject
异步异常对象。 错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_signal_thread
。请使用AddCapabilities
。JVMTI_ERROR_THREAD_NOT_SUSPENDED
线程是虚拟线程,未被暂停且不是当前线程。 JVMTI_ERROR_OPAQUE_FRAME
线程是暂停的虚拟线程,实现无法从当前帧抛出异步异常。 JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
未启动或已终止。JVMTI_ERROR_INVALID_OBJECT
exception
不是对象。
中断线程
jvmtiError InterruptThread(jvmtiEnv* env, jthread thread)
java.lang.Thread.interrupt
)。能力 效果 can_signal_thread
可以向线程发送停止或中断信号 参数 名称 类型 描述 thread
jthread
要中断的线程。 错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_signal_thread
。请使用AddCapabilities
。JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
未启动或已终止。
获取线程信息
typedef struct { char* name; jint priority; jboolean is_daemon; jthreadGroup thread_group; jobject context_class_loader; } jvmtiThreadInfo;
jvmtiError GetThreadInfo(jvmtiEnv* env, jthread thread, jvmtiThreadInfo* info_ptr)
jvmtiThreadInfo
- 线程信息结构字段 类型 描述 name
char*
线程名称,编码为修改的 UTF-8字符串。 priority
jint
线程优先级。参见线程优先级常量: jvmtiThreadPriority
。虚拟线程的优先级始终为JVMTI_THREAD_NORM_PRIORITY
。is_daemon
jboolean
这是守护线程吗?虚拟线程的守护状态始终为 JNI_TRUE
。thread_group
jthreadGroup
此线程所属的线程组。如果线程已终止,则为 NULL
。context_class_loader
jobject
与此线程关联的上下文类加载器。 参数 名称 类型 描述 thread
jthread
要查询的线程。如果 thread
为NULL
,则使用当前线程。info_ptr
jvmtiThreadInfo*
返回时,填充有描述指定线程的信息。 代理传递指向 jvmtiThreadInfo
的指针。返回时,jvmtiThreadInfo
已设置。在jvmtiThreadInfo
的name
字段中返回的指针是新分配的数组。应使用Deallocate
释放数组。在jvmtiThreadInfo
的thread_group
字段中返回的对象是JNI本地引用,必须管理。在jvmtiThreadInfo
的context_class_loader
字段中返回的对象是JNI本地引用,必须管理。错误 描述 JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_NULL_POINTER
info_ptr
为NULL
。
获取拥有的监视器信息
jvmtiError GetOwnedMonitorInfo(jvmtiEnv* env, jthread thread, jint* owned_monitor_count_ptr, jobject** owned_monitors_ptr)
能力 效果 can_get_owned_monitor_info
可以获取有关监视器所有权的信息 - GetOwnedMonitorInfo
参数 名称 类型 描述 thread
jthread
要查询的线程。如果 thread
为NULL
,则使用当前线程。owned_monitor_count_ptr
jint*
返回的监视器数量。 代理传递一个指向 jint
的指针。返回时,jint
已被设置。owned_monitors_ptr
jobject**
拥有的监视器数组。 代理传递一个指向 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_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(未启动或已终止)。JVMTI_ERROR_NULL_POINTER
owned_monitor_count_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
owned_monitors_ptr
为NULL
。
获取拥有的监视器堆栈深度信息
typedef struct { jobject monitor; jint stack_depth; } jvmtiMonitorStackDepthInfo;
jvmtiError GetOwnedMonitorStackDepthInfo(jvmtiEnv* env, jthread thread, jint* monitor_info_count_ptr, jvmtiMonitorStackDepthInfo** monitor_info_ptr)
能力 效果 can_get_owned_monitor_stack_depth_info
可以获取具有堆栈深度的拥有监视器的信息 - GetOwnedMonitorStackDepthInfo
jvmtiMonitorStackDepthInfo
- 监视器堆栈深度信息结构字段 类型 描述 monitor
jobject
拥有的监视器。 stack_depth
jint
堆栈深度。对应于堆栈帧函数中使用的堆栈深度。即,零是当前帧,一是调用当前帧的帧。如果实现无法确定堆栈深度(例如,对于通过JNI MonitorEnter
获取的监视器),则为负一。参数 名称 类型 描述 thread
jthread
要查询的线程。如果 thread
为NULL
,则使用当前线程。monitor_info_count_ptr
jint*
返回的监视器数量。 代理传递一个指向 jint
的指针。返回时,jint
已被设置。monitor_info_ptr
jvmtiMonitorStackDepthInfo **
拥有的监视器深度信息数组。 代理传递一个指向 jvmtiMonitorStackDepthInfo*
的指针。返回时,jvmtiMonitorStackDepthInfo*
指向一个新分配的大小为*monitor_info_count_ptr
的数组。应使用Deallocate
释放数组。在jvmtiMonitorStackDepthInfo
的monitor
字段中返回的对象是JNI本地引用,必须进行管理。
获取当前争用的监视器
jvmtiError GetCurrentContendedMonitor(jvmtiEnv* env, jthread thread, jobject* monitor_ptr)
java.lang.Object.wait
重新获取其监视器的对象(如果有)。能力 效果 can_get_current_contended_monitor
可以 GetCurrentContendedMonitor
参数 名称 类型 描述 thread
jthread
要查询的线程。如果 thread
为NULL
,则使用当前线程。monitor_ptr
jobject*
返回时,填充有当前争用的监视器,如果没有则为NULL。 代理传递一个指向 jobject
的指针。返回时,jobject
已被设置。由monitor_ptr
返回的对象是JNI本地引用,必须进行管理。错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_get_current_contended_monitor
。使用AddCapabilities
。JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(未启动或已终止)。JVMTI_ERROR_NULL_POINTER
monitor_ptr
为NULL
。
代理启动函数
typedef void (JNICALL *jvmtiStartFunction) (jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg);
RunAgentThread
启动的代理线程的入口点。参数 名称 类型 描述 jvmti_env
jvmtiEnv *
JVM TI环境。 jni_env
JNIEnv *
JNI环境。 arg
void *
传递给 RunAgentThread
的arg
参数。
运行代理线程
jvmtiError RunAgentThread(jvmtiEnv* env, jthread thread, jvmtiStartFunction proc, const void* arg, jint priority)
arg
被转发到启动函数(由proc
指定)作为其单个参数。此函数允许创建用于处理与另一个进程的通信或处理事件而无需加载java.lang.Thread
的特殊子类或java.lang.Runnable
的实现者。相反,创建的线程可以完全在本机代码中运行。但是,创建的线程需要一个新创建的java.lang.Thread
实例(由参数thread
引用),它将与之关联。可以使用JNI调用创建线程对象。 为方便起见,提供以下常见线程优先级:线程优先级常量 常量 值 描述 JVMTI_THREAD_MIN_PRIORITY
1 可能的最低线程优先级 JVMTI_THREAD_NORM_PRIORITY
5 正常线程优先级 JVMTI_THREAD_MAX_PRIORITY
10 可能的最高线程优先级 priority
作为守护线程启动。如果启用,将发送一个ThreadStart
事件。 由于线程已启动,因此此函数返回时线程将处于活动状态,除非线程立即终止。 线程的线程组被忽略--具体来说,线程不会添加到线程组中,并且线程不会在Java编程语言或JVM TI级别的线程组查询中看到。 线程对Java编程语言查询不可见,但包含在JVM TI查询中(例如,GetAllThreads
和GetAllStackTraces
)。 在执行proc
时,新线程将附加到VM--请参阅JNI文档中的附加到VM。参数 名称 类型 描述 thread
jthread
要运行的线程。该 thread
可能不是虚拟线程。否则,将返回错误代码JVMTI_ERROR_UNSUPPORTED_OPERATION
。proc
jvmtiStartFunction
启动函数。 arg
const void *
启动函数的参数。 代理传递一个指针。如果 arg
为NULL
,则将NULL
传递给启动函数。priority
jint
启动线程的优先级。可以使用 java.lang.Thread.setPriority
允许的任何线程优先级,包括jvmtiThreadPriority
中的优先级。
设置线程本地存储
jvmtiError SetThreadLocalStorage(jvmtiEnv* env, jthread thread, const void* data)
NULL
。代理可以分配内存,其中存储特定于线程的信息。通过设置线程本地存储,然后可以使用GetThreadLocalStorage
访问它。 代理调用此函数以设置JVM TI线程本地存储的值。JVM TI向代理提供一个指针大小的线程本地存储,可用于记录每个线程的信息。参数 名称 类型 描述 thread
jthread
存储到此线程。如果 thread
为NULL
,则使用当前线程。data
const void *
要输入到线程本地存储中的值。 代理传递一个指针。如果 data
为NULL
,则值设置为NULL
。错误 描述 JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(尚未启动或已终止)。
获取线程本地存储
jvmtiError GetThreadLocalStorage(jvmtiEnv* env, jthread thread, void** data_ptr)
参数 名称 类型 描述 thread
jthread
从此线程检索。如果 thread
为NULL
,则使用当前线程。data_ptr
void**
通过此指针返回线程本地存储的值。如果未使用 SetThreadLocalStorage
设置线程本地存储,则返回的指针为NULL
。错误 描述 JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(尚未启动或已终止)。JVMTI_ERROR_NULL_POINTER
data_ptr
为NULL
。
线程组
线程组函数: 线程组类型:jvmtiThreadGroupInfo
- 线程组信息结构
获取顶级线程组
jvmtiError GetTopThreadGroups(jvmtiEnv* env, jint* group_count_ptr, jthreadGroup** groups_ptr)
参数 名称 类型 描述 group_count_ptr
jint*
返回时,指向顶级线程组的数量。 代理传递一个指向 jint
的指针。返回时,jint
已设置。groups_ptr
jthreadGroup**
返回时,指向顶级线程组数组的指针。 代理传递一个指向 jthreadGroup*
的指针。返回时,jthreadGroup*
指向一个新分配的大小为*group_count_ptr
的数组。数组应使用Deallocate
释放。由groups_ptr
返回的对象是JNI本地引用,必须管理。错误 描述 JVMTI_ERROR_NULL_POINTER
group_count_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
groups_ptr
为NULL
。
获取线程组信息
typedef struct { jthreadGroup parent; char* name; jint max_priority; jboolean is_daemon; } jvmtiThreadGroupInfo;
jvmtiError GetThreadGroupInfo(jvmtiEnv* env, jthreadGroup group, jvmtiThreadGroupInfo* info_ptr)
jvmtiThreadGroupInfo
结构的字段中。jvmtiThreadGroupInfo
- 线程组信息结构字段 类型 描述 parent
jthreadGroup
父线程组。 name
char*
线程组的名称,编码为修改后的UTF-8字符串。 max_priority
jint
此线程组的最大优先级。 is_daemon
jboolean
这是一个守护线程组吗? 参数 名称 类型 描述 group
jthreadGroup
要查询的线程组。 info_ptr
jvmtiThreadGroupInfo*
返回时,填充描述指定线程组的信息。 代理传递一个指向 jvmtiThreadGroupInfo
的指针。返回时,jvmtiThreadGroupInfo
已设置。在jvmtiThreadGroupInfo
的parent
字段中返回的对象是JNI本地引用,必须进行管理。在jvmtiThreadGroupInfo
的name
字段中返回的指针是新分配的数组。应使用Deallocate
释放数组。错误 描述 JVMTI_ERROR_INVALID_THREAD_GROUP
group
不是线程组对象。JVMTI_ERROR_NULL_POINTER
info_ptr
为NULL
。
获取线程组子项
jvmtiError GetThreadGroupChildren(jvmtiEnv* env, jthreadGroup group, jint* thread_count_ptr, jthread** threads_ptr, jint* group_count_ptr, jthreadGroup** groups_ptr)
参数 名称 类型 描述 group
jthreadGroup
要查询的组。 thread_count_ptr
jint*
返回时,指向此线程组中活动线程的数量。 代理传递一个指向 jint
的指针。返回时,jint
已设置。threads_ptr
jthread**
返回时,指向此线程组中活动线程的数组。 代理传递一个指向 jthread*
的指针。返回时,jthread*
指向一个新分配的大小为*thread_count_ptr
的数组。应使用Deallocate
释放数组。由threads_ptr
返回的对象是JNI本地引用,必须进行管理。group_count_ptr
jint*
返回时,指向子线程组的数量。 代理传递一个指向 jint
的指针。返回时,jint
已设置。groups_ptr
jthreadGroup**
返回时,指向子线程组的数组。 代理传递一个指向 jthreadGroup*
的指针。返回时,jthreadGroup*
指向一个新分配的大小为*group_count_ptr
的数组。应使用Deallocate
释放数组。由groups_ptr
返回的对象是JNI本地引用,必须进行管理。错误 描述 JVMTI_ERROR_INVALID_THREAD_GROUP
group
不是线程组对象。JVMTI_ERROR_NULL_POINTER
thread_count_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
threads_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
group_count_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
groups_ptr
为NULL
。
堆栈帧
堆栈帧函数: 堆栈帧类型:jvmtiFrameInfo
- 堆栈帧信息结构jvmtiStackInfo
- 堆栈信息结构
main()
和run()
更深的帧。但是,这种呈现必须在使用堆栈帧或堆栈深度的所有JVM TI功能中保持一致。堆栈帧信息结构
返回有关堆栈帧的信息在此结构中。typedef struct { jmethodID method; jlocation location; } jvmtiFrameInfo;
jvmtiFrameInfo
- 堆栈帧信息结构字段 类型 描述 method
jmethodID
在此帧中执行的方法。 location
jlocation
在此帧中执行的指令的索引。如果帧正在执行本地方法,则为 -1
。堆栈信息结构
返回一组堆栈帧的信息在此结构中。typedef struct { jthread thread; jint state; jvmtiFrameInfo* frame_buffer; jint frame_count; } jvmtiStackInfo;
jvmtiStackInfo
- 堆栈信息结构字段 类型 描述 thread
jthread
返回时,跟踪的线程。 state
jint
返回时,线程状态。参见 GetThreadState
。frame_buffer
jvmtiFrameInfo *
返回时,此代理分配的缓冲区填充有堆栈帧信息。 frame_count
jint
返回时,填充到 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
记录。参数 名称 类型 描述 thread
jthread
获取此线程的堆栈跟踪。如果 thread
为NULL
,则使用当前线程。start_depth
jint
从此深度开始检索帧。如果为非负数,则从当前帧计数,第一个检索的帧位于深度 start_depth
处。例如,如果为零,则从当前帧开始;如果为一,则从当前帧的调用者开始;如果为二,则从当前帧的调用者的调用者开始;依此类推。如果为负数,则从最老帧下方计数,第一个检索的帧位于深度stackDepth+ start_depth
处,其中stackDepth是堆栈上的帧数。例如,如果为负一,则只检索最老的帧;如果为负二,则从最老帧调用。max_frame_count
jint
frame_buffer
jvmtiFrameInfo *
返回时,此代理分配的缓冲区填充有堆栈帧信息。 代理传递一个足够大的数组,可以容纳 max_frame_count
个jvmtiFrameInfo
元素。数组元素的传入值将被忽略。返回时,设置了*count_ptr
的元素。count_ptr
jint*
返回时,指向填充记录数的指针。对于非负的 start_depth
,这将是min(max_frame_count
, stackDepth- start_depth
)。对于负的start_depth
,这将是min(max_frame_count
,-start_depth
)。 代理传递一个指向jint
的指针。返回时,设置了jint
。错误 描述 JVMTI_ERROR_ILLEGAL_ARGUMENT
start_depth
为正且大于或等于stackDepth。或start_depth
为负且小于-stackDepth。JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(尚未启动或已终止)。JVMTI_ERROR_ILLEGAL_ARGUMENT
max_frame_count
小于0
。JVMTI_ERROR_NULL_POINTER
frame_buffer
为NULL
。JVMTI_ERROR_NULL_POINTER
count_ptr
为NULL
。
获取所有堆栈跟踪
jvmtiError GetAllStackTraces(jvmtiEnv* env, jint max_frame_count, jvmtiStackInfo** stack_info_ptr, jint* thread_count_ptr)
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_count
jint
每个线程检索的最大 jvmtiFrameInfo
记录数。stack_info_ptr
jvmtiStackInfo **
返回时,此缓冲区填充了每个线程的堆栈信息。 thread_count_ptr
确定jvmtiStackInfo
记录的数量。 请注意,此缓冲区被分配为包括jvmtiStackInfo.frame_buffer
指向的jvmtiFrameInfo
缓冲区。 这些缓冲区不得单独释放。 代理程序传递一个指向jvmtiStackInfo*
的指针。 返回时,jvmtiStackInfo*
指向一个新分配的数组。 应使用Deallocate
释放数组。jvmtiStackInfo
字段thread
中返回的对象是JNI本地引用,必须管理。thread_count_ptr
jint*
错误 描述 JVMTI_ERROR_ILLEGAL_ARGUMENT
max_frame_count
小于0
。JVMTI_ERROR_NULL_POINTER
stack_info_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
thread_count_ptr
为NULL
。
获取线程列表堆栈跟踪
jvmtiError GetThreadListStackTraces(jvmtiEnv* env, jint thread_count, const jthread* thread_list, jint max_frame_count, jvmtiStackInfo** stack_info_ptr)
max_frame_count
小于堆栈深度,则为该线程返回max_frame_count
个最顶部的帧,否则返回整个堆栈。最顶部的帧,即最近调用的帧,位于返回的缓冲区开头。 所有堆栈同时收集,即在采样一个线程和下一个线程之间不会发生线程状态或堆栈的更改。线程无需暂停。 如果线程尚未启动或在收集堆栈信息之前终止,则将返回零长度堆栈(jvmtiStackInfo.frame_count
将为零),并且可以检查线程jvmtiStackInfo.state
。 请参阅类似函数GetAllStackTraces
的示例。代理程序传入一个包含 thread_count
个jthread
元素的数组。jvmtiFrameInfo
记录数。thread_count
确定jvmtiStackInfo
记录的数量。 请注意,此缓冲区被分配为包括jvmtiFrameInfo
缓冲区指向的jvmtiStackInfo.frame_buffer
。 这些缓冲区不得单独释放。 代理程序传递一个指向jvmtiStackInfo*
的指针。 返回时,jvmtiStackInfo*
指向一个新分配的大小为*thread_count
的数组。 应使用Deallocate
释放数组。jvmtiStackInfo
字段thread
中返回的对象是JNI本地引用,必须 管理。参数 名称 类型 描述 thread_count
jint
thread_list
const jthread*
max_frame_count
jint
stack_info_ptr
jvmtiStackInfo **
获取帧计数
jvmtiError GetFrameCount(jvmtiEnv* env, jthread thread, jint* count_ptr)
参数 名称 类型 描述 线程
jthread
要查询的线程。如果 thread
为NULL
,则使用当前线程。count_ptr
jint*
返回时,指向调用堆栈中帧的数量。 代理传递指向 jint
的指针。返回时,jint
已设置。错误 描述 JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(未启动或已终止)。JVMTI_ERROR_NULL_POINTER
count_ptr
为NULL
。
弹出帧
jvmtiError PopFrame(jvmtiEnv* env, jthread thread)
thread
的堆栈中的当前帧。弹出帧将您带回到上一个帧。当线程恢复时,线程的执行状态将重置为调用方法被调用之前的状态。也就是(使用Java™虚拟机规范术语):- 当前帧被丢弃,前一个帧变为当前帧
- 操作数栈被恢复--参数值被添加回去,如果调用不是
invokestatic
,objectref
也被添加回去 - Java虚拟机PC被恢复为调用指令的操作码
PopFrame
和恢复线程之间,堆栈的状态是未定义的。要弹出第一个帧之外的帧,必须重复以下三个步骤:- 通过事件(步骤,断点,...)暂停线程
- 调用
PopFrame
- 恢复线程
synchronized
方法)和在被调用方法中进入的锁synchronized
块被释放。注意:这不适用于本地锁或java.util.concurrent.locks
锁。 最终块不会被执行。 对全局状态的更改未被处理,因此保持更改。 指定的线程必须被暂停或必须是当前线程。 被调用方法和调用方法都必须是非本地Java编程语言方法。 此函数不会生成任何JVM TI事件。功能 效果 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_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(未启动或已终止)。
获取帧位置
jvmtiError GetFrameLocation(jvmtiEnv* env, jthread thread, jint depth, jmethodID* method_ptr, jlocation* location_ptr)
参数 名称 类型 描述 thread
jthread
要查询的帧的线程。如果 thread
为NULL
,则使用当前线程。depth
jint
要查询的帧的深度。 method_ptr
jmethodID*
返回时,指向当前位置的方法。 代理传递指向 jmethodID
的指针。返回时,jmethodID
已设置。location_ptr
jlocation*
返回时,指向当前执行指令的索引。如果帧正在执行本地方法,则设置为 -1
。 代理传递指向jlocation
的指针。返回时,jlocation
已设置。错误 描述 JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
未启动或已终止。JVMTI_ERROR_ILLEGAL_ARGUMENT
depth
小于零。JVMTI_ERROR_NO_MORE_FRAMES
指定深度处没有堆栈帧。 JVMTI_ERROR_NULL_POINTER
method_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
location_ptr
为NULL
。
通知帧弹出
jvmtiError NotifyFramePop(jvmtiEnv* env, jthread thread, jint depth)
depth
的帧从堆栈中弹出时,生成一个FramePop
事件。有关详细信息,请参阅FramePop
事件。只有对应于非本地Java编程语言方法的帧才能接收通知。 指定的线程必须被挂起或必须是当前线程。能力 效果 can_generate_frame_pop_events
可以设置并获取 FramePop
事件参数 名称 类型 描述 thread
jthread
将生成帧弹出事件的帧的线程。如果 thread
为NULL
,则使用当前线程。depth
jint
将生成帧弹出事件的帧的深度。 错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_generate_frame_pop_events
。使用AddCapabilities
。JVMTI_ERROR_OPAQUE_FRAME
在 depth
处的帧正在执行本地方法。JVMTI_ERROR_THREAD_NOT_SUSPENDED
线程未被挂起且不是当前线程。 JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
未启动或已终止。JVMTI_ERROR_ILLEGAL_ARGUMENT
depth
小于零。JVMTI_ERROR_NO_MORE_FRAMES
指定深度处没有堆栈帧。
强制提前返回
强制提前返回函数: 这些函数允许代理强制从当前帧返回。指定的线程必须被挂起或必须是当前线程。这些函数可用于在事件挂起时强制从虚拟线程的当前帧返回。实现可能支持在其他情况下强制从挂起的虚拟线程的当前帧返回。将提前返回的方法称为 被调用方法。被调用方法是在调用函数时指定线程的当前方法(由 Java™虚拟机规范,第3.6章 定义)。 返回发生在此线程上的Java编程语言代码的执行恢复时。在调用这些函数和线程执行恢复之间,堆栈的状态是未定义的。 被调用方法中不会执行更多指令。特别地,finally块不会执行。注意:这可能导致应用程序中的不一致状态。 通过调用被调用方法获取的锁(如果它是一个synchronized
方法)以及在被调用方法内部进入的synchronized
块获取的锁将被释放。注意:这不适用于本地锁或java.util.concurrent.locks
锁。 事件,例如MethodExit
,将像在正常返回时生成。 被调用方法必须是非本地Java编程语言方法。在堆栈上只有一个帧的线程上强制返回会导致在恢复时线程退出。
强制提前返回 - 对象
jvmtiError ForceEarlyReturnObject(jvmtiEnv* env, jthread thread, jobject value)
Object
或Object
的子类的方法返回。能力 效果 can_force_early_return
可以从方法中提前返回,如Force Early Return类别中所述。 参数 名称 类型 描述 thread
jthread
要提前返回其当前帧的线程。如果 thread
为NULL
,则使用当前线程。value
jobject
被调用帧的返回值。一个对象或 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_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(尚未启动或已终止)。JVMTI_ERROR_INVALID_OBJECT
value
不是对象。
提前返回 - 整数
jvmtiError ForceEarlyReturnInt(jvmtiEnv* env, jthread thread, jint value)
int
、short
、char
、byte
或boolean
的方法中返回。能力 效果 can_force_early_return
可以从方法中提前返回,如Force Early Return类别中所述。 参数 名称 类型 描述 thread
jthread
要提前返回其当前帧的线程。如果 thread
为NULL
,则使用当前线程。value
jint
被调用帧的返回值。 错误 描述 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_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(尚未启动或已终止)。
提前返回 - 长整型
jvmtiError ForceEarlyReturnLong(jvmtiEnv* env, jthread thread, jlong value)
long
的方法中返回。能力 效果 can_force_early_return
可以从方法中提前返回,如Force Early Return类别中所述。 参数 名称 类型 描述 thread
jthread
要提前返回其当前帧的线程。如果 thread
为NULL
,则使用当前线程。value
jlong
被调用帧的返回值。 错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_force_early_return
。请使用AddCapabilities
。JVMTI_ERROR_OPAQUE_FRAME
尝试从对应于本地方法的帧中提前返回。线程是一个挂起的虚拟线程,实现无法强制其当前帧返回。或者实现无法在此帧上提供此功能。 JVMTI_ERROR_TYPE_MISMATCH
调用方法的结果类型不是 long
。JVMTI_ERROR_THREAD_NOT_SUSPENDED
线程未挂起且不是当前线程。 JVMTI_ERROR_NO_MORE_FRAMES
调用堆栈上没有帧。 JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(未启动或已终止)。
强制提前返回 - 浮点数
jvmtiError ForceEarlyReturnFloat(jvmtiEnv* env, jthread thread, jfloat value)
float
的方法中返回。能力 效果 can_force_early_return
可以从方法中提前返回,如“强制提前返回”类别中描述的。 参数 名称 类型 描述 thread
jthread
要提前返回其当前帧的线程。如果 thread
为NULL
,则使用当前线程。value
jfloat
调用帧的返回值。 错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_force_early_return
。请使用AddCapabilities
。JVMTI_ERROR_OPAQUE_FRAME
尝试从对应于本地方法的帧中提前返回。线程是一个挂起的虚拟线程,实现无法强制其当前帧返回。或者实现无法在此帧上提供此功能。 JVMTI_ERROR_TYPE_MISMATCH
调用方法的结果类型不是 float
。JVMTI_ERROR_THREAD_NOT_SUSPENDED
线程未挂起且不是当前线程。 JVMTI_ERROR_NO_MORE_FRAMES
调用堆栈上没有帧。 JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(未启动或已终止)。
强制提前返回 - 双精度浮点数
jvmtiError ForceEarlyReturnDouble(jvmtiEnv* env, jthread thread, jdouble value)
double
的方法中返回。能力 效果 can_force_early_return
可以从方法中提前返回,如“强制提前返回”类别中描述的。 参数 名称 类型 描述 thread
jthread
要提前返回其当前帧的线程。如果 thread
为NULL
,则使用当前线程。value
jdouble
调用帧的返回值。 错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_force_early_return
。请使用AddCapabilities
。JVMTI_ERROR_OPAQUE_FRAME
尝试从对应于本地方法的帧中提前返回。线程是一个挂起的虚拟线程,实现无法强制其当前帧返回。或者实现无法在此帧上提供此功能。 JVMTI_ERROR_TYPE_MISMATCH
调用方法的结果类型不是 double
。JVMTI_ERROR_THREAD_NOT_SUSPENDED
线程未挂起且不是当前线程。 JVMTI_ERROR_NO_MORE_FRAMES
调用堆栈上没有帧。 JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(未启动或已终止)。
强制提前返回 - 无返回值
jvmtiError ForceEarlyReturnVoid(jvmtiEnv* env, jthread thread)
void
。能力 效果 can_force_early_return
可以从方法中提前返回,如“强制提前返回”类别中所述。 参数 名称 类型 描述 thread
jthread
要提前返回其当前帧的线程。如果 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_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(尚未启动或已终止)。
堆
堆函数: 堆函数类型: 堆类型:jvmtiHeapReferenceKind
- 堆引用枚举jvmtiPrimitiveType
- 基本类型枚举jvmtiHeapReferenceInfoField
- 字段引用的引用信息结构jvmtiHeapReferenceInfoArray
- 数组引用的引用信息结构jvmtiHeapReferenceInfoConstantPool
- 常量池引用的引用信息结构jvmtiHeapReferenceInfoStackLocal
- 局部变量引用的引用信息结构jvmtiHeapReferenceInfoJniLocal
- JNI本地引用的引用信息结构jvmtiHeapReferenceInfoReserved
- 其他引用的引用信息结构jvmtiHeapReferenceInfo
- 引用信息结构jvmtiHeapCallbacks
- 堆回调函数结构
对象标记
标记是与对象关联的值。标记由代理使用SetTag
函数显式设置,或者由诸如jvmtiHeapIterationCallback
之类的回调函数设置。 标记是局部于环境的;也就是说,一个环境的标记在另一个环境中不可见。 标记是jlong
值,可以简单地用于标记对象或存储指向更详细信息的指针。未标记的对象的标记为零。将标记设置为零会使对象未标记。堆回调函数
遍历堆并递归跟踪对象引用的堆函数使用代理提供的回调函数来传递信息。 这些堆回调函数必须遵守以下限制--这些回调不能使用JNI函数。这些回调不能使用JVM TI函数,除非明确允许使用的回调安全函数(请参阅原始监视器、内存管理和环境本地存储函数)。 实现可以在内部线程或调用迭代函数的线程上调用回调。堆回调是单线程的--一次只会调用一个回调。 堆过滤标志可用于基于对象的标记状态或其类来阻止报告。如果未设置任何标志(jint
为零),则不会过滤对象。堆过滤标志 常量 值 描述 JVMTI_HEAP_FILTER_TAGGED
0x4 过滤已标记的对象。已标记的对象不包括在内。 JVMTI_HEAP_FILTER_UNTAGGED
0x8 过滤未标记的对象。未标记的对象不包括在内。 JVMTI_HEAP_FILTER_CLASS_TAGGED
0x10 过滤具有已标记类的对象。类已标记的对象不包括在内。 JVMTI_HEAP_FILTER_CLASS_UNTAGGED
0x20 过滤具有未标记类的对象。类未标记的对象不包括在内。 JVMTI_VISIT_OBJECTS
)。堆访问控制标志 常量 值 描述 JVMTI_VISIT_OBJECTS
0x100 如果我们正在访问一个对象,并且此回调是由 FollowReferences
发起的,则遍历此对象的引用。否则忽略。JVMTI_VISIT_ABORT
0x8000 中止迭代。忽略所有其他位。 堆引用枚举( jvmtiHeapReferenceKind
)常量 值 描述 JVMTI_HEAP_REFERENCE_CLASS
1 从对象到其类的引用。 JVMTI_HEAP_REFERENCE_FIELD
2 从对象到其实例字段值的引用。 JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT
3 从数组到其元素的引用。 JVMTI_HEAP_REFERENCE_CLASS_LOADER
4 从类到其类加载器的引用。 JVMTI_HEAP_REFERENCE_SIGNERS
5 从类到其签名者数组的引用。 JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN
6 从类到其保护域的引用。 JVMTI_HEAP_REFERENCE_INTERFACE
7 从类到其接口之一的引用。注意:接口是通过常量池引用定义的,因此引用的接口也可能使用 JVMTI_HEAP_REFERENCE_CONSTANT_POOL
引用类型报告。JVMTI_HEAP_REFERENCE_STATIC_FIELD
8 从类到其静态字段值的引用。 JVMTI_HEAP_REFERENCE_CONSTANT_POOL
9 从类到常量池中的一个已解析条目的引用。 JVMTI_HEAP_REFERENCE_SUPERCLASS
10 从类到其超类的引用。如果超类是 java.lang.Object
,则不发送回调。注意:加载的类通过常量池引用定义超类,因此引用的超类也可能使用JVMTI_HEAP_REFERENCE_CONSTANT_POOL
引用类型报告。JVMTI_HEAP_REFERENCE_JNI_GLOBAL
21 堆根引用:JNI 全局引用。 JVMTI_HEAP_REFERENCE_SYSTEM_CLASS
22 堆根引用:系统类。 JVMTI_HEAP_REFERENCE_MONITOR
23 堆根引用:监视器。 JVMTI_HEAP_REFERENCE_STACK_LOCAL
24 线程堆栈上的局部变量。 JVMTI_HEAP_REFERENCE_JNI_LOCAL
25 JNI 本地引用。 JVMTI_HEAP_REFERENCE_THREAD
26 堆根引用:线程。 JVMTI_HEAP_REFERENCE_OTHER
27 堆根引用:其他堆根引用。 原始类型枚举( jvmtiPrimitiveType
)常量 值 描述 JVMTI_PRIMITIVE_TYPE_BOOLEAN
90 'Z' - Java 编程语言 boolean
- JNIjboolean
JVMTI_PRIMITIVE_TYPE_BYTE
66 'B' - Java 编程语言 byte
- JNIjbyte
JVMTI_PRIMITIVE_TYPE_CHAR
67 'C' - Java 编程语言 char
- JNIjchar
JVMTI_PRIMITIVE_TYPE_SHORT
83 'S' - Java 编程语言 short
- JNIjshort
JVMTI_PRIMITIVE_TYPE_INT
73 'I' - Java 编程语言 int
- JNIjint
JVMTI_PRIMITIVE_TYPE_LONG
74 'J' - Java 编程语言 long
- JNIjlong
JVMTI_PRIMITIVE_TYPE_FLOAT
70 'F' - Java 编程语言 float
- JNIjfloat
JVMTI_PRIMITIVE_TYPE_DOUBLE
68 'D' - Java 编程语言 double
- JNIjdouble
字段引用的引用信息结构
为字段引用返回的引用信息JVMTI_HEAP_REFERENCE_FIELD
和JVMTI_HEAP_REFERENCE_STATIC_FIELD
引用。typedef struct { jint index; } jvmtiHeapReferenceInfoField;
jvmtiHeapReferenceInfoField
- 字段引用信息结构字段 类型 描述 index
jint
对于 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
- 数组引用信息结构字段 类型 描述 index
jint
数组索引。 常量池引用信息结构
返回JVMTI_HEAP_REFERENCE_CONSTANT_POOL
引用的引用信息。typedef struct { jint index; } jvmtiHeapReferenceInfoConstantPool;
jvmtiHeapReferenceInfoConstantPool
- 常量池引用信息结构字段 类型 描述 index
jint
类的常量池中的索引。请参阅Java™虚拟机规范,第4.4章中的描述。 本地变量引用信息结构
返回JVMTI_HEAP_REFERENCE_STACK_LOCAL
引用的引用信息。typedef struct { jlong thread_tag; jlong thread_id; jint depth; jmethodID method; jlocation location; jint slot; } jvmtiHeapReferenceInfoStackLocal;
jvmtiHeapReferenceInfoStackLocal
- 本地变量引用信息结构字段 类型 描述 thread_tag
jlong
与此堆栈对应的线程标记,如果未标记则为零。 thread_id
jlong
与此堆栈对应的线程的唯一线程ID。 depth
jint
帧的深度。 method
jmethodID
在此帧中执行的方法。 location
jlocation
此帧中当前执行的位置。 slot
jint
本地变量的槽号。 JNI本地引用信息结构
返回JVMTI_HEAP_REFERENCE_JNI_LOCAL
引用的引用信息。typedef struct { jlong thread_tag; jlong thread_id; jint depth; jmethodID method; } jvmtiHeapReferenceInfoJniLocal;
jvmtiHeapReferenceInfoJniLocal
- JNI本地引用的引用信息结构字段 类型 描述 thread_tag
jlong
与此堆栈对应的线程标记,如果未标记则为零。 thread_id
jlong
与此堆栈对应的线程的唯一线程ID。 depth
jint
帧的深度。 method
jmethodID
在此帧中执行的方法。 其他引用的引用信息结构
其他引用返回的引用信息。typedef struct { jlong reserved1; jlong reserved2; jlong reserved3; jlong reserved4; jlong reserved5; jlong reserved6; jlong reserved7; jlong reserved8; } jvmtiHeapReferenceInfoReserved;
jvmtiHeapReferenceInfoReserved
- 其他引用的引用信息结构字段 类型 描述 reserved1
jlong
保留以供将来使用。 reserved2
jlong
保留以供将来使用。 reserved3
jlong
保留以供将来使用。 reserved4
jlong
保留以供将来使用。 reserved5
jlong
保留以供将来使用。 reserved6
jlong
保留以供将来使用。 reserved7
jlong
保留以供将来使用。 reserved8
jlong
保留以供将来使用。 引用信息结构
有关引用者返回的信息。表示各种引用信息的联合。typedef union { jvmtiHeapReferenceInfoField field; jvmtiHeapReferenceInfoArray array; jvmtiHeapReferenceInfoConstantPool constant_pool; jvmtiHeapReferenceInfoStackLocal stack_local; jvmtiHeapReferenceInfoJniLocal jni_local; jvmtiHeapReferenceInfoReserved other; } jvmtiHeapReferenceInfo;
jvmtiHeapReferenceInfo
- 引用信息结构字段 类型 描述 field
jvmtiHeapReferenceInfoField
JVMTI_HEAP_REFERENCE_FIELD
和JVMTI_HEAP_REFERENCE_STATIC_FIELD
引用的引用者信息。array
jvmtiHeapReferenceInfoArray
JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT
引用的引用者信息。constant_pool
jvmtiHeapReferenceInfoConstantPool
JVMTI_HEAP_REFERENCE_CONSTANT_POOL
引用的引用者信息。stack_local
jvmtiHeapReferenceInfoStackLocal
JVMTI_HEAP_REFERENCE_STACK_LOCAL
引用的引用者信息。jni_local
jvmtiHeapReferenceInfoJniLocal
JVMTI_HEAP_REFERENCE_JNI_LOCAL
引用的引用者信息。other
jvmtiHeapReferenceInfoReserved
保留以供将来使用。 堆回调函数结构
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_callback
jvmtiHeapIterationCallback
用于描述堆中对象的回调。被 IterateThroughHeap
函数调用,被FollowReferences
函数忽略。heap_reference_callback
jvmtiHeapReferenceCallback
用于描述对象引用的回调。被 FollowReferences
函数调用,被IterateThroughHeap
函数忽略。primitive_field_callback
jvmtiPrimitiveFieldCallback
用于描述原始字段的回调。 array_primitive_value_callback
jvmtiArrayPrimitiveValueCallback
用于描述原始值数组的回调。 string_primitive_value_callback
jvmtiStringPrimitiveValueCallback
用于描述字符串值的回调。 reserved5
jvmtiReservedCallback
保留以供将来使用。 reserved6
jvmtiReservedCallback
保留以供将来使用。 reserved7
jvmtiReservedCallback
保留以供将来使用。 reserved8
jvmtiReservedCallback
保留以供将来使用。 reserved9
jvmtiReservedCallback
保留以供将来使用。 reserved10
jvmtiReservedCallback
保留以供将来使用。 reserved11
jvmtiReservedCallback
保留以供将来使用。 reserved12
jvmtiReservedCallback
保留以供将来使用。 reserved13
jvmtiReservedCallback
保留以供将来使用。 reserved14
jvmtiReservedCallback
保留以供将来使用。 reserved15
jvmtiReservedCallback
保留以供将来使用。 理由:堆转储功能(下文)使用每个对象的回调。虽然似乎缓冲区方法会提供更好的吞吐量,但测试结果并未显示这种情况——可能是由于内存引用的局部性或数组访问开销。
堆迭代回调
typedef jint (JNICALL *jvmtiHeapIterationCallback) (jlong class_tag, jlong size, jlong* tag_ptr, jint length, void* user_data);
JVMTI_VISIT_OBJECTS
标志被忽略)。 请参阅堆回调函数限制。class_tag
是与java.lang.Class
关联的标记(如果java.lang.Class
未标记则为零)。参数 名称 类型 描述 class_tag
jlong
size
jlong
对象的大小(以字节为单位)。参见 GetObjectSize
。tag_ptr
jlong*
对象标记值,如果对象未标记则为零。要将与对象关联的标记值设置为代理设置的 jlong
指向的值。length
jint
如果此对象是数组,则为数组的长度。否则为负一(-1)。 user_data
void*
传入迭代函数的用户提供的数据。
堆引用回调
typedef jint (JNICALL *jvmtiHeapReferenceCallback) (jvmtiHeapReferenceKind reference_kind, const jvmtiHeapReferenceInfo* reference_info, jlong class_tag, jlong referrer_class_tag, jlong size, jlong* tag_ptr, jlong* referrer_tag_ptr, jint length, void* user_data);
参数 名称 类型 描述 reference_kind
jvmtiHeapReferenceKind
引用的类型。 reference_info
const 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_tag
jlong
被引用对象的类标记(如果类未标记则为零)。如果被引用对象表示运行时类,则 class_tag
是与java.lang.Class
关联的标记(如果java.lang.Class
未标记则为零)。referrer_class_tag
jlong
引用者对象的类标记(如果类未标记或被引用对象是堆根则为零)。如果引用者对象表示运行时类,则 referrer_class_tag
是与java.lang.Class
关联的标记(如果java.lang.Class
未标记则为零)。size
jlong
被引用对象的大小(以字节为单位)。参见 GetObjectSize
。tag_ptr
jlong*
指向被引用对象标记值的指针,如果对象未标记则为零。要将与对象关联的标记值设置为代理设置的参数指向的 jlong
。referrer_tag_ptr
jlong*
指向引用者对象的标记的指针,如果引用者对象未标记则指向零。如果引用者不是对象(即,此回调报告堆根),则为 NULL
。要将与引用者对象关联的标记值设置为代理设置的参数指向的jlong
。如果此回调报告对象自身的引用,则referrer_tag_ptr == tag_ptr
。length
jint
如果此对象是数组,则为数组的长度。否则为负一(-1)。 user_data
void*
传递给迭代函数的用户提供的数据。
原始字段回调
typedef jint (JNICALL *jvmtiPrimitiveFieldCallback) (jvmtiHeapReferenceKind kind, const jvmtiHeapReferenceInfo* info, jlong object_class_tag, jlong* object_tag_ptr, jvalue value, jvmtiPrimitiveType value_type, void* user_data);
JVMTI_VISIT_OBJECTS
标志将被忽略)。 请参阅堆回调函数限制。参数 名称 类型 描述 kind
jvmtiHeapReferenceKind
字段的类型 -- 实例或静态( JVMTI_HEAP_REFERENCE_FIELD
或JVMTI_HEAP_REFERENCE_STATIC_FIELD
)。info
const jvmtiHeapReferenceInfo *
哪个字段(字段索引)。 object_class_tag
jlong
对象的类的标记(如果类未标记则为零)。如果对象表示运行时类,则 object_class_tag
是与java.lang.Class
关联的标记(如果java.lang.Class
未标记则为零)。object_tag_ptr
jlong*
指向对象标记的指针,如果对象未标记则为零。要将与对象关联的标记值设置为代理设置的参数指向的 jlong
。value
jvalue
字段的值。 value_type
jvmtiPrimitiveType
字段的类型。 user_data
void*
传递给迭代函数的用户提供的数据。
数组原始值回调
typedef jint (JNICALL *jvmtiArrayPrimitiveValueCallback) (jlong class_tag, jlong size, jlong* tag_ptr, jint element_count, jvmtiPrimitiveType element_type, const void* elements, void* user_data);
JVMTI_VISIT_OBJECTS
标志将被忽略)。 请参阅堆回调函数限制。参数 名称 类型 描述 class_tag
jlong
数组对象的类标记(如果类未标记则为零)。 size
jlong
数组的大小(以字节为单位)。参见 GetObjectSize
。tag_ptr
jlong*
指向数组对象标记的指针,如果对象未标记则为零。要将与对象关联的标记值设置为代理设置的参数指向的 jlong
。element_count
jint
原始数组的长度。 element_type
jvmtiPrimitiveType
数组元素的类型。 elements
const void*
数组中元素的打包数组,每个元素为 element_type
大小的element_count
项。user_data
void*
传递给迭代函数的用户提供的数据。
字符串原始值回调
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_tag
jlong
String类的类标记(如果类未标记,则为零)。 size
jlong
字符串的大小(以字节为单位)。请参阅 GetObjectSize
。tag_ptr
jlong*
指向String对象的标记,如果对象未标记则为零。要设置与对象关联的标记值,代理设置参数指向的 jlong
。value
const jchar*
String的值,编码为Unicode字符串。 value_length
jint
字符串的长度。长度等于字符串中的16位Unicode字符数。 user_data
void*
传递给迭代函数的用户提供的数据。
保留供将来使用的回调函数
typedef jint (JNICALL *jvmtiReservedCallback) ();
跟踪引用
jvmtiError FollowReferences(jvmtiEnv* env, jint heap_filter, jclass klass, jobject initial_object, const jvmtiHeapCallbacks* callbacks, const void* user_data)
initial_object
,则遍历从堆根可达的所有对象。堆根是系统类集、JNI全局变量、来自平台线程堆栈的引用以及其他用作垃圾回收根的对象集合。 此函数通过遍历引用图来操作。当从A到B的引用被遍历时,当从堆根到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
设置为字节类的数组,则只会报告字节数组。下表总结了这一点:控制访问的对象 控制报告的对象 控制报告的原始值 由 jvmtiHeapReferenceCallback
返回的堆访问控制标志是 是,因为访问受控制 是,因为访问受控制 在 callbacks
中设置的array_primitive_value_callback
否 是 否 heap_filter
否 是 是 klass
否 是 是 功能 效果 can_tag_objects
可以设置和获取标记,如堆类别中所述。 参数 名称 类型 描述 heap_filter
jint
这是一个位向量,用于限制调用回调函数的对象。这适用于对象和基本类型的回调。 klass
jclass
仅在对象是此类的实例时报告回调。属于 klass
子类的对象不会被报告。如果klass
是一个接口,则不会报告任何对象。这适用于对象和基本类型的回调。 如果klass
是NULL
,则回调不会限制到特定类的实例。initial_object
jobject
要跟踪的对象 如果 initial_object
是NULL
,则从堆根引用开始跟踪。callbacks
const jvmtiHeapCallbacks *
定义回调函数集的结构。 代理传递一个指向 jvmtiHeapCallbacks
的指针。user_data
const void *
用户提供的数据将传递给回调函数。 代理传递一个指针。如果 user_data
是NULL
,则将NULL
作为用户提供的数据传递。错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备 can_tag_objects
能力。使用AddCapabilities
。JVMTI_ERROR_INVALID_CLASS
klass
不是一个有效的类。JVMTI_ERROR_INVALID_OBJECT
initial_object
不是一个有效的对象。JVMTI_ERROR_NULL_POINTER
callbacks
是NULL
。
遍历堆
jvmtiError IterateThroughHeap(jvmtiEnv* env, jint heap_filter, jclass klass, const jvmtiHeapCallbacks* callbacks, const void* user_data)
jvmtiHeapIterationCallback
。对象之间的引用不会被报告。如果只需要可达对象,或者需要对象引用信息,请使用FollowReferences
。 此函数还可用于检查基本(非对象)值。数组或字符串的基本值在访问对象后报告;通过调用代理提供的回调函数报告jvmtiArrayPrimitiveValueCallback
或jvmtiStringPrimitiveValueCallback
。字段的基本值在访问具有该字段的对象后报告;通过调用代理提供的回调函数报告jvmtiPrimitiveFieldCallback
。 除非回调由回调返回的堆访问控制标志中止,否则将访问堆中的所有对象。提供回调或为NULL
仅确定是否调用回调函数,不影响访问哪些对象,也不影响是否调用其他回调函数。提供给此函数的堆过滤器标志和klass
不控制访问哪些对象,但它们控制回调函数报告的对象和基本值。例如,如果设置的唯一回调是array_primitive_value_callback
,并且klass
设置为字节数组类,则只会报告字节数组。下表总结了这一点(与FollowReferences
对比):控制访问的对象 控制报告的对象 控制报告的基本值 由 jvmtiHeapIterationCallback
返回的堆访问控制标志否
(除非它们中止迭代)否
(除非它们中止迭代)否
(除非它们中止迭代)array_primitive_value_callback
在callbacks
中设置否 是 否 heap_filter
否 是 是 klass
否 是 是 能力 效果 can_tag_objects
可以设置和获取标签,如堆类别中描述的。 参数 名称 类型 描述 heap_filter
jint
这是一个位向量,用于限制调用回调函数的对象。这适用于对象和基本类型的回调。 klass
jclass
仅在对象是此类的实例时报告回调。属于 klass
子类的对象不会被报告。如果klass
是一个接口,则不会报告任何对象。这适用于对象和基本类型的回调。 如果klass
是NULL
,则回调不会限制到特定类的实例。callbacks
const jvmtiHeapCallbacks *
定义回调函数集的结构。 代理传递一个指向 jvmtiHeapCallbacks
的指针。user_data
const void *
用户提供的数据将传递给回调函数。 代理传递一个指针。如果 user_data
是NULL
,则将NULL
作为用户提供的数据传递。错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_tag_objects
。请使用AddCapabilities
。JVMTI_ERROR_INVALID_CLASS
klass
不是有效的类。JVMTI_ERROR_NULL_POINTER
callbacks
为NULL
。
获取标签
jvmtiError GetTag(jvmtiEnv* env, jobject object, jlong* tag_ptr)
SetTag
设置的。未设置标签的对象返回零值。能力 效果 can_tag_objects
可以设置和获取标签,如Heap类别中所述。 参数 名称 类型 描述 object
jobject
要检索其标签的对象。 tag_ptr
jlong*
返回时,引用的长整型设置为标签的值。 代理传递一个指向 jlong
的指针。返回时,jlong
已设置。错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_tag_objects
。请使用AddCapabilities
。JVMTI_ERROR_INVALID_OBJECT
object
不是对象。JVMTI_ERROR_NULL_POINTER
tag_ptr
为NULL
。
设置标签
jvmtiError SetTag(jvmtiEnv* env, jobject object, jlong tag)
GetTag
查看。能力 效果 can_tag_objects
可以设置和获取标签,如Heap类别中所述。 参数 名称 类型 描述 object
jobject
要设置其标签的对象。 tag
jlong
标签的新值。 错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_tag_objects
。请使用AddCapabilities
。JVMTI_ERROR_INVALID_OBJECT
object
不是对象。
获取带有标签的对象
jvmtiError GetObjectsWithTags(jvmtiEnv* env, jint tag_count, const jlong* tags, jint* count_ptr, jobject** object_result_ptr, jlong** tag_result_ptr)
能力 效果 can_tag_objects
可以设置和获取标签,如Heap类别中所述。 参数 名称 类型 描述 tag_count
jint
要扫描的标签数量。 tags
const jlong *
扫描具有这些标签的对象。在此数组中不允许为零。 代理传入一个包含 tag_count
个元素的jlong
数组。count_ptr
jint *
返回具有 tags
中任意标签的对象数量。 代理传入一个指向jint
的指针。返回时,jint
已被设置。object_result_ptr
jobject **
返回具有 tags
中任意标签的对象数组。 代理传入一个指向jobject*
的指针。返回时,jobject*
指向一个新分配的大小为*count_ptr
的数组。该数组应使用Deallocate
进行释放。如果object_result_ptr
为NULL
,则不返回此信息。由object_result_ptr
返回的对象是 JNI 本地引用,必须进行 管理。tag_result_ptr
jlong **
对于 object_result_ptr
中的每个对象,返回相应索引处的标签。 代理传入一个指向jlong*
的指针。返回时,jlong*
指向一个新分配的大小为*count_ptr
的数组。该数组应使用Deallocate
进行释放。如果tag_result_ptr
为NULL
,则不返回此信息。错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备 can_tag_objects
能力。请使用AddCapabilities
。JVMTI_ERROR_ILLEGAL_ARGUMENT
tags
中存在零。JVMTI_ERROR_ILLEGAL_ARGUMENT
tag_count
小于0
。JVMTI_ERROR_NULL_POINTER
tags
为NULL
。JVMTI_ERROR_NULL_POINTER
count_ptr
为NULL
。
强制垃圾回收
jvmtiError ForceGarbageCollection(jvmtiEnv* env)
ObjectFree
事件都已发送。特别是,对象可能因等待 finalization 而无法释放。
堆(1.0)
堆(1.0)函数: 堆(1.0)函数类型: 堆(1.0)类型:jvmtiHeapObjectFilter
- 堆对象过滤器枚举jvmtiHeapRootKind
- 堆根种类枚举jvmtiObjectReferenceKind
- 对象引用枚举jvmtiIterationControl
- 迭代控制枚举
- 允许访问原始值(字符串、数组和基本字段的值)
- 允许设置引用者的标签,从而实现更高效的局部引用图构建
- 提供更广泛的过滤能力
- 是可扩展的,允许它们的功能在未来的 JVM TI 版本中增强
堆对象过滤器枚举( jvmtiHeapObjectFilter
)常量 值 描述 JVMTI_HEAP_OBJECT_TAGGED
1 仅标记的对象。 JVMTI_HEAP_OBJECT_UNTAGGED
2 仅未标记的对象。 JVMTI_HEAP_OBJECT_EITHER
3 标记或未标记的对象。 堆根种类枚举( jvmtiHeapRootKind
)常量 值 描述 JVMTI_HEAP_ROOT_JNI_GLOBAL
1 JNI 全局引用。 JVMTI_HEAP_ROOT_SYSTEM_CLASS
2 系统类。 JVMTI_HEAP_ROOT_MONITOR
3 监视器。 JVMTI_HEAP_ROOT_STACK_LOCAL
4 堆栈本地。 JVMTI_HEAP_ROOT_JNI_LOCAL
5 JNI 本地引用。 JVMTI_HEAP_ROOT_THREAD
6 线程。 JVMTI_HEAP_ROOT_OTHER
7 其他。 对象引用枚举( jvmtiObjectReferenceKind
)常量 值 描述 JVMTI_REFERENCE_CLASS
1 从对象到其类的引用。 JVMTI_REFERENCE_FIELD
2 从对象到其实例字段值的引用。对于这种引用, referrer_index
参数传递给jvmtiObjectReferenceCallback是实例字段的索引。该索引基于对象所有字段的顺序。这包括类中直接声明的静态和实例字段的所有字段,并包括在超类和超接口中声明的所有字段(公共和私有字段)。因此,索引是通过将字段在直接声明类中的索引(参见GetClassFields
)与在所有超类和超接口中声明的所有字段(公共和私有字段)的总数相加来计算的。索引从零开始。JVMTI_REFERENCE_ARRAY_ELEMENT
3 从数组到其元素的引用。对于这种引用, referrer_index
参数传递给jvmtiObjectReferenceCallback是数组索引。JVMTI_REFERENCE_CLASS_LOADER
4 从类到其类加载器的引用。 JVMTI_REFERENCE_SIGNERS
5 从类到其签名者数组的引用。 JVMTI_REFERENCE_PROTECTION_DOMAIN
6 从类到其保护域的引用。 JVMTI_REFERENCE_INTERFACE
7 从类到其接口之一的引用。 JVMTI_REFERENCE_STATIC_FIELD
8 从类到其静态字段值的引用。对于这种引用, referrer_index
参数传递给jvmtiObjectReferenceCallback是静态字段的索引。该索引基于对象所有字段的顺序。这包括类中直接声明的静态和实例字段的所有字段,并包括在超类和超接口中声明的所有字段(公共和私有字段)。因此,索引是通过将字段在直接声明类中的索引(参见GetClassFields
)与在所有超类和超接口中声明的所有字段(公共和私有字段)的总数相加来计算的。索引从零开始。注意:此定义与JVM 1.0规范中的定义不同。理由:没有已知的实现使用了1.0定义。
JVMTI_REFERENCE_CONSTANT_POOL
9 从类到常量池中的已解析条目的引用。对于这种引用, referrer_index
参数传递给jvmtiObjectReferenceCallback是类的常量池表中的索引,从1开始。参见《Java™虚拟机规范,第4.4章》。迭代控制枚举( jvmtiIterationControl
)常量 值 描述 JVMTI_ITERATION_CONTINUE
1 继续迭代。如果这是引用迭代,则跟随此对象的引用。 JVMTI_ITERATION_IGNORE
2 继续迭代。如果这是引用迭代,则忽略此对象的引用。 JVMTI_ITERATION_ABORT
0 中止迭代。
堆对象回调
typedef jvmtiIterationControl (JNICALL *jvmtiHeapObjectCallback) (jlong class_tag, jlong size, jlong* tag_ptr, void* user_data);
JVMTI_ITERATION_CONTINUE
以继续迭代,或JVMTI_ITERATION_ABORT
以停止迭代。 请参阅堆回调函数限制。参数 名称 类型 描述 class_tag
jlong
对象的类标记(如果类未标记,则为零)。如果对象表示运行时类,则 class_tag
是与java.lang.Class
关联的标记(如果java.lang.Class
未标记,则为零)。size
jlong
对象的大小(以字节为单位)。参见 GetObjectSize
。tag_ptr
jlong*
对象标记值,如果对象未标记则为零。要将标记值设置为与对象关联的值,代理设置参数指向的 jlong
。user_data
void*
传递给迭代函数的用户提供的数据。
堆根对象回调
typedef jvmtiIterationControl (JNICALL *jvmtiHeapRootCallback) (jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong* tag_ptr, void* user_data);
JVMTI_ITERATION_CONTINUE
以继续迭代,JVMTI_ITERATION_IGNORE
以继续迭代而不追踪被引用对象的引用,或JVMTI_ITERATION_ABORT
以停止迭代。 请参阅堆回调函数限制。参数 名称 类型 描述 root_kind
jvmtiHeapRootKind
堆根的类型。 class_tag
jlong
对象的类标记(如果类未标记,则为零)。如果对象表示运行时类,则 class_tag
是与java.lang.Class
关联的标记(如果java.lang.Class
未标记,则为零)。size
jlong
对象的大小(以字节为单位)。参见 GetObjectSize
。tag_ptr
jlong*
对象标记值,如果对象未标记则为零。要将标记值设置为与对象关联的值,代理设置参数指向的 jlong
。user_data
void*
传递给迭代函数的用户提供的数据。
堆栈引用对象回调
typedef jvmtiIterationControl (JNICALL *jvmtiStackReferenceCallback) (jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong* tag_ptr, jlong thread_tag, jint depth, jmethodID method, jint slot, void* user_data);
JVMTI_ITERATION_CONTINUE
以继续迭代,JVMTI_ITERATION_IGNORE
以继续迭代而不追踪被引用对象的引用,或JVMTI_ITERATION_ABORT
以停止迭代。 请参阅堆回调函数限制。JVMTI_HEAP_ROOT_STACK_LOCAL
或JVMTI_HEAP_ROOT_JNI_LOCAL
)。class_tag
是与java.lang.Class
关联的标记(如果java.lang.Class
未标记则为零)。GetObjectSize
。jlong
。参数 名称 类型 描述 root_kind
jvmtiHeapRootKind
class_tag
jlong
size
jlong
tag_ptr
jlong*
thread_tag
jlong
depth
jint
method
jmethodID
slot
jint
user_data
void*
对象引用回调
typedef jvmtiIterationControl (JNICALL *jvmtiObjectReferenceCallback) (jvmtiObjectReferenceKind reference_kind, jlong class_tag, jlong size, jlong* tag_ptr, jlong referrer_tag, jint referrer_index, void* user_data);
JVMTI_ITERATION_CONTINUE
以继续迭代,JVMTI_ITERATION_IGNORE
以继续迭代而不追踪被引用对象的引用,或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_kind
jvmtiObjectReferenceKind
class_tag
jlong
size
jlong
tag_ptr
jlong*
referrer_tag
jlong
referrer_index
jint
user_data
void*
迭代从对象可达的对象
jvmtiError IterateOverObjectsReachableFromObject(jvmtiEnv* env, jobject object, jvmtiObjectReferenceCallback object_reference_callback, const void* user_data)
jvmtiObjectReferenceCallback.reference_kind
和jvmtiObjectReferenceCallback.referrer_index
进行区分。对象的回调将始终在其引用者的回调之后发生。 请参阅FollowReferences
以获取报告的对象引用。 在执行此函数期间,堆的状态不会更改:不会分配对象,不会进行垃圾回收,并且对象的状态(包括持有的值)不会更改。因此,执行Java编程语言代码的线程,尝试恢复Java编程语言代码的线程以及尝试执行JNI函数的线程通常会被阻塞。功能 效果 can_tag_objects
可以设置和获取标记,如堆类别中所述。 参数 名称 类型 描述 object
jobject
对象 object_reference_callback
jvmtiObjectReferenceCallback
用于描述每个对象引用的回调函数。 user_data
const void *
用户提供的数据,将传递给回调函数。 代理传入一个指针。如果 user_data
为NULL
,则将NULL
作为用户提供的数据传递。错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备 can_tag_objects
的能力。使用AddCapabilities
。JVMTI_ERROR_INVALID_OBJECT
object
不是一个对象。JVMTI_ERROR_NULL_POINTER
object_reference_callback
为NULL
。
遍历可达对象
jvmtiError IterateOverReachableObjects(jvmtiEnv* env, jvmtiHeapRootCallback heap_root_callback, jvmtiStackReferenceCallback stack_ref_callback, jvmtiObjectReferenceCallback object_ref_callback, const void* user_data)
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函数的线程通常会被阻塞。能力 效果 can_tag_objects
可以设置和获取标签,如 Heap
类别中所述。参数 名称 类型 描述 heap_root_callback
jvmtiHeapRootCallback
用于每个堆根的回调函数,类型为 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_callback
jvmtiStackReferenceCallback
用于每个 JVMTI_HEAP_ROOT_STACK_LOCAL
或JVMTI_HEAP_ROOT_JNI_LOCAL
堆根的回调函数。 如果stack_ref_callback
为NULL
,则不报告堆根引用。object_ref_callback
jvmtiObjectReferenceCallback
用于每个对象引用的回调函数。 如果 object_ref_callback
为NULL
,则不跟踪从根对象的引用。user_data
const 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函数的线程通常会被阻塞。能力 效果 can_tag_objects
可以设置和获取标签,如在Heap类别中描述的。 参数 名称 类型 描述 klass
jclass
仅迭代此类的对象。 object_filter
jvmtiHeapObjectFilter
指示调用回调函数的对象。 heap_object_callback
jvmtiHeapObjectCallback
要为每个与 object_filter
匹配的klass
实例调用的迭代器函数。user_data
const void *
要传递给回调的用户提供的数据。 代理传入一个指针。如果 user_data
为NULL
,则将NULL
作为用户提供的数据传递。错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备 can_tag_objects
能力。使用AddCapabilities
。JVMTI_ERROR_INVALID_CLASS
klass
不是类对象或类已被卸载。JVMTI_ERROR_ILLEGAL_ARGUMENT
object_filter
不是jvmtiHeapObjectFilter。JVMTI_ERROR_NULL_POINTER
heap_object_callback
为NULL
。
本地变量
本地变量函数:- 获取本地变量 - 对象
- 获取本地实例
- 获取本地变量 - 整数
- 获取本地变量 - 长整数
- 获取本地变量 - 浮点数
- 获取本地变量 - 双精度浮点数
- 设置本地变量 - 对象
- 设置本地变量 - 整数
- 设置本地变量 - 长整数
- 设置本地变量 - 浮点数
- 设置本地变量 - 双精度浮点数
GetLocalVariableTable
获得。GetLocalXXX
函数可用于检索虚拟线程帧中包含的本地变量的值。SetLocalXXX
函数可用于在暂停在事件的虚拟线程的顶层帧中设置本地变量的值。实现可能支持在其他情况下设置本地变量。
获取本地变量 - 对象
jvmtiError GetLocalObject(jvmtiEnv* env, jthread thread, jint depth, jint slot, jobject* value_ptr)
Object
或Object子类的本地变量的值。 指定的线程必须被挂起或必须是当前线程。
SetNativeMethodPrefix与使用能力 效果 can_access_local_variables
可以设置和获取本地变量 参数 名称 类型 描述 thread
jthread
包含变量值的帧的线程。如果 thread
为NULL
,则使用当前线程。depth
jint
包含变量值的帧的深度。 slot
jint
变量的槽号。 value_ptr
jobject*
返回时,指向变量的值。 代理传递一个指向 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_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(尚未启动或已终止)。JVMTI_ERROR_ILLEGAL_ARGUMENT
depth
小于零。JVMTI_ERROR_NO_MORE_FRAMES
指定深度处没有堆栈帧。 JVMTI_ERROR_NULL_POINTER
value_ptr
为NULL
。
获取本地实例
jvmtiError GetLocalInstance(jvmtiEnv* env, jthread thread, jint depth, jobject* value_ptr)
this
”对象)的本地对象变量的值。此函数可以从本地方法帧中检索“this
”对象,而GetLocalObject()
在这些情况下会返回JVMTI_ERROR_OPAQUE_FRAME
。 指定的线程必须被挂起或必须是当前线程。能力 效果 can_access_local_variables
可以设置和获取本地变量 参数 名称 类型 描述 thread
jthread
包含变量值的帧的线程。如果 thread
为NULL
,则使用当前线程。depth
jint
包含变量值的帧的深度。 value_ptr
jobject*
返回时,指向变量的值。 代理传递一个指向 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_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(尚未启动或已终止)。JVMTI_ERROR_ILLEGAL_ARGUMENT
depth
小于零。JVMTI_ERROR_NO_MORE_FRAMES
指定深度处没有堆栈帧。 JVMTI_ERROR_NULL_POINTER
value_ptr
为NULL
。
获取本地变量 - Int
jvmtiError GetLocalInt(jvmtiEnv* env, jthread thread, jint depth, jint slot, jint* value_ptr)
int
,short
,char
,字节
,或布尔
。 指定的线程必须被挂起或必须是当前线程。能力 效果 can_access_local_variables
可以设置和获取局部变量 参数 名称 类型 描述 线程
jthread
包含变量值的帧的线程。如果 线程
为NULL
,则使用当前线程。深度
jint
包含变量值的帧的深度。 槽
jint
变量的槽号。 value_ptr
jint*
返回时,指向变量的值。 代理传递一个指向 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_POINTER
value_ptr
为NULL
。
获取局部变量 - 长整型
jvmtiError GetLocalLong(jvmtiEnv* env, jthread thread, jint depth, jint slot, jlong* value_ptr)
long
的局部变量的值。 指定的线程必须被挂起或必须是当前线程。能力 效果 can_access_local_variables
可以设置和获取局部变量 参数 名称 类型 描述 线程
jthread
包含变量值的帧的线程。如果 线程
为NULL
,则使用当前线程。深度
jint
包含变量值的帧的深度。 槽
jint
变量的槽号。 value_ptr
jlong*
返回时,指向变量的值。 代理传递一个指向 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_POINTER
value_ptr
为NULL
。能力 效果 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_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(未启动或已终止)。JVMTI_ERROR_ILLEGAL_ARGUMENT
depth
小于零。JVMTI_ERROR_NO_MORE_FRAMES
指定深度处没有堆栈帧。 JVMTI_ERROR_NULL_POINTER
value_ptr
为NULL
。
获取本地变量 - 双精度
jvmtiError GetLocalDouble(jvmtiEnv* env, jthread thread, jint depth, jint slot, jdouble* value_ptr)
long
的本地变量的值。 指定的线程必须已暂停或必须是当前线程。能力 效果 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_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(未启动或已终止)。JVMTI_ERROR_ILLEGAL_ARGUMENT
depth
小于零。JVMTI_ERROR_NO_MORE_FRAMES
指定深度处没有堆栈帧。 JVMTI_ERROR_NULL_POINTER
value_ptr
为NULL
。
设置本地变量 - 对象
jvmtiError SetLocalObject(jvmtiEnv* env, jthread thread, jint depth, jint slot, jobject value)
Object
或Object
子类的本地变量的值。 指定的线程必须已暂停或必须是当前线程。能力 效果 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_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
未启动或已终止。JVMTI_ERROR_ILLEGAL_ARGUMENT
depth
小于零。JVMTI_ERROR_NO_MORE_FRAMES
指定深度处没有堆栈帧。 JVMTI_ERROR_INVALID_OBJECT
value
不是对象。
设置本地变量 - 整数
jvmtiError SetLocalInt(jvmtiEnv* env, jthread thread, jint depth, jint slot, jint value)
int
、short
、char
、byte
或boolean
的本地变量的值。 指定的线程必须被挂起或必须是当前线程。能力 效果 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_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
未启动或已终止。JVMTI_ERROR_ILLEGAL_ARGUMENT
depth
小于零。JVMTI_ERROR_NO_MORE_FRAMES
指定深度处没有堆栈帧。
设置本地变量 - 长整型
jvmtiError SetLocalLong(jvmtiEnv* env, jthread thread, jint depth, jint slot, jlong value)
long
的本地变量的值。 指定的线程必须被挂起或必须是当前线程。能力 效果 can_access_local_variables
可以设置和获取本地变量 参数 名称 类型 描述 thread
jthread
包含变量值的帧的线程。如果 thread
为NULL
,则使用当前线程。depth
jint
包含变量值的帧的深度。 slot
jint
变量的槽号。 value
jlong
变量的新值。 错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_access_local_variables
。请使用AddCapabilities
。JVMTI_ERROR_INVALID_SLOT
无效的 slot
。JVMTI_ERROR_TYPE_MISMATCH
变量类型不是 long
。JVMTI_ERROR_OPAQUE_FRAME
不是可见帧 JVMTI_ERROR_OPAQUE_FRAME
线程是挂起的虚拟线程,实现不支持在给定深度的帧中设置本地变量的值。请参阅本地变量。 JVMTI_ERROR_THREAD_NOT_SUSPENDED
线程未被挂起且不是当前线程。 JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
未启动或已终止。JVMTI_ERROR_ILLEGAL_ARGUMENT
depth
小于零。JVMTI_ERROR_NO_MORE_FRAMES
指定深度处没有堆栈帧。
设置本地变量 - 浮点数
jvmtiError SetLocalFloat(jvmtiEnv* env, jthread thread, jint depth, jint slot, jfloat value)
float
的本地变量的值。 指定的线程必须被挂起或必须是当前线程。能力 效果 can_access_local_variables
可以设置和获取本地变量 参数 名称 类型 描述 thread
jthread
包含变量值的帧的线程。如果 thread
为NULL
,则使用当前线程。depth
jint
包含变量值的帧的深度。 slot
jint
变量的槽号。 value
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_OPAQUE_FRAME
线程是挂起的虚拟线程,实现不支持在给定深度的帧中设置本地变量的值。请参阅本地变量。 JVMTI_ERROR_THREAD_NOT_SUSPENDED
线程未被挂起且不是当前线程。 JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
未启动或已终止。JVMTI_ERROR_ILLEGAL_ARGUMENT
depth
小于零。JVMTI_ERROR_NO_MORE_FRAMES
指定深度处没有堆栈帧。
设置本地变量 - 双精度浮点数
jvmtiError SetLocalDouble(jvmtiEnv* env, jthread thread, jint depth, jint slot, jdouble value)
double
的本地变量的值。 指定的线程必须被挂起或必须是当前线程。能力 效果 can_access_local_variables
可以设置和获取局部变量 参数 名称 类型 描述 thread
jthread
包含变量值的帧的线程。如果 thread
为NULL
,则使用当前线程。depth
jint
包含变量值的帧的深度。 slot
jint
变量的槽号。 value
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_OPAQUE_FRAME
线程是挂起的虚拟线程,实现不支持在给定深度的帧中设置局部变量的值。请参阅局部变量。 JVMTI_ERROR_THREAD_NOT_SUSPENDED
线程未挂起且不是当前线程。 JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(未启动或已终止)。JVMTI_ERROR_ILLEGAL_ARGUMENT
depth
小于零。JVMTI_ERROR_NO_MORE_FRAMES
指定深度处没有堆栈帧。
断点
断点函数:
设置断点
jvmtiError SetBreakpoint(jvmtiEnv* env, jmethodID method, jlocation location)
method
和location
指示的指令处设置断点。一个指令只能有一个断点。 每当指定的指令即将执行时,会生成一个断点
事件。能力 效果 can_generate_breakpoint_events
可以设置并因此获取 断点
事件参数 名称 类型 描述 method
jmethodID
要设置断点的方法 location
jlocation
要设置断点的指令的索引 错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_generate_breakpoint_events
。请使用AddCapabilities
。JVMTI_ERROR_DUPLICATE
指定的字节码已经有一个断点。 JVMTI_ERROR_INVALID_METHODID
method
不是jmethodID。JVMTI_ERROR_INVALID_LOCATION
location
不是有效位置。
清除断点
jvmtiError ClearBreakpoint(jvmtiEnv* env, jmethodID method, jlocation location)
method
和location
指示的字节码处的断点。能力 效果 can_generate_breakpoint_events
可以设置并因此获取 断点
事件参数 名称 类型 描述 method
jmethodID
要清除断点的方法 location
jlocation
要清除断点的指令索引 错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备 can_generate_breakpoint_events
能力。请使用AddCapabilities
。JVMTI_ERROR_NOT_FOUND
指定的字节码中没有断点。 JVMTI_ERROR_INVALID_METHODID
method
不是 jmethodID。JVMTI_ERROR_INVALID_LOCATION
location
不是有效的位置。
监视字段
监视字段函数:
设置字段访问监视
jvmtiError SetFieldAccessWatch(jvmtiEnv* env, jclass klass, jfieldID field)
klass
和field
指定的字段即将被访问时生成一个FieldAccess
事件。每次访问该字段时都会生成一个事件,直到使用ClearFieldAccessWatch
取消。来自Java编程语言代码或JNI代码的字段访问会被监视,通过其他方式修改的字段不会被监视。请注意,JVM TI用户应注意,他们自己的字段访问将触发监视。一个字段只能设置一个字段访问监视。字段的修改不被视为访问--使用SetFieldModificationWatch
监视修改。能力 效果 can_generate_field_access_events
可以在字段访问上设置监视点 - SetFieldAccessWatch
参数 名称 类型 描述 klass
jclass
包含要监视的字段的类 field
jfieldID
要监视的字段 错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备 can_generate_field_access_events
能力。请使用AddCapabilities
。JVMTI_ERROR_DUPLICATE
指定的字段已经被监视以进行访问。 JVMTI_ERROR_INVALID_CLASS
klass
不是类对象或类已被卸载。JVMTI_ERROR_INVALID_FIELDID
field
不是 jfieldID。
清除字段访问监视
jvmtiError ClearFieldAccessWatch(jvmtiEnv* env, jclass klass, jfieldID field)
SetFieldAccessWatch
设置的字段访问监视,针对klass
和field
指定的字段。能力 效果 can_generate_field_access_events
可以在字段访问上设置监视点 - SetFieldAccessWatch
参数 名称 类型 描述 klass
jclass
包含要监视的字段的类 field
jfieldID
要监视的字段 错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备 can_generate_field_access_events
能力。请使用AddCapabilities
。JVMTI_ERROR_NOT_FOUND
指定的字段未被监视以进行访问。 JVMTI_ERROR_INVALID_CLASS
klass
不是类对象或类已被卸载。JVMTI_ERROR_INVALID_FIELDID
field
不是 jfieldID。
设置字段修改监视
jvmtiError SetFieldModificationWatch(jvmtiEnv* env, jclass klass, jfieldID field)
klass
和field
指定的字段即将被修改时生成一个FieldModification
事件。每次修改该字段时都会生成一个事件,直到使用ClearFieldModificationWatch
。来自Java编程语言代码或JNI代码的字段修改会被监视,其他方式修改的字段不会被监视。请注意,JVM TI用户应该注意,他们自己的字段修改将触发监视。一个字段只能设置一个字段修改监视。能力 效果 can_generate_field_modification_events
可以在字段修改上设置监视点 - SetFieldModificationWatch
参数 名称 类型 描述 klass
jclass
包含要监视的字段的类 field
jfieldID
要监视的字段 错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_generate_field_modification_events
。使用AddCapabilities
。JVMTI_ERROR_DUPLICATE
指定的字段已经被监视以进行修改。 JVMTI_ERROR_INVALID_CLASS
klass
不是类对象或类已被卸载。JVMTI_ERROR_INVALID_FIELDID
field
不是jfieldID。
清除字段修改监视
jvmtiError ClearFieldModificationWatch(jvmtiEnv* env, jclass klass, jfieldID field)
SetFieldModificationWatch
设置的字段修改监视,取消指定的klass
和field
字段。能力 效果 can_generate_field_modification_events
可以在字段修改上设置监视点 - SetFieldModificationWatch
参数 名称 类型 描述 klass
jclass
包含要监视的字段的类 field
jfieldID
要监视的字段 错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_generate_field_modification_events
。使用AddCapabilities
。JVMTI_ERROR_NOT_FOUND
指定的字段未被监视以进行修改。 JVMTI_ERROR_INVALID_CLASS
klass
不是类对象或类已被卸载。JVMTI_ERROR_INVALID_FIELDID
field
不是jfieldID。
模块
模块函数:
获取所有模块
jvmtiError GetAllModules(jvmtiEnv* env, jint* module_count_ptr, jobject** modules_ptr)
module_count_ptr
返回,数组本身通过modules_ptr
返回。参数 名称 类型 描述 module_count_ptr
jint*
返回时,指向返回的模块数量。 代理传递一个指向 jint
的指针。返回时,jint
已被设置。modules_ptr
jobject**
返回时,指向一个引用数组,每个模块一个引用。 代理传递一个指向 jobject*
的指针。返回时,jobject*
指向一个新分配的大小为*module_count_ptr
的数组。数组应使用Deallocate
释放。由modules_ptr
返回的对象是JNI本地引用,必须管理。错误 描述 JVMTI_ERROR_NULL_POINTER
module_count_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
modules_ptr
为NULL
。
获取命名模块
jvmtiError GetNamedModule(jvmtiEnv* env, jobject class_loader, const char* package_name, jobject* module_ptr)
java.lang.Module
对象。模块通过module_ptr
返回。 如果类加载器定义了命名模块并且包含该包,则返回该命名模块,否则返回NULL
。参数 名称 类型 描述 class_loader
jobject
一个类加载器。如果 class_loader
不为NULL
或为java.lang.ClassLoader
的子类,则此函数返回JVMTI_ERROR_ILLEGAL_ARGUMENT
。 如果class_loader
为NULL
,则假定为引导加载器。package_name
const char*
包的名称,编码为修改后的UTF-8字符串。包名采用内部形式(JVMS 4.2.1);标识符用斜杠而不是句点分隔。 代理传入一个 char
数组。module_ptr
jobject*
返回时,指向一个 java.lang.Module
对象或指向NULL
。 代理传递一个指向jobject
的指针。返回时,jobject
已被设置。由module_ptr
返回的对象是JNI本地引用,必须管理。错误 描述 JVMTI_ERROR_ILLEGAL_ARGUMENT
如果类加载器不为 NULL
且不是类加载器对象。JVMTI_ERROR_NULL_POINTER
package_name
为NULL
。JVMTI_ERROR_NULL_POINTER
module_ptr
为NULL
。
添加模块读取
jvmtiError AddModuleReads(jvmtiEnv* env, jobject module, jobject to_module)
module
是一个未命名模块时,此函数无效。此函数便于在需要扩展模块读取的模块中进行代码的插装。参数 名称 类型 描述 module
jobject
要更新的模块。 to_module
jobject
要读取的额外模块。 错误 描述 JVMTI_ERROR_INVALID_MODULE
如果 module
不是模块对象。JVMTI_ERROR_INVALID_MODULE
如果 to_module
不是模块对象。JVMTI_ERROR_UNMODIFIABLE_MODULE
如果无法修改模块。请参阅 IsModifiableModule
。JVMTI_ERROR_NULL_POINTER
module
为NULL
。JVMTI_ERROR_NULL_POINTER
to_module
为NULL
。
添加模块导出
jvmtiError AddModuleExports(jvmtiEnv* env, jobject module, const char* pkg_name, jobject to_module)
module
是一个未命名模块或开放模块时,此函数无效。此函数便于在需要扩展模块导出的包集的插装代码中进行插装。参数 名称 类型 描述 module
jobject
要更新的模块。 pkg_name
const char*
导出的包名称。 代理传入一个 char
数组。to_module
jobject
要导出包的模块。如果 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_POINTER
module
为NULL
。JVMTI_ERROR_NULL_POINTER
pkg_name
为NULL
。JVMTI_ERROR_NULL_POINTER
to_module
为NULL
。
添加模块打开
jvmtiError AddModuleOpens(jvmtiEnv* env, jobject module, const char* pkg_name, jobject to_module)
module
是一个未命名模块或一个开放模块时,此函数不执行任何操作。此函数有助于在需要扩展模块打开到其他模块的包集的情况下对模块中的代码进行仪器化。代理传入一个 char
数组。to_module
不是java.lang.Module
的子类,则此函数返回JVMTI_ERROR_INVALID_MODULE
。参数 名称 类型 描述 module
jobject
pkg_name
const char*
to_module
jobject
错误 描述 JVMTI_ERROR_INVALID_MODULE
如果 module
不是模块对象。JVMTI_ERROR_INVALID_MODULE
如果 to_module
不是模块对象。JVMTI_ERROR_ILLEGAL_ARGUMENT
如果包 pkg_name
不属于该模块。JVMTI_ERROR_UNMODIFIABLE_MODULE
如果模块无法修改。请参阅 IsModifiableModule
。JVMTI_ERROR_NULL_POINTER
module
为NULL
。JVMTI_ERROR_NULL_POINTER
pkg_name
为NULL
。JVMTI_ERROR_NULL_POINTER
to_module
为NULL
。
添加模块使用
jvmtiError AddModuleUses(jvmtiEnv* env, jobject module, jclass service)
参数 名称 类型 描述 module
jobject
service
jclass
错误 描述 JVMTI_ERROR_INVALID_MODULE
如果 module
不是模块对象。JVMTI_ERROR_INVALID_CLASS
如果 service
不是类对象。JVMTI_ERROR_UNMODIFIABLE_MODULE
如果模块无法修改。请参阅 IsModifiableModule
。JVMTI_ERROR_NULL_POINTER
module
为NULL
。JVMTI_ERROR_NULL_POINTER
service
为NULL
。
添加模块提供
jvmtiError AddModuleProvides(jvmtiEnv* env, jobject module, jclass service, jclass impl_class)
参数 名称 类型 描述 module
jobject
要更新的模块。 service
jclass
要提供的服务。 impl_class
jclass
提供的服务的实现类。 错误 描述 JVMTI_ERROR_INVALID_MODULE
如果 module
不是模块对象。JVMTI_ERROR_INVALID_CLASS
如果 service
不是类对象。JVMTI_ERROR_INVALID_CLASS
如果 impl_class
不是类对象。JVMTI_ERROR_UNMODIFIABLE_MODULE
如果无法修改模块。请参阅 IsModifiableModule
。JVMTI_ERROR_NULL_POINTER
module
为NULL
。JVMTI_ERROR_NULL_POINTER
service
为NULL
。JVMTI_ERROR_NULL_POINTER
impl_class
为NULL
。
可修改模块
jvmtiError IsModifiableModule(jvmtiEnv* env, jobject module, jboolean* is_modifiable_module_ptr)
AddModuleReads
、AddModuleExports
、AddModuleOpens
、AddModuleUses
和AddModuleProvides
更新此模块。如果模块不可修改,则无法使用这些函数更新模块。当用于确定未命名模块是否可修改时,此函数的结果始终为JNI_TRUE
。参数 名称 类型 描述 module
jobject
is_modifiable_module_ptr
jboolean*
返回时,指向此函数的布尔结果。 代理传递指向 jboolean
的指针。返回时,已设置jboolean
。错误 描述 JVMTI_ERROR_INVALID_MODULE
如果 module
不是模块对象。JVMTI_ERROR_NULL_POINTER
module
为NULL
。JVMTI_ERROR_NULL_POINTER
is_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_ptr
jint*
返回时指向类的数量。代理传递一个指向 jint
的指针。返回时,jint
已被设置。classes_ptr
jclass**
返回时指向一个引用数组,每个类一个引用。代理传递一个指向 jclass*
的指针。返回时,jclass*
指向一个新分配的大小为*class_count_ptr
的数组。该数组应使用Deallocate
进行释放。由classes_ptr
返回的对象是 JNI 本地引用,必须进行 管理。错误 描述 JVMTI_ERROR_NULL_POINTER
class_count_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
classes_ptr
为NULL
。
获取类加载器加载的类
jvmtiError GetClassLoaderClasses(jvmtiEnv* env, jobject initiating_loader, jint* class_count_ptr, jclass** classes_ptr)
class_count_ptr
返回,数组本身通过classes_ptr
返回。 参见 Lookup::defineHiddenClass。参数 名称 类型 描述 initiating_loader
jobject
一个初始化类加载器。 如果 initiating_loader
为NULL
,则返回由引导加载器初始化的类。class_count_ptr
jint*
返回时指向类的数量。 代理传递一个指向 jint
的指针。返回时,jint
已被设置。classes_ptr
jclass**
返回时指向一个引用数组,每个类一个引用。 代理传递一个指向 jclass*
的指针。返回时,jclass*
指向一个新分配的大小为*class_count_ptr
的数组。该数组应使用Deallocate
进行释放。由classes_ptr
返回的对象是 JNI 本地引用,必须进行 管理。错误 描述 JVMTI_ERROR_NULL_POINTER
class_count_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
classes_ptr
为NULL
。
获取类签名
jvmtiError GetClassSignature(jvmtiEnv* env, jclass klass, char** signature_ptr, char** generic_ptr)
klass
指示的类的名称和通用签名。 如果类是类或接口,则:- 如果类或接口不是 隐藏的,则返回的名称是 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"。参数 名称 类型 描述 klass
jclass
要查询的类。 signature_ptr
char **
返回时指向类的 JNI 类型签名,编码为 修改的 UTF-8 字符串。 代理传递一个指向 char*
的指针。返回时,char*
指向一个新分配的数组。该数组应使用Deallocate
进行释放。如果signature_ptr
为NULL
,则不返回签名。generic_ptr
char **
返回时指向类的通用签名,编码为 修改的 UTF-8 字符串。如果类没有通用签名属性,则返回时指向 NULL
。 代理传递一个指向char*
的指针。返回时,char*
指向一个新分配的数组。该数组应使用Deallocate
进行释放。如果generic_ptr
为NULL
,则不返回通用签名。错误 描述 JVMTI_ERROR_INVALID_CLASS
klass
不是一个类对象或该类已被卸载。
获取类状态
jvmtiError GetClassStatus(jvmtiEnv* env, jclass klass, jint* status_ptr)
类状态标志 常量 值 描述 JVMTI_CLASS_STATUS_VERIFIED
1 类字节码已经验证 JVMTI_CLASS_STATUS_PREPARED
2 类准备完成 JVMTI_CLASS_STATUS_INITIALIZED
4 类初始化完成。静态初始化程序已运行。 JVMTI_CLASS_STATUS_ERROR
8 初始化期间的错误使类无法使用 JVMTI_CLASS_STATUS_ARRAY
16 类是一个数组。如果设置,所有其他位都为零。 JVMTI_CLASS_STATUS_PRIMITIVE
32 类是一个原始类(例如, java.lang.Integer.TYPE
)。如果设置,所有其他位都为零。参数 名称 类型 描述 klass
jclass
要查询的类。 status_ptr
jint*
返回时,指向该类当前状态的一个或多个类状态标志。 代理传递一个指向 jint
的指针。返回时,jint
已被设置。错误 描述 JVMTI_ERROR_INVALID_CLASS
klass
不是一个类对象或该类已被卸载。JVMTI_ERROR_NULL_POINTER
status_ptr
为NULL
。
获取源文件名
jvmtiError GetSourceFileName(jvmtiEnv* env, jclass klass, char** source_name_ptr)
klass
指示的类,通过source_name_ptr
返回源文件名。返回的字符串仅包含文件名,不包含目录名。 对于原始类(例如,java.lang.Integer.TYPE
)和数组,此函数返回JVMTI_ERROR_ABSENT_INFORMATION
。能力 效果 can_get_source_file_name
可以获取类的源文件名 参数 名称 类型 描述 klass
jclass
要查询的类。 source_name_ptr
char**
返回时,指向类的源文件名,编码为修改的UTF-8字符串。 代理传递一个指向 char*
的指针。返回时,char*
指向一个新分配的数组。应使用Deallocate
释放数组。错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_get_source_file_name
。使用AddCapabilities
。JVMTI_ERROR_ABSENT_INFORMATION
类信息不包括源文件名。这包括类是数组类或原始类的情况。 JVMTI_ERROR_INVALID_CLASS
klass
不是一个类对象或该类已被卸载。JVMTI_ERROR_NULL_POINTER
source_name_ptr
为NULL
。
获取类修饰符
jvmtiError GetClassModifiers(jvmtiEnv* env, jclass klass, jint* modifiers_ptr)
klass
指示的类,通过modifiers_ptr
返回访问标志。访问标志在 The Java™ Virtual Machine Specification, Chapter 4 中定义。 如果类是数组类,则其公共、私有和受保护修饰符与其组件类型的相同。对于原始类型的数组,此组件类型由一个原始类之一表示(例如,java.lang.Integer.TYPE
)。 如果类是原始类,则其公共修饰符始终为真,其受保护和私有修饰符始终为假。 如果类是数组类或原始类,则其最终修饰符始终为真,其接口修饰符始终为假。其其他修饰符的值不由此规范确定。参数 名称 类型 描述 klass
jclass
要查询的类。 modifiers_ptr
jint*
返回时,指向此类的当前访问标志。 代理传递一个指向 jint
的指针。返回时,jint
已被设置。错误 描述 JVMTI_ERROR_INVALID_CLASS
klass
不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTER
modifiers_ptr
是NULL
。
获取类方法
jvmtiError GetClassMethods(jvmtiEnv* env, jclass klass, jint* method_count_ptr, jmethodID** methods_ptr)
klass
指示的类的方法计数通过method_count_ptr
和方法ID列表通过methods_ptr
。方法列表包含构造函数和静态初始化程序以及真实方法。仅返回直接声明的方法(不包括继承的方法)。对于数组类和基本类(例如,java.lang.Integer.TYPE
),返回一个空方法列表。可选特性 能力 效果 can_maintain_original_method_order
可以按照类文件中的顺序返回方法 参数 名称 类型 描述 klass
jclass
要查询的类。 method_count_ptr
jint*
返回时,指向此类中声明的方法数量。 代理传递一个指向 jint
的指针。返回时,jint
已被设置。methods_ptr
jmethodID**
返回时,指向方法ID数组。 代理传递一个指向 jmethodID*
的指针。返回时,jmethodID*
指向一个新分配的大小为*method_count_ptr
的数组。应使用Deallocate
释放数组。错误 描述 JVMTI_ERROR_CLASS_NOT_PREPARED
klass
未准备好。JVMTI_ERROR_INVALID_CLASS
klass
不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTER
method_count_ptr
是NULL
。JVMTI_ERROR_NULL_POINTER
methods_ptr
是NULL
。
获取类字段
jvmtiError GetClassFields(jvmtiEnv* env, jclass klass, jint* field_count_ptr, jfieldID** fields_ptr)
klass
指示的类的字段计数通过field_count_ptr
和字段ID列表通过fields_ptr
。仅返回直接声明的字段(不包括继承的字段)。字段按照它们在类文件中出现的顺序返回。对于数组类和基本类(例如,java.lang.Integer.TYPE
),返回一个空字段列表。使用 JNI 来确定数组的长度。参数 名称 类型 描述 klass
jclass
要查询的类。 field_count_ptr
jint*
返回时,指向此类中声明的字段数量。 代理传递一个指向 jint
的指针。返回时,jint
已被设置。fields_ptr
jfieldID**
返回时,指向字段ID数组。 代理传递一个指向 jfieldID*
的指针。返回时,jfieldID*
指向一个新分配的大小为*field_count_ptr
的数组。应使用Deallocate
释放数组。错误 描述 JVMTI_ERROR_CLASS_NOT_PREPARED
klass
未准备好。JVMTI_ERROR_INVALID_CLASS
klass
不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTER
field_count_ptr
是NULL
。JVMTI_ERROR_NULL_POINTER
fields_ptr
是NULL
。
获取已实现的接口
jvmtiError GetImplementedInterfaces(jvmtiEnv* env, jclass klass, jint* interface_count_ptr, jclass** interfaces_ptr)
implements
子句中声明的接口。对于接口,此函数返回其extends
子句中声明的接口。对于数组类和基本类(例如,java.lang.Integer.TYPE
),返回一个空接口列表。参数 名称 类型 描述 klass
jclass
要查询的类。 interface_count_ptr
jint*
返回时指向接口数量的指针。 代理传递一个指向 jint
的指针。 返回时,jint
已被设置。interfaces_ptr
jclass**
返回时指向接口数组的指针。 代理传递一个指向 jclass*
的指针。 返回时,jclass*
指向一个新分配的大小为*interface_count_ptr
的数组。 应使用Deallocate
释放数组。 GetImplementedInterfaces() 返回的对象是 JNI 本地引用,必须进行 管理。错误 描述 JVMTI_ERROR_CLASS_NOT_PREPARED
klass
未准备好。JVMTI_ERROR_INVALID_CLASS
klass
不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTER
interface_count_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
interfaces_ptr
为NULL
。
获取类版本号
jvmtiError GetClassVersionNumbers(jvmtiEnv* env, jclass klass, jint* minor_version_ptr, jint* major_version_ptr)
klass
指示的类的次要和主要版本号,如 Java™虚拟机规范第4章 中定义。参数 名称 类型 描述 klass
jclass
要查询的类。 constant_pool_count_ptr
jint*
返回时,指向常量池表中条目数加一。这对应于类文件格式的 constant_pool_count
项。 代理传递一个指向jint
的指针。返回时,jint
已被设置。constant_pool_byte_count_ptr
jint*
返回时,指向返回的原始常量池中的字节数。 代理传递一个指向 jint
的指针。返回时,jint
已被设置。constant_pool_bytes_ptr
unsigned 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_CLASS
klass
不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTER
constant_pool_count_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
constant_pool_byte_count_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
constant_pool_bytes_ptr
为NULL
。
是否为接口
jvmtiError IsInterface(jvmtiEnv* env, jclass klass, jboolean* is_interface_ptr)
jboolean
结果为JNI_TRUE
,否则为JNI_FALSE
。参数 名称 类型 描述 klass
jclass
要查询的类。 is_interface_ptr
jboolean*
返回时,指向此函数的布尔结果。 代理传递一个指向 jboolean
的指针。返回时,jboolean
已被设置。错误 描述 JVMTI_ERROR_INVALID_CLASS
klass
不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTER
is_interface_ptr
为NULL
。
是否为数组类
jvmtiError IsArrayClass(jvmtiEnv* env, jclass klass, jboolean* is_array_class_ptr)
jboolean
结果为JNI_TRUE
,否则为JNI_FALSE
。参数 名称 类型 描述 klass
jclass
要查询的类。 is_array_class_ptr
jboolean*
返回时,指向此函数的布尔结果。 代理传递一个指向 jboolean
的指针。返回时,jboolean
已被设置。错误 描述 JVMTI_ERROR_INVALID_CLASS
klass
不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTER
is_array_class_ptr
为NULL
。
是否为可修改类
jvmtiError IsModifiableClass(jvmtiEnv* env, jclass klass, jboolean* is_modifiable_class_ptr)
is_modifiable_class_ptr
返回JNI_TRUE
),则该类可以使用RedefineClasses
(假设代理具有can_redefine_classes
能力)重新定义,或者可以使用RetransformClasses
(假设代理具有can_retransform_classes
能力)重新转换。如果类不可修改(is_modifiable_class_ptr
返回JNI_FALSE
),则该类既不能重新定义也不能重新转换。 原始类(例如,java.lang.Integer.TYPE
)、数组类和一些实现定义的类永远不可修改。可选特性 能力 效果 can_redefine_any_class
如果拥有此能力,则所有类(除了基本类型、数组和一些实现定义的类)都可以使用 RedefineClasses
进行修改。can_retransform_any_class
如果拥有此能力,则所有类(除了基本类型、数组和一些实现定义的类)都可以使用 RetransformClasses
进行修改。can_redefine_classes
对函数结果没有影响。但必须额外拥有此能力才能使用 RedefineClasses
修改类。can_retransform_classes
对函数结果没有影响。但必须额外拥有此能力才能使用 RetransformClasses
修改类。名称 类型 描述 klass
jclass
要查询的类。 is_modifiable_class_ptr
jboolean*
返回时,指向此函数的布尔结果。 代理传递一个指向 jboolean
的指针。返回时,jboolean
已被设置。错误 描述 JVMTI_ERROR_INVALID_CLASS
klass
不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTER
is_modifiable_class_ptr
为NULL
。
获取类加载器
jvmtiError GetClassLoader(jvmtiEnv* env, jclass klass, jobject* classloader_ptr)
klass
指示的类,通过classloader_ptr
返回加载该类的类加载器的引用。名称 类型 描述 klass
jclass
要查询的类。 classloader_ptr
jobject*
返回时,指向加载此类的类加载器。如果类不是由类加载器创建或类加载器是引导类加载器,则指向 NULL
。 代理传递一个指向jobject
的指针。返回时,jobject
已被设置。由classloader_ptr
返回的对象是 JNI 本地引用,必须进行 管理。错误 描述 JVMTI_ERROR_INVALID_CLASS
klass
不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTER
classloader_ptr
为NULL
。
获取源代码调试扩展
jvmtiError GetSourceDebugExtension(jvmtiEnv* env, jclass klass, char** source_debug_extension_ptr)
klass
指示的类,通过source_debug_extension_ptr
返回调试扩展。返回的字符串精确包含klass
的类文件中存在的调试扩展信息。能力 效果 can_get_source_debug_extension
可以获取类的源代码调试扩展 名称 类型 描述 klass
jclass
要查询的类。 source_debug_extension_ptr
char**
返回时,指向类的调试扩展,编码为 修改的 UTF-8 字符串。 代理传递一个指向 char*
的指针。返回时,char*
指向一个新分配的数组。应使用Deallocate
释放数组。错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备 can_get_source_debug_extension
能力。使用AddCapabilities
。JVMTI_ERROR_ABSENT_INFORMATION
类信息不包括调试扩展。 JVMTI_ERROR_INVALID_CLASS
klass
不是类对象或类已被卸载。JVMTI_ERROR_NULL_POINTER
source_debug_extension_ptr
为NULL
。
重新转换类
jvmtiError RetransformClasses(jvmtiEnv* env, jint class_count, const jclass* classes)
RedefineClasses
函数。 当类最初加载或重新定义时,初始类文件字节可以通过ClassFileLoadHook
事件进行转换。此函数重新运行转换过程(无论之前是否已发生过转换)。此重新转换遵循以下步骤:- 从初始类文件字节开始
- 对于每个 无法重新转换
- 的代理,其在上一次加载或重新定义期间收到
- 事件返回的字节(通过
- 参数)将被重用作为转换的输出;请注意,这等同于重新应用先前的转换,未更改。除了不会向这些代理发送
- 事件之外
- 对于每个 可以重新转换
- 的代理,将发送
- 事件,允许应用新的转换
- 转换后的类文件字节将安装为类的新定义
ClassFileLoadHook
new_class_data
ClassFileLoadHook
ClassFileLoadHook
ClassFileLoadHook
事件。 初始类文件字节表示传递给ClassLoader.defineClass
或RedefineClasses
(在应用任何转换之前),但它们可能不完全匹配。常量池可能以GetConstantPool
中描述的方式不同。方法字节码中的常量池索引将对应。某些属性可能不存在。例如,对于不具有意义的顺序,例如方法的顺序,可能不会保留顺序。 重新转换可能导致安装新版本的方法。旧方法版本可能会变得过时新方法版本将在新调用中使用。如果方法具有活动堆栈帧,则这些活动帧将继续运行原始方法版本的字节码。 此函数不会引起任何初始化,除非按照通常的JVM语义进行。换句话说,重新转换类不会导致其初始化器运行。静态字段的值将保持调用之前的状态。 线程无需暂停。 类中的所有断点都将被清除。 所有属性都将被更新。 重新转换后的类的实例不受影响--字段保留其先前的值。 实例上的标签也不受影响。 对于此调用,除了ClassFileLoadHook
事件之外,不会发送任何其他事件。 重新转换可能会更改方法体、常量池和属性(除非明确禁止)。重新转换不能添加、删除或重命名字段或方法,更改方法的签名,更改修饰符,或更改继承。重新转换不能更改NestHost
、NestMembers
、Record
或PermittedSubclasses
属性。这些限制可能在将来的版本中取消。有关尝试不受支持的重新转换时返回的错误代码的信息,请参阅下面的错误返回描述。在通过ClassFileLoadHook
链传递之前,类文件字节不会被验证或安装,因此返回的错误代码反映了转换的结果。如果返回的错误代码不是JVMTI_ERROR_NONE
,则将不会安装要重新转换的任何类的新定义。当此函数返回(带有错误代码为JVMTI_ERROR_NONE
)时,所有要重新转换的类都将安装其新定义。能力 效果 can_retransform_classes
可以使用 RetransformClasses
重新转换类。除了特定实现对此能力施加的限制(请参阅能力部分),此能力必须在此环境中首次启用ClassFileLoadHook
事件之前设置。在首次启用ClassFileLoadHook
时具有此能力的环境被称为重新转换能力。在首次启用ClassFileLoadHook
时不具备此能力的环境被称为重新转换无能。可选特性 can_retransform_any_class
RetransformClasses
可在任何可修改的类上调用。请参阅IsModifiableClass
。(还必须设置can_retransform_classes
)。参数 名称 类型 描述 class_count
jint
要重新转换的类的数量。 classes
const 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
)时,所有要重新定义的类都将安装其新定义。能力 效果 can_redefine_classes
可以使用 RedefineClasses
重新定义类。可选特性 can_redefine_any_class
RedefineClasses
可在任何可修改的类上调用。请参阅IsModifiableClass
。(can_redefine_classes
也必须设置)jvmtiClassDefinition
- 类重新定义描述字段 类型 描述 klass
jclass
此类的类对象 class_byte_count
jint
定义类的字节数(以下) class_bytes
const unsigned char*
定义类的字节(在Java™虚拟机规范第4章中) 参数 名称 类型 描述 class_count
jint
在 class_definitions
中指定的类的数量class_definitions
const jvmtiClassDefinition*
新类定义的数组 代理传入一个包含 class_count
个jvmtiClassDefinition
元素的数组。
对象
对象函数: 对象类型:jvmtiMonitorUsage
- 对象监视器使用信息
获取对象大小
jvmtiError GetObjectSize(jvmtiEnv* env, jobject object, jlong* size_ptr)
object
指示的对象的大小,通过size_ptr
返回对象的大小。这个大小是对该对象消耗的存储空间的实现特定近似值。它可能包括对象的一部分或全部开销,因此对于在一个实现内部进行比较很有用,但不适用于不同实现之间的比较。在JVM的单个调用期间,估计值可能会发生变化。参数 名称 类型 描述 object
jobject
要查询的对象。 size_ptr
jlong*
返回时,指向对象的大小(以字节为单位)。 代理传递一个指向 jlong
的指针。返回时,jlong
已设置。错误 描述 JVMTI_ERROR_INVALID_OBJECT
object
不是对象。JVMTI_ERROR_NULL_POINTER
size_ptr
是NULL
。
获取对象哈希码
jvmtiError GetObjectHashCode(jvmtiEnv* env, jobject object, jint* hash_code_ptr)
object
指示的对象的哈希码,通过hash_code_ptr
返回哈希码。这个哈希码可用于维护对象引用的哈希表,但在某些实现中,这可能会导致显著的性能影响--在大多数情况下,标签将是与对象关联信息的更有效手段。此函数保证特定对象的相同哈希码值在其整个生命周期中保持不变。参数 名称 类型 描述 object
jobject
要查询的对象。 hash_code_ptr
jint*
返回时,指向对象的哈希码。 代理传递一个指向 jint
的指针。返回时,jint
已被设置。错误 描述 JVMTI_ERROR_INVALID_OBJECT
object
不是一个对象。JVMTI_ERROR_NULL_POINTER
hash_code_ptr
是NULL
。
获取对象监视器使用情况
typedef struct { jthread owner; jint entry_count; jint waiter_count; jthread* waiters; jint notify_waiter_count; jthread* notify_waiters; } jvmtiMonitorUsage;
jvmtiError GetObjectMonitorUsage(jvmtiEnv* env, jobject object, jvmtiMonitorUsage* info_ptr)
jvmtiMonitorUsage
结构的字段将填充有关监视器使用情况的信息。能力 效果 can_get_monitor_info
可以 GetObjectMonitorUsage
jvmtiMonitorUsage
- 对象监视器使用信息字段 类型 描述 owner
jthread
拥有此监视器的线程,如果未使用则为 NULL
entry_count
jint
拥有线程进入监视器的次数 waiter_count
jint
等待拥有此监视器的线程数 waiters
jthread*
waiter_count
个等待线程notify_waiter_count
jint
等待由此监视器通知的线程数 notify_waiters
jthread*
notify_waiter_count
个等待被通知的线程参数 名称 类型 描述 object
jobject
要查询的对象。 info_ptr
jvmtiMonitorUsage*
返回时,填充指定对象的监视器信息。 代理传递一个指向 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_OBJECT
object
不是一个对象。JVMTI_ERROR_NULL_POINTER
info_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 章节 中称为字段描述符
。参数 名称 类型 描述 klass
jclass
要查询的字段的类。 field
jfieldID
要查询的字段。 name_ptr
char **
返回时,指向字段名称,编码为修改后的UTF-8字符串。 代理传递一个指向 char*
的指针。 返回时,char*
指向一个新分配的数组。 该数组应使用Deallocate
释放。 如果name_ptr
为NULL
,则不返回名称。signature_ptr
char **
返回时,指向字段签名,编码为修改后的UTF-8字符串。 代理传递一个指向 char*
的指针。 返回时,char*
指向一个新分配的数组。 该数组应使用Deallocate
释放。 如果signature_ptr
为NULL
,则不返回签名。generic_ptr
char **
返回时,指向字段的通用签名,编码为修改后的UTF-8字符串。 如果字段没有通用签名属性,则返回时指向 NULL
。 代理传递一个指向char*
的指针。 返回时,char*
指向一个新分配的数组。 该数组应使用Deallocate
释放。 如果generic_ptr
为NULL
,则不返回通用签名。错误 描述 JVMTI_ERROR_INVALID_CLASS
klass
不是类对象或类已被卸载。JVMTI_ERROR_INVALID_FIELDID
field
不是jfieldID。
获取字段声明类
jvmtiError GetFieldDeclaringClass(jvmtiEnv* env, jclass klass, jfieldID field, jclass* declaring_class_ptr)
klass
和field
指示的字段的定义类,通过declaring_class_ptr
。 声明类将是klass
、一个超类或一个实现的接口。参数 名称 类型 描述 klass
jclass
要查询的类。 field
jfieldID
要查询的字段。 declaring_class_ptr
jclass*
返回时,指向声明类 代理传递一个指向 的指针。 返回时, 已被设置。 declaring_class_ptr
返回的对象是JNI本地引用,必须 管理。错误 描述 JVMTI_ERROR_INVALID_CLASS
klass
不是类对象或类已被卸载。JVMTI_ERROR_INVALID_FIELDID
field
不是jfieldID。JVMTI_ERROR_NULL_POINTER
declaring_class_ptr
为NULL
。
获取字段修饰符
jvmtiError GetFieldModifiers(jvmtiEnv* env, jclass klass, jfieldID field, jint* modifiers_ptr)
klass
和field
指示的字段的访问标志,通过modifiers_ptr
。 访问标志在Java™虚拟机规范,第4章中定义。参数 名称 类型 描述 klass
jclass
要查询的类。 field
jfieldID
要查询的字段。 modifiers_ptr
jint*
返回时,指向访问标志。 代理传递一个指向 的指针。 返回时, 已被设置。 错误 描述 JVMTI_ERROR_INVALID_CLASS
klass
不是类对象或类已被卸载。JVMTI_ERROR_INVALID_FIELDID
field
不是jfieldID。JVMTI_ERROR_NULL_POINTER
modifiers_ptr
为NULL
。
字段是否合成
jvmtiError IsFieldSynthetic(jvmtiEnv* env, jclass klass, jfieldID field, jboolean* is_synthetic_ptr)
klass
和field
指示的字段是否合成的值,通过is_synthetic_ptr
。 合成字段由编译器生成,但不在原始源代码中存在。能力 效果 can_get_synthetic_attribute
可以测试字段或方法是否是合成的 - IsFieldSynthetic
和IsMethodSynthetic
参数 名称 类型 描述 klass
jclass
要查询的字段的类。 field
jfieldID
要查询的字段。 is_synthetic_ptr
jboolean*
返回时,指向此函数的布尔结果。 代理传递指向 jboolean
的指针。返回时,jboolean
已设置。错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备 can_get_synthetic_attribute
能力。使用AddCapabilities
。JVMTI_ERROR_INVALID_CLASS
klass
不是类对象或类已被卸载。JVMTI_ERROR_INVALID_FIELDID
field
不是jfieldID。JVMTI_ERROR_NULL_POINTER
is_synthetic_ptr
为NULL
。
方法
方法函数:- 获取方法名称(及签名)
- 获取方法声明类
- 获取方法修饰符
- 获取最大本地变量数
- 获取参数大小
- 获取行号表
- 获取方法位置
- 获取本地变量表
- 获取字节码
- 方法是否为本地方法
- 方法是否为合成方法
- 方法是否已过时
- 设置本地方法前缀
- 设置本地方法前缀
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语言规范中定义的方法签名不同。参数 名称 类型 描述 method
jmethodID
name_ptr
char **
返回时,指向方法名称,编码为修改的UTF-8字符串。 代理传递指向 char*
的指针。返回时,char*
指向新分配的数组。应使用Deallocate
释放数组。如果name_ptr
为NULL
,则不返回名称。signature_ptr
char **
返回时,指向方法签名,编码为修改的UTF-8字符串。 代理传递指向 char*
的指针。返回时,char*
指向新分配的数组。应使用Deallocate
释放数组。如果signature_ptr
为NULL
,则不返回签名。generic_ptr
char **
返回时,指向方法的通用签名,编码为修改的UTF-8字符串。如果方法没有通用签名属性,则返回时指向 NULL
。 代理传递指向char*
的指针。返回时,char*
指向新分配的数组。应使用Deallocate
释放数组。如果generic_ptr
为NULL
,则不返回通用签名。错误 描述 JVMTI_ERROR_INVALID_METHODID
method
不是jmethodID。
获取方法声明类
jvmtiError GetMethodDeclaringClass(jvmtiEnv* env, jmethodID method, jclass* declaring_class_ptr)
method
指示的方法的定义类通过declaring_class_ptr
。参数 名称 类型 描述 method
jmethodID
要查询的方法。 declaring_class_ptr
jclass*
返回指向声明类的指针 代理传递一个指向 jclass
的指针。返回时,jclass
已被设置。由declaring_class_ptr
返回的对象是 JNI 本地引用,必须进行 管理。错误 描述 JVMTI_ERROR_INVALID_METHODID
method
不是 jmethodID。JVMTI_ERROR_NULL_POINTER
declaring_class_ptr
是NULL
。
获取方法修饰符
jvmtiError GetMethodModifiers(jvmtiEnv* env, jmethodID method, jint* modifiers_ptr)
method
指示的方法的访问标志,通过modifiers_ptr
。访问标志在 Java™ 虚拟机规范,第 4 章 中定义。参数 名称 类型 描述 method
jmethodID
要查询的方法。 modifiers_ptr
jint*
返回指向访问标志的指针。 代理传递一个指向 jint
的指针。返回时,jint
已被设置。错误 描述 JVMTI_ERROR_INVALID_METHODID
method
不是 jmethodID。JVMTI_ERROR_NULL_POINTER
modifiers_ptr
是NULL
。
获取最大本地变量数
jvmtiError GetMaxLocals(jvmtiEnv* env, jmethodID method, jint* max_ptr)
method
指示的方法使用的本地变量槽的数量,包括用于将参数传递给方法的本地变量。 参见max_locals
在 Java™ 虚拟机规范,第 4.7.3 章。参数 名称 类型 描述 method
jmethodID
要查询的方法。 max_ptr
jint*
返回指向最大本地槽数的指针。 代理传递一个指向 jint
的指针。返回时,jint
已被设置。错误 描述 JVMTI_ERROR_INVALID_METHODID
method
不是 jmethodID。JVMTI_ERROR_NATIVE_METHOD
method
是本地方法。JVMTI_ERROR_NULL_POINTER
max_ptr
是NULL
。
获取参数大小
jvmtiError GetArgumentsSize(jvmtiEnv* env, jmethodID method, jint* size_ptr)
method
指示的方法的参数使用的本地变量槽数,通过max_ptr
。请注意,两个字长的参数使用两个槽。参数 名称 类型 描述 method
jmethodID
要查询的方法。 size_ptr
jint*
返回指向参数槽数的指针。 代理传递一个指向 jint
的指针。返回时,jint
已被设置。错误 描述 JVMTI_ERROR_INVALID_METHODID
method
不是 jmethodID。JVMTI_ERROR_NATIVE_METHOD
method
是本地方法。JVMTI_ERROR_NULL_POINTER
size_ptr
是NULL
。
获取行号表
typedef struct { jlocation start_location; jint line_number; } jvmtiLineNumberEntry;
jvmtiError GetLineNumberTable(jvmtiEnv* env, jmethodID method, jint* entry_count_ptr, jvmtiLineNumberEntry** table_ptr)
method
指示的方法的源代码行号条目表。表的大小通过entry_count_ptr
返回,表本身通过table_ptr
返回。能力 效果 can_get_line_numbers
可以获取方法的行号表 jvmtiLineNumberEntry
- 行号表条目字段 类型 描述 start_location
jlocation
行开始的 jlocation
line_number
jint
行号 参数 名称 类型 描述 method
jmethodID
要查询的方法。 entry_count_ptr
jint*
返回时,指向表中的条目数 代理传递一个指向 jint
的指针。返回时,jint
已设置。table_ptr
jvmtiLineNumberEntry**
返回时,指向行号表指针。 代理传递一个指向 jvmtiLineNumberEntry*
的指针。返回时,jvmtiLineNumberEntry*
指向一个新分配的大小为*entry_count_ptr
的数组。应使用Deallocate
释放数组。错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_get_line_numbers
。使用AddCapabilities
。JVMTI_ERROR_ABSENT_INFORMATION
类信息不包括行号。 JVMTI_ERROR_INVALID_METHODID
method
不是jmethodID。JVMTI_ERROR_NATIVE_METHOD
method
是本地方法。JVMTI_ERROR_NULL_POINTER
entry_count_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
table_ptr
为NULL
。
获取方法位置
jvmtiError GetMethodLocation(jvmtiEnv* env, jmethodID method, jlocation* start_location_ptr, jlocation* end_location_ptr)
method
指示的方法的开始和结束地址,通过start_location_ptr
和end_location_ptr
。在传统的字节码索引方案中,start_location_ptr
始终指向零,end_location_ptr
始终指向字节码计数减一。参数 名称 类型 描述 method
jmethodID
要查询的方法。 start_location_ptr
jlocation*
返回时,指向第一个位置,或 -1
如果位置信息不可用。如果信息可用且GetJLocationFormat
返回JVMTI_JLOCATION_JVMBCI
,则此值始终为零。 代理传递一个指向jlocation
的指针。返回时,jlocation
已设置。end_location_ptr
jlocation*
返回时,指向最后一个位置,或 -1
如果位置信息不可用。 代理传递一个指向jlocation
的指针。返回时,jlocation
已设置。错误 描述 JVMTI_ERROR_ABSENT_INFORMATION
类信息不包括方法大小。 JVMTI_ERROR_INVALID_METHODID
method
不是jmethodID。JVMTI_ERROR_NATIVE_METHOD
method
是本地方法。JVMTI_ERROR_NULL_POINTER
start_location_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
end_location_ptr
为NULL
。
获取局部变量表
typedef struct { jlocation start_location; jint length; char* name; char* signature; char* generic_signature; jint slot; } jvmtiLocalVariableEntry;
jvmtiError GetLocalVariableTable(jvmtiEnv* env, jmethodID method, jint* entry_count_ptr, jvmtiLocalVariableEntry** table_ptr)
能力 效果 can_access_local_variables
可以设置和获取局部变量 jvmtiLocalVariableEntry
- 本地变量表条目字段 类型 描述 start_location
jlocation
本地变量首次有效的代码数组索引(即必须具有值的位置)。 length
jint
本地变量有效部分的长度。本地变量有效的最后一个代码数组索引为 start_location + length
。name
char*
本地变量名称,编码为 修改过的 UTF-8 字符串。 signature
char*
本地变量的类型签名,编码为 修改过的 UTF-8 字符串。签名格式与《Java™虚拟机规范》第4.3.2章节中定义的相同。 generic_signature
char*
本地变量的通用签名,编码为 修改过的 UTF-8 字符串。对于没有通用类型的任何本地变量,此字段的值将为 NULL
。slot
jint
本地变量的槽位。参见 本地变量。 参数 名称 类型 描述 method
jmethodID
要查询的方法。 entry_count_ptr
jint*
返回时,指向表中条目的数量 代理传递一个指向 jint
的指针。返回时,jint
已被设置。table_ptr
jvmtiLocalVariableEntry**
返回时,指向本地变量表条目数组 代理传递一个指向 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_METHODID
method
不是 jmethodID。JVMTI_ERROR_NATIVE_METHOD
method
是本地方法。JVMTI_ERROR_NULL_POINTER
entry_count_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
table_ptr
为NULL
。
获取字节码
jvmtiError GetBytecodes(jvmtiEnv* env, jmethodID method, jint* bytecode_count_ptr, unsigned char** bytecodes_ptr)
method
。通过bytecode_count_ptr
返回字节码的数量。通过bytecodes_ptr
返回字节码本身。能力 效果 can_get_bytecodes
可以获取方法的字节码 GetBytecodes
参数 名称 类型 描述 method
jmethodID
要查询的方法。 bytecode_count_ptr
jint*
返回时,指向字节码数组的长度 代理传递一个指向 jint
的指针。返回时,jint
已被设置。bytecodes_ptr
unsigned char**
返回时,指向字节码数组的指针 代理传递一个指向 unsigned char*
的指针。返回时,unsigned char*
指向一个新分配的大小为*bytecode_count_ptr
的数组。数组应使用Deallocate
释放。错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备 can_get_bytecodes
能力。使用AddCapabilities
。JVMTI_ERROR_INVALID_METHODID
method
不是 jmethodID。JVMTI_ERROR_NATIVE_METHOD
method
是本地方法。JVMTI_ERROR_NULL_POINTER
bytecode_count_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
bytecodes_ptr
为NULL
。
方法是否为本地方法
jvmtiError IsMethodNative(jvmtiEnv* env, jmethodID method, jboolean* is_native_ptr)
method
指示的方法是否为本地方法的值通过is_native_ptr
参数 名称 类型 描述 方法
jmethodID
要查询的方法。 is_native_ptr
jboolean*
返回时,指向此函数的布尔结果的指针。 代理传递一个指向 jboolean
的指针。返回时,jboolean
已被设置。错误 描述 JVMTI_ERROR_INVALID_METHODID
方法
不是 jmethodID。JVMTI_ERROR_NULL_POINTER
is_native_ptr
是NULL
。
方法是否合成
jvmtiError IsMethodSynthetic(jvmtiEnv* env, jmethodID method, jboolean* is_synthetic_ptr)
方法
指示的方法,通过is_synthetic_ptr
返回一个值,指示方法是否是合成的。合成方法是编译器生成的,但不在原始源代码中存在。能力 效果 can_get_synthetic_attribute
可以测试字段或方法是否是合成的 - IsFieldSynthetic
和IsMethodSynthetic
参数 名称 类型 描述 方法
jmethodID
要查询的方法。 is_synthetic_ptr
jboolean*
返回时,指向此函数的布尔结果的指针。 代理传递一个指向 jboolean
的指针。返回时,jboolean
已被设置。错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备 can_get_synthetic_attribute
能力。使用AddCapabilities
。JVMTI_ERROR_INVALID_METHODID
方法
不是 jmethodID。JVMTI_ERROR_NULL_POINTER
is_synthetic_ptr
是NULL
。
方法是否过时
jvmtiError IsMethodObsolete(jvmtiEnv* env, jmethodID method, jboolean* is_obsolete_ptr)
参数 名称 类型 描述 方法
jmethodID
要查询的方法 ID。 is_obsolete_ptr
jboolean*
返回时,指向此函数的布尔结果的指针。 代理传递一个指向 jboolean
的指针。返回时,jboolean
已被设置。错误 描述 JVMTI_ERROR_INVALID_METHODID
方法
不是 jmethodID。JVMTI_ERROR_NULL_POINTER
is_obsolete_ptr
是NULL
。
设置本地方法前缀
jvmtiError SetNativeMethodPrefix(jvmtiEnv* env, const char* prefix)
native boolean foo(int x);
boolean foo(int x) { ... 记录进入 foo ... return wrapped_foo(x); } native boolean wrapped_foo(int x);
wrapped_foo
需要解析为foo
的本地实现,可能是:Java_somePackage_someClass_foo(JNIEnv* env, jint x)
RegisterNatives
进行显式解析和正常的自动解析。对于RegisterNatives
,VM 将尝试进行以下关联:method(foo) -> nativeImplementation(foo)
method(wrapped_foo) -> nativeImplementation(foo)
method(wrapped_foo) -> nativeImplementation(wrapped_foo)
method(wrapped_foo) -> nativeImplementation(foo)
ClassFileLoadHook
事件中描述。因此,如果三个环境应用了包装器,foo
可能会变成$env3_$env2_$env1_foo
。但是,如果,例如,第二个环境没有对foo
应用包装器,那么它将只是$env3_$env1_foo
。为了能够有效地确定前缀的顺序,只有在其非本机包装器存在时才应用中间前缀。因此,在最后一个示例中,即使$env1_foo
不是本机方法,也会应用$env1_
前缀,因为$env1_foo
存在。 由于前缀在解析时使用,而解析可能会任意延迟,因此只要存在相应的带前缀的本机方法,本机方法前缀必须保持设置。能力 效果 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
调用此函数相同。能力 效果 can_set_native_method_prefix
可以设置在无法解析本机方法时应用的前缀 - SetNativeMethodPrefix
和SetNativeMethodPrefixes
参数 名称 类型 描述 prefix_count
jint
要应用的前缀数量。 prefixes
char **
要应用于此环境的前缀,每个都编码为修改后的UTF-8字符串。 错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_set_native_method_prefix
。请使用AddCapabilities
。JVMTI_ERROR_ILLEGAL_ARGUMENT
prefix_count
小于0
。JVMTI_ERROR_NULL_POINTER
prefixes
为NULL
。
原始监视器
原始监视器函数:
创建原始监视器
jvmtiError CreateRawMonitor(jvmtiEnv* env, const char* name, jrawMonitorID* monitor_ptr)
只能在OnLoad或live阶段调用311.0修改后的UTF-8字符串。 代理传入一个 char
数组。代理传递一个指向 jrawMonitorID
的指针。返回时,jrawMonitorID
已设置。参数 名称 类型 描述 name
const char*
monitor_ptr
jrawMonitorID*
错误 描述 JVMTI_ERROR_NULL_POINTER
name
为NULL
。JVMTI_ERROR_NULL_POINTER
monitor_ptr
为NULL
。
销毁原始监视器
jvmtiError DestroyRawMonitor(jvmtiEnv* env, jrawMonitorID monitor)
只能在OnLoad或live阶段调用321.0参数 名称 类型 描述 monitor
jrawMonitorID
监视器 错误 描述 JVMTI_ERROR_NOT_MONITOR_OWNER
非监视器所有者 JVMTI_ERROR_INVALID_MONITOR
monitor
不是jrawMonitorID。
进入原始监视器
jvmtiError RawMonitorEnter(jvmtiEnv* env, jrawMonitorID monitor)
OnLoad
期间(在附加线程存在之前)进入监视器,并且在附加线程出现时尚未退出,则认为进入是在主线程上发生的。可以在任何阶段调用331.0参数 名称 类型 描述 monitor
jrawMonitorID
监视器 错误 描述 JVMTI_ERROR_INVALID_MONITOR
monitor
不是jrawMonitorID。
退出原始监视器
jvmtiError RawMonitorExit(jvmtiEnv* env, jrawMonitorID monitor)
可以在任何阶段调用341.0参数 名称 类型 描述 monitor
jrawMonitorID
监视器 错误 描述 JVMTI_ERROR_NOT_MONITOR_OWNER
非监视器所有者 JVMTI_ERROR_INVALID_MONITOR
monitor
不是jrawMonitorID。
等待原始监视器
jvmtiError RawMonitorWait(jvmtiEnv* env, jrawMonitorID monitor, jlong millis)
RawMonitorNotify
或RawMonitorNotifyAll
用于指定的原始监视器,或指定的 超时 已经过去。可在任何阶段调用此函数可以从对 Heap 迭代函数的回调中调用,也可以从GarbageCollectionStart
、GarbageCollectionFinish
和ObjectFree
事件的事件处理程序中调用。351.0参数 名称 类型 描述 monitor
jrawMonitorID
监视器 millis
jlong
超时时间,以毫秒为单位。如果超时时间为零,则不考虑实时时间,线程将等待直到收到通知。 错误 描述 JVMTI_ERROR_NOT_MONITOR_OWNER
非监视器所有者 JVMTI_ERROR_INTERRUPT
等待被中断,请重试 JVMTI_ERROR_INVALID_MONITOR
monitor
不是 jrawMonitorID。
原始监视器通知
jvmtiError RawMonitorNotify(jvmtiEnv* env, jrawMonitorID monitor)
可在任何阶段调用此函数可以从对 Heap 迭代函数的回调中调用,也可以从GarbageCollectionStart
、GarbageCollectionFinish
和ObjectFree
事件的事件处理程序中调用。361.0参数 名称 类型 描述 monitor
jrawMonitorID
监视器 错误 描述 JVMTI_ERROR_NOT_MONITOR_OWNER
非监视器所有者 JVMTI_ERROR_INVALID_MONITOR
monitor
不是 jrawMonitorID。
原始监视器通知所有
jvmtiError RawMonitorNotifyAll(jvmtiEnv* env, jrawMonitorID monitor)
可在任何阶段调用此函数可以从对 Heap 迭代函数的回调中调用,也可以从GarbageCollectionStart
、GarbageCollectionFinish
和ObjectFree
事件的事件处理程序中调用。371.0参数 名称 类型 描述 monitor
jrawMonitorID
监视器 错误 描述 JVMTI_ERROR_NOT_MONITOR_OWNER
非监视器所有者 JVMTI_ERROR_INVALID_MONITOR
monitor
不是 jrawMonitorID。
JNI函数拦截
JNI函数拦截函数: 通过操纵JNI函数表提供拦截和重新发送Java本机接口(JNI)函数调用的能力。请参阅 JNI函数 在 Java本机接口规范 中。 以下示例说明拦截NewGlobalRef
JNI调用以计算引用创建次数。JNIEnv original_jni_Functions; JNIEnv redirected_jni_Functions; int my_global_ref_count = 0; jobject MyNewGlobalRef(JNIEnv *jni_env, jobject lobj) { ++my_global_ref_count; return originalJNIFunctions->NewGlobalRef(env, lobj); } void myInit() { jvmtiError err; err = (*jvmti_env)->GetJNIFunctionTable(jvmti_env, &original_jni_Functions); if (err != JVMTI_ERROR_NONE) { die(); } err = (*jvmti_env)->GetJNIFunctionTable(jvmti_env, &redirected_jni_Functions); if (err != JVMTI_ERROR_NONE) { die(); } redirectedJNIFunctions->NewGlobalRef = MyNewGlobalRef; err = (*jvmti_env)->SetJNIFunctionTable(jvmti_env, redirected_jni_Functions); if (err != JVMTI_ERROR_NONE) { die(); } }
myInit
之后的某个时刻,将执行用户的JNI代码,该代码会调用创建新全局引用的调用。该调用不会转到正常的JNI实现,而是转到myNewGlobalRef
。请注意,保留原始函数表的副本,以便在收集数据后可以调用正常的JNI函数。还请注意,任何未被覆盖的JNI函数将正常工作。
设置JNI函数表
jvmtiError SetJNIFunctionTable(jvmtiEnv* env, const jniNativeInterface* function_table)
GetJNIFunctionTable
获取要传递给此函数的函数表。为使此函数生效,必须使用更新后的表条目的JNI客户端。由于表被定义为const
,一些编译器可能会优化掉对表的访问,从而阻止此函数生效。表被复制--对表的本地副本的更改不会产生影响。此函数仅影响函数表,环境的所有其他方面不受影响。请参见上面的示例 above。参数 名称 类型 描述 function_table
const jniNativeInterface *
指向新的JNI函数表。代理传递指向 jniNativeInterface
的指针。错误 描述 JVMTI_ERROR_NULL_POINTER
function_table
为NULL
。
获取JNI函数表
jvmtiError GetJNIFunctionTable(jvmtiEnv* env, jniNativeInterface** function_table)
SetJNIFunctionTable
已被调用,则返回修改后的(而不是原始的)函数表。只复制函数表,不复制环境的其他方面。参见上面的示例。参数 名称 类型 描述 function_table
jniNativeInterface **
返回时, *function_table
指向新分配的JNI函数表的副本。代理传递指向jniNativeInterface*
的指针。返回时,jniNativeInterface*
指向新分配的数组。应使用Deallocate
释放数组。错误 描述 JVMTI_ERROR_NULL_POINTER
function_table
为NULL
。
事件管理
事件管理函数: 事件管理类型:jvmtiEventMode
- 事件启用/禁用
设置事件回调
jvmtiError SetEventCallbacks(jvmtiEnv* env, const jvmtiEventCallbacks* callbacks, jint size_of_callbacks)
NULL
或事件超出size_of_callbacks
时,不会发送任何事件。有关事件的详细信息在本文档的后面描述。为了发送事件,事件必须被启用并具有回调--调用此函数和SetEventNotificationMode
的顺序不会影响结果。参数 名称 类型 描述 callbacks
const jvmtiEventCallbacks *
新的事件回调。代理传递指向 jvmtiEventCallbacks
的指针。如果callbacks
为NULL
,则删除现有的回调。size_of_callbacks
jint
sizeof(jvmtiEventCallbacks)
--用于版本兼容性。错误 描述 JVMTI_ERROR_ILLEGAL_ARGUMENT
size_of_callbacks
小于0
。
设置事件通知模式
typedef enum { JVMTI_ENABLE = 1, JVMTI_DISABLE = 0 } jvmtiEventMode;
jvmtiError SetEventNotificationMode(jvmtiEnv* env, jvmtiEventMode mode, jvmtiEvent event_type, jthread event_thread, ...)
事件启用/禁用 ( jvmtiEventMode
)常量 值 描述 JVMTI_ENABLE
1 如果 mode
为JVMTI_ENABLE
,则事件event_type
将被启用JVMTI_DISABLE
0 如果 mode
为JVMTI_DISABLE
,则事件event_type
将被禁用event_thread
为NULL
,则事件在全局范围内启用或禁用;否则,它将针对特定线程启用或禁用。如果在线程级别或全局级别启用了事件,则为特定线程生成事件。 有关特定事件的信息,请参见 下面。 以下事件无法通过此函数在线程级别进行控制。VMInit
VMStart
VMDeath
ThreadStart
VirtualThreadStart
CompiledMethodLoad
CompiledMethodUnload
DynamicCodeGenerated
DataDumpRequest
参数 名称 类型 描述 模式
jvmtiEventMode
JVMTI_ENABLE
或JVMTI_DISABLE
事件类型
jvmtiEvent
要控制的事件 事件线程
jthread
要控制的线程 如果 event_thread
是NULL
,则在全局级别控制事件。...
...
用于未来扩展 错误 描述 JVMTI_ERROR_INVALID_THREAD
event_thread
非NULL
且不是有效线程。JVMTI_ERROR_THREAD_NOT_ALIVE
event_thread
非NULL
且不活动(未启动或已终止)。JVMTI_ERROR_ILLEGAL_ARGUMENT
尝试对不允许线程级别控制的事件进行线程级别控制。 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
未拥有所需的事件启用能力。 JVMTI_ERROR_ILLEGAL_ARGUMENT
mode
不是jvmtiEventMode。JVMTI_ERROR_INVALID_EVENT_TYPE
event_type
不是jvmtiEvent。
生成事件
jvmtiError GenerateEvents(jvmtiEnv* env, jvmtiEvent event_type)
event_type
是JVMTI_EVENT_COMPILED_METHOD_LOAD
,则将为每个当前编译的方法发送一个CompiledMethodLoad
事件。已加载并现在已卸载的方法不会发送。先前发送的事件历史不会影响此函数发送的事件--例如,每次调用此函数时都会发送所有当前编译的方法。 当代理程序在程序执行开始后附加时可能错过事件时,此函数非常有用;此函数生成错过的事件。 尝试执行Java编程语言代码或JNI函数可能会暂停,直到此函数返回 - 因此不应从发送事件的线程调用任何一个。此函数仅在错过的事件已发送、处理并返回后才返回。事件可能在与事件发生的线程不同的线程上发送。事件的回调必须使用SetEventCallbacks
设置,并且必须使用SetEventNotificationMode
启用事件,否则事件将不会发生。如果VM不再具有生成所请求事件的某些或全部信息,则简单地不发送这些事件 - 不会返回错误。 仅支持以下事件:可选功能 能力 效果 can_generate_compiled_method_load_events
可以在方法编译或卸载时生成事件 参数 名称 类型 描述 event_type
jvmtiEvent
要生成的事件类型。必须是以下之一:
扩展机制
扩展机制函数: 扩展机制函数类型: 扩展机制类型:jvmtiParamTypes
- 扩展函数/事件参数类型jvmtiParamKind
- 扩展函数/事件参数种类jvmtiParamInfo
- 扩展函数/事件参数信息jvmtiExtensionFunctionInfo
- 扩展函数信息jvmtiExtensionEventInfo
- 扩展事件信息
扩展函数/事件参数类型( jvmtiParamTypes
)常量 值 描述 JVMTI_TYPE_JBYTE
101 Java编程语言基本类型 - byte
。JNI类型jbyte
。JVMTI_TYPE_JCHAR
102 Java编程语言基本类型 - char
。JNI类型jchar
。JVMTI_TYPE_JSHORT
103 Java编程语言基本类型 - short
。JNI类型jshort
。JVMTI_TYPE_JINT
104 Java编程语言基本类型 - int
。JNI类型jint
。JVMTI_TYPE_JLONG
105 Java编程语言基本类型 - long
。JNI类型jlong
。JVMTI_TYPE_JFLOAT
106 Java编程语言基本类型 - float
。JNI类型jfloat
。JVMTI_TYPE_JDOUBLE
107 Java编程语言基本类型 - double
。JNI类型jdouble
。JVMTI_TYPE_JBOOLEAN
108 Java编程语言基本类型 - boolean
。JNI类型jboolean
。JVMTI_TYPE_JOBJECT
109 Java编程语言对象类型 - java.lang.Object
。JNI类型jobject
。返回值是JNI本地引用,必须进行管理。JVMTI_TYPE_JTHREAD
110 Java编程语言对象类型 - java.lang.Thread
。JVM TI类型jthread
。返回值是JNI本地引用,必须进行管理。JVMTI_TYPE_JCLASS
111 Java编程语言对象类型 - java.lang.Class
。JNI类型jclass
。返回值是JNI本地引用,必须进行管理。JVMTI_TYPE_JVALUE
112 所有Java编程语言基本和对象类型的联合 - JNI类型 jvalue
。表示对象类型的返回值是JNI本地引用,必须进行管理。JVMTI_TYPE_JFIELDID
113 Java编程语言字段标识符 - JNI类型 jfieldID
。JVMTI_TYPE_JMETHODID
114 Java编程语言方法标识符 - JNI类型 jmethodID
。JVMTI_TYPE_CCHAR
115 C编程语言类型 - char
。JVMTI_TYPE_CVOID
116 C编程语言类型 - void
。JVMTI_TYPE_JNIENV
117 JNI环境 - JNIEnv
。应与正确的jvmtiParamKind
一起使用,使其成为指针类型。扩展函数/事件参数种类( jvmtiParamKind
)常量 值 描述 JVMTI_KIND_IN
91 传入参数 - foo
。JVMTI_KIND_IN_PTR
92 传入指针参数 - const foo*
。JVMTI_KIND_IN_BUF
93 传入数组参数 - const foo*
。JVMTI_KIND_ALLOC_BUF
94 输出分配的数组参数 - foo**
。使用Deallocate
释放。JVMTI_KIND_ALLOC_ALLOC_BUF
95 输出分配的数组的分配数组参数 - foo***
。使用Deallocate
释放。JVMTI_KIND_OUT
96 输出参数 - foo*
。JVMTI_KIND_OUT_BUF
97 输出数组参数(由代理预先分配) - foo*
。不要Deallocate
。扩展函数/事件参数信息
typedef struct { char* 名称; jvmtiParamKind 种类; jvmtiParamTypes 基本类型; jboolean 可空; } jvmtiParamInfo;
jvmtiParamInfo
- 扩展函数/事件参数信息字段 类型 描述 名称
char*
参数名称,编码为修改过的UTF-8字符串 种类
jvmtiParamKind
参数的种类 - 类型修饰符 基本类型
jvmtiParamTypes
参数的基本类型 - 被 kind
修改可空
jboolean
是否允许 NULL
参数?仅适用于指针和对象类型。
扩展函数
typedef jvmtiError (JNICALL *jvmtiExtensionFunction) (jvmtiEnv* jvmti_env, ...);
参数 名称 类型 描述 jvmti_env
jvmtiEnv *
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
- 扩展函数信息字段 类型 描述 func
jvmtiExtensionFunction
要调用的实际函数 id
char*
扩展函数的标识符,编码为修改过的UTF-8字符串。使用包名约定。例如, com.sun.hotspot.bar
short_description
char*
函数的一句话描述,编码为修改过的UTF-8字符串。 param_count
jint
参数数量,不包括 jvmtiEnv *jvmti_env
params
jvmtiParamInfo *
包含 param_count
个参数的数组(不包括jvmtiEnv *jvmti_env
)error_count
jint
可能的错误返回数量(不包括通用错误) errors
jvmtiError *
包含 error_count
个可能错误的数组错误 描述 JVMTI_ERROR_NULL_POINTER
extension_count_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
extensions
为NULL
。
获取扩展事件
typedef struct { jint extension_event_index; char* id; char* short_description; jint param_count; jvmtiParamInfo* params; } jvmtiExtensionEventInfo;
jvmtiError GetExtensionEvents(jvmtiEnv* env, jint* extension_count_ptr, jvmtiExtensionEventInfo** extensions)
jvmtiExtensionEventInfo
- 扩展事件信息字段 类型 描述 extension_event_index
jint
事件的标识索引 id
char*
扩展事件的标识符,编码为修改后的UTF-8字符串。使用包名约定。例如, com.sun.hotspot.bar
short_description
char*
事件的一句描述,编码为修改后的UTF-8字符串。 param_count
jint
参数数量,不包括 jvmtiEnv *jvmti_env
params
jvmtiParamInfo *
包含 param_count
个参数的数组(不包括jvmtiEnv *jvmti_env
)参数 名称 类型 描述 extension_count_ptr
jint*
返回扩展事件数量的指针 代理传递一个 jint
的指针。返回时,jint
已被设置。extensions
jvmtiExtensionEventInfo**
返回一个扩展事件信息数组,每个事件一个 代理传递一个 jvmtiExtensionEventInfo*
的指针。返回时,jvmtiExtensionEventInfo*
指向一个新分配的大小为*extension_count_ptr
的数组。数组应使用Deallocate
释放。在jvmtiExtensionEventInfo
的id
字段中返回的指针是新分配的数组。数组应使用Deallocate
释放。在jvmtiExtensionEventInfo
的short_description
字段中返回的指针是新分配的数组。数组应使用Deallocate
释放。在jvmtiExtensionEventInfo
的params
字段中返回的指针是新分配的数组。数组应使用Deallocate
释放。在jvmtiParamInfo
的name
字段中返回的指针是新分配的数组。数组应使用Deallocate
释放。错误 描述 JVMTI_ERROR_NULL_POINTER
extension_count_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
extensions
为NULL
。
扩展事件
typedef void (JNICALL *jvmtiExtensionEvent) (jvmtiEnv* jvmti_env, ...);
SetExtensionEventCallback
设置。 扩展事件的事件处理程序必须声明为可变参数以匹配此定义。否则可能导致在某些平台上调用约定不匹配和未定义行为。 例如,如果GetExtensionEvents
返回的jvmtiParamInfo
指示存在一个jint
参数,则事件处理程序应声明为:void JNICALL myHandler(jvmtiEnv* jvmti_env, ...)
...
"表示可变参数。在myHandler
内部需要使用C编程语言的va_*
语法提取jint
参数。参数 名称 类型 描述 jvmti_env
jvmtiEnv *
JVM TI环境是扩展事件的唯一固定参数。 ...
...
扩展事件特定的参数
设置扩展事件回调
jvmtiError SetExtensionEventCallback(jvmtiEnv* env, jint extension_event_index, jvmtiExtensionEvent callback)
NULL
,则禁用该事件。请注意,与标准事件不同,设置回调和启用事件是一个操作。参数 名称 类型 描述 extension_event_index
jint
标识要设置的回调。此索引是 extension_event_index
字段的jvmtiExtensionEventInfo
。callback
jvmtiExtensionEvent
如果 callback
不为NULL
,则将callback
设置为事件回调函数并启用事件。 如果callback
为NULL
,则禁用事件。错误 描述 JVMTI_ERROR_ILLEGAL_ARGUMENT
extension_event_index
不是extension_event_index
由GetExtensionEvents
返回的索引。
能力
能力函数: 能力类型:jvmtiCapabilities
- 能力结构
- 永远不会被添加
- 可以在OnLoad或任何环境中的live阶段添加
- 仅可在OnLoad阶段添加
- 一次只能由一个环境拥有
- 一次只能由一个环境拥有,并且仅在OnLoad阶段拥有
- 等等...
- 一个虚拟机可能通过将字节码编译成本机代码来执行所有操作,并且无法生成单步执行指令。在这种实现中,无法添加该功能。
- 另一个虚拟机可以随时将执行切换到单步执行解释器。在这种实现中,拥有该功能没有开销,可以随时添加。
- 另一个虚拟机可能能够在启动时选择字节码编译或单步执行能力的解释执行引擎,但无法在它们之间切换。在这种实现中,该功能需要在
OnLoad
阶段(在字节码执行开始之前)添加,并且即使从未使用单步执行,它也会对执行速度产生很大影响。 - 另一个虚拟机可能能够在编译的字节码或生成的解释器中添加“单步执行是否开启”的检查。同样,在这种实现中,该功能需要在
OnLoad
阶段添加,但开销(在每条指令上进行测试和分支)会大大减少。
OnLoad
阶段添加。对于大多数虚拟机,某些功能需要为虚拟机进行特殊设置,并且这些设置必须在虚拟机开始执行之前的OnLoad
阶段完成。一旦添加了功能,只有在环境明确放弃时才能移除它。 代理可以确定此VM可能提供的功能,添加要使用的功能,释放不再需要的功能,并检查当前可用的功能。功能示例
例如,一个刚启动的代理(在OnLoad
函数中)希望启用所有可能的功能。请注意,一般来说,这是不建议的,因为代理可能会因为未使用的功能而遭受性能损失。代码可能如下所示(使用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;
字段 描述 自 can_tag_objects
可以设置和获取标签,如在Heap类别中描述的。 1.0 can_generate_field_modification_events
可以在字段修改时设置监视点 - SetFieldModificationWatch
1.0 can_generate_field_access_events
可以在字段访问时设置监视点 - SetFieldAccessWatch
1.0 can_get_bytecodes
可以获取方法的字节码 GetBytecodes
1.0 can_get_synthetic_attribute
可以测试字段或方法是否是合成的 - IsFieldSynthetic
和IsMethodSynthetic
1.0 can_get_owned_monitor_info
可以获取有关监视器所有权的信息 - GetOwnedMonitorInfo
1.0 can_get_current_contended_monitor
可以 GetCurrentContendedMonitor
1.0 can_get_monitor_info
可以 GetObjectMonitorUsage
1.0 can_pop_frame
可以从堆栈中弹出帧 - PopFrame
1.0 can_redefine_classes
可以使用 RedefineClasses
重新定义类。1.0 can_signal_thread
可以向线程发送停止或中断信号 1.0 can_get_source_file_name
可以获取类的源文件名 1.0 can_get_line_numbers
可以获取方法的行号表 1.0 can_get_source_debug_extension
可以获取类的源调试扩展 1.0 can_access_local_variables
可以设置和获取局部变量 1.0 can_maintain_original_method_order
可以按照类文件中的顺序返回方法 1.0 can_generate_single_step_events
可以获取 单步 事件 1.0 can_generate_exception_events
可以获取 抛出异常 和 捕获异常 事件 1.0 can_generate_frame_pop_events
可以 设置 并获取 FramePop
事件1.0 can_generate_breakpoint_events
可以 设置 并获取 Breakpoint
事件1.0 can_suspend
可以暂停和恢复线程 1.0 can_redefine_any_class
RedefineClasses
可以在任何可修改的类上调用。参见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
可以获取具有堆栈深度的拥有监视器的信息 - GetOwnedMonitorStackDepthInfo
1.1 can_get_constant_pool
可以获取类的常量池 - GetConstantPool
1.1 can_set_native_method_prefix
可以设置在无法解析本地方法时应用的前缀 - SetNativeMethodPrefix
和SetNativeMethodPrefixes
1.1 can_retransform_classes
可以使用 RetransformClasses
重新转换类。除了特定实现对此功能施加的限制(请参阅 Capability 部分),此功能必须在此环境中首次启用ClassFileLoadHook
事件之前设置。在首次启用ClassFileLoadHook
时具有此功能的环境被称为 重新转换能力。在首次启用ClassFileLoadHook
时不具备此功能的环境被称为 重新转换无能。1.1 can_retransform_any_class
RetransformClasses
可以在任何可修改的类上调用。参见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_ptr
jvmtiCapabilities*
返回时,指向可能添加的JVM TI功能的指针。 代理传递一个指向 jvmtiCapabilities
的指针。返回时,jvmtiCapabilities
已被设置。错误 描述 JVMTI_ERROR_NULL_POINTER
capabilities_ptr
为NULL
。
添加功能
jvmtiError 添加功能(jvmtiEnv* env, const jvmtiCapabilities* capabilities_ptr)
*
capabilities_ptr
中将值设置为一(1
)来设置新功能。所有先前的功能都将保留。通常此函数在OnLoad
函数中使用。一些虚拟机可能允许在活动阶段添加有限的功能集。 参见功能示例。参数 名称 类型 描述 capabilities_ptr
const jvmtiCapabilities*
指向要添加的JVM TI功能的指针。 代理传递一个指向 jvmtiCapabilities
的指针。错误 描述 JVMTI_ERROR_NOT_AVAILABLE
所需功能甚至可能不可用。 JVMTI_ERROR_NULL_POINTER
capabilities_ptr
为NULL
。
放弃功能
jvmtiError 放弃功能(jvmtiEnv* env, const jvmtiCapabilities* capabilities_ptr)
*
capabilities_ptr
中将值设置为一(1
)来放弃功能。一些实现可能只允许一个环境拥有一个功能(参见功能介绍)。此函数释放功能,以便其他代理可以使用。所有其他功能都将保留。该功能将不再存在于GetCapabilities
中。尝试放弃代理不拥有的功能不会导致错误。参数 名称 类型 描述 capabilities_ptr
const jvmtiCapabilities*
指向要放弃的JVM TI功能的指针。 代理传递一个指向 jvmtiCapabilities
的指针。错误 描述 JVMTI_ERROR_NULL_POINTER
capabilities_ptr
为NULL
。
获取功能
jvmtiError 获取功能(jvmtiEnv* env, jvmtiCapabilities* capabilities_ptr)
capabilities_ptr
返回此环境当前拥有的可选JVM TI功能。每个拥有的功能在功能结构的相应字段中用一(1
)表示。除非使用AddCapabilities
成功添加,否则环境不拥有功能。只有通过RelinquishCapabilities
放弃功能后,环境才会失去功能的拥有权。因此,此函数返回已进行的AddCapabilities
和RelinquishCapabilities
调用的净结果。 参见功能示例。参数 名称 类型 描述 capabilities_ptr
jvmtiCapabilities*
返回时,指向JVM TI能力。 代理传递指向 jvmtiCapabilities
的指针。返回时,jvmtiCapabilities
已设置。错误 描述 JVMTI_ERROR_NULL_POINTER
capabilities_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_value
jlong
计时器可以达到的最大值。达到此值后,计时器将回到零。这是一个无符号值。如果作为jlong(有符号值)进行测试或打印,它可能看起来是一个负数。 may_skip_forward
jboolean
如果为true,则计时器可以被外部调整,从而向前跳过。如果为false,则计时器值永远不会比实时增加得更快。 may_skip_backward
jboolean
如果为true,则计时器可以被外部调整,从而向后跳过。如果为false,则计时器值将单调增加。 kind
jvmtiTimerKind
计时器的种类。在不区分用户和系统时间的平台上,返回 JVMTI_TIMER_TOTAL_CPU
。reserved1
jlong
保留供将来使用。 reserved2
jlong
保留供将来使用。 计时器种类( jvmtiTimerKind
)常量 值 描述 JVMTI_TIMER_USER_CPU
30 线程在用户模式下的CPU时间。 JVMTI_TIMER_TOTAL_CPU
31 线程在用户或系统模式下的CPU时间。 JVMTI_TIMER_ELAPSED
32 经过的时间。
获取当前线程CPU计时器信息
jvmtiError GetCurrentThreadCpuTimerInfo(jvmtiEnv* env, jvmtiTimerInfo* info_ptr)
GetCurrentThreadCpuTime
计时器的信息。填充jvmtiTimerInfo
结构的字段,其中包含有关计时器的详细信息。此信息特定于平台和GetCurrentThreadCpuTime
的实现,因此不会因线程或VM的特定调用而变化。 请注意,GetCurrentThreadCpuTime
和GetThreadCpuTime
的实现可能不同,因此GetCurrentThreadCpuTimerInfo
返回的值可能与GetThreadCpuTimerInfo
返回的值不同 -- 有关更多信息,请参阅GetCurrentThreadCpuTime
。能力 效果 can_get_current_thread_cpu_time
可以获取当前线程CPU时间。 参数 名称 类型 描述 info_ptr
jvmtiTimerInfo*
返回时,填充有关由 GetCurrentThreadCpuTime
返回的时间的信息。 代理传递指向jvmtiTimerInfo
的指针。返回时,jvmtiTimerInfo
已设置。错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备 can_get_current_thread_cpu_time
能力。使用AddCapabilities
。JVMTI_ERROR_NULL_POINTER
info_ptr
为NULL
。
获取当前线程CPU时间
jvmtiError GetCurrentThreadCpuTime(jvmtiEnv* env, jlong* nanos_ptr)
GetThreadCpuTime
函数为任何线程提供CPU时间,包括当前线程。GetCurrentThreadCpuTime
用于支持无法为除当前线程外的其他线程提供CPU时间或对当前线程具有更准确信息的平台(请参见GetCurrentThreadCpuTimerInfo
与GetThreadCpuTimerInfo
)。当当前线程是虚拟线程时,不需要支持此函数的实现,在这种情况下将返回JVMTI_ERROR_UNSUPPORTED_OPERATION
。在许多平台上,此调用将等效于:GetThreadCpuTime(env, NULL, nanos_ptr)
只能在启动或活动阶段调用1351.0能力 效果 can_get_current_thread_cpu_time
可以获取当前线程的CPU时间。 如果在线程启动后启用此功能,则实现可以选择任何时间,直到并包括启用功能的时间作为CPU时间收集开始的时间点。 此功能必须在任何可能支持 can_get_thread_cpu_time
的平台上潜在可用。参数 名称 类型 描述 nanos_ptr
jlong*
返回时,指向线程使用的CPU时间(以纳秒为单位)。这是一个无符号值。如果作为jlong(有符号值)进行测试或打印,它可能看起来是一个负数。 代理传递一个指向 的指针。返回时, 已设置。 错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_get_current_thread_cpu_time
。使用AddCapabilities
。JVMTI_ERROR_UNSUPPORTED_OPERATION
当前线程是虚拟线程,且实现不支持在当前线程为虚拟线程时获取当前线程的CPU时间。 JVMTI_ERROR_NULL_POINTER
nanos_ptr
为NULL
。
获取线程CPU计时器信息
jvmtiError GetThreadCpuTimerInfo(jvmtiEnv* env, jvmtiTimerInfo* info_ptr)
GetThreadCpuTime
计时器的信息。jvmtiTimerInfo
结构的字段将填充有关计时器的详细信息。此信息特定于平台和GetThreadCpuTime
的实现,因此不会因线程而异,也不会在VM的特定调用期间变化。 请注意,GetCurrentThreadCpuTime
和GetThreadCpuTime
的实现可能不同,因此GetCurrentThreadCpuTimerInfo
和GetThreadCpuTimerInfo
返回的值可能不同--请参见GetCurrentThreadCpuTime
获取更多信息。能力 效果 can_get_thread_cpu_time
可以获取线程CPU时间。 参数 名称 类型 描述 info_ptr
jvmtiTimerInfo*
返回时,填充有关 GetThreadCpuTime
返回的时间的信息。 代理传递一个指向的指针。返回时, 已设置。 错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备能力 can_get_thread_cpu_time
。使用AddCapabilities
。JVMTI_ERROR_NULL_POINTER
info_ptr
为NULL
。
获取线程CPU时间
jvmtiError GetThreadCpuTime(jvmtiEnv* env, jthread thread, jlong* nanos_ptr)
GetThreadCpuTimerInfo
获取有关此计时器的信息。能力 效果 can_get_thread_cpu_time
可以获取线程CPU时间。 如果在线程启动后启用此功能,则实现可以选择任何时间,直到并包括启用功能的时间作为CPU时间收集开始的时间。 参数 名称 类型 描述 线程
jthread
要查询的线程。当给定线程是虚拟线程时,实现不需要支持此功能,此时将返回 JVMTI_ERROR_UNSUPPORTED_OPERATION
。如果thread
为NULL
,则使用当前线程。nanos_ptr
jlong*
返回指定线程使用的CPU时间(以纳秒为单位)。这是一个无符号值。如果作为jlong(有符号值)进行测试或打印,它可能看起来是一个负数。 代理传递一个指向 jlong
的指针。返回时,jlong
已被设置。错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备 can_get_thread_cpu_time
能力。使用AddCapabilities
。JVMTI_ERROR_UNSUPPORTED_OPERATION
thread
是虚拟线程,且实现不支持获取虚拟线程的线程CPU时间。JVMTI_ERROR_INVALID_THREAD
thread
不是线程对象。JVMTI_ERROR_THREAD_NOT_ALIVE
thread
不活动(尚未启动或已终止)。JVMTI_ERROR_NULL_POINTER
nanos_ptr
为NULL
。
获取计时器信息
jvmtiError GetTimerInfo(jvmtiEnv* env, jvmtiTimerInfo* info_ptr)
GetTime
计时器的信息。jvmtiTimerInfo
结构的字段将填充有关计时器的详细信息。此信息在VM的特定调用期间不会更改。可在任何阶段调用1381.0参数 名称 类型 描述 info_ptr
jvmtiTimerInfo*
返回时,填充有关 GetTime
返回的时间的信息。 代理传递一个指向jvmtiTimerInfo
的指针。返回时,jvmtiTimerInfo
已被设置。错误 描述 JVMTI_ERROR_NULL_POINTER
info_ptr
为NULL
。
获取时间
jvmtiError GetTime(jvmtiEnv* env, jlong* nanos_ptr)
GetTimerInfo
获取有关此计时器的信息。可在任何阶段调用1391.0参数 名称 类型 描述 nanos_ptr
jlong*
返回时,指向纳秒时间的指针。这是一个无符号值。如果作为jlong(有符号值)进行测试或打印,它可能看起来是一个负数。 代理传递一个指向 jlong
的指针。返回时,jlong
已被设置。错误 描述 JVMTI_ERROR_NULL_POINTER
nanos_ptr
为NULL
。
获取可用处理器数
jvmtiError GetAvailableProcessors(jvmtiEnv* env, jint* processor_count_ptr)
参数 名称 类型 描述 processor_count_ptr
jint*
返回时,指向虚拟机可用的处理器数量的最大值;永远不会小于一。 代理传递一个指向 jint
的指针。返回时,jint
已被设置。错误 描述 JVMTI_ERROR_NULL_POINTER
processor_count_ptr
为NULL
。
类加载器搜索
类加载器搜索函数: 这些函数允许代理程序添加类加载器搜索类的位置。这对于在正确的类加载器下安装仪器很有用。
添加到引导类加载器搜索
jvmtiError AddToBootstrapClassLoaderSearch(jvmtiEnv* env, const char* segment)
segment
。只能在segment
中指定一个段。可以多次调用此函数以添加多个段,这些段将按照调用此函数的顺序进行搜索。 在OnLoad
阶段,此函数可用于指定在引导类加载器未成功搜索类之后要搜索的任何平台相关搜索路径段。该段通常是目录或JAR文件。 在实时阶段,segment
可用于指定任何平台相关路径到 JAR文件。代理程序应注意,JAR文件不应包含任何除了为仪器目的而由引导类加载器定义的类或资源之外的内容。 Java™虚拟机规范 指定,对先前未能成功解析的符号引用进行后续尝试始终会以与初始解析尝试导致的错误相同的错误失败。因此,如果JAR文件包含与Java虚拟机先前未能成功解析引用相对应的条目,则后续尝试解析该引用将以与初始尝试相同的错误失败。参数 名称 类型 描述 segment
const char*
平台相关的搜索路径段,编码为修改的UTF-8字符串。 代理程序传入一个 char
数组。错误 描述 JVMTI_ERROR_ILLEGAL_ARGUMENT
segment
是无效路径。在实时阶段,除了现有的JAR文件之外的任何内容都是无效路径。JVMTI_ERROR_NULL_POINTER
segment
为NULL
。
添加到系统类加载器搜索
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_ARGUMENT
segment
是无效路径。在实时阶段,除了现有的JAR文件之外的任何内容都是无效路径。JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED
系统类加载器不支持此操作。 JVMTI_ERROR_NULL_POINTER
segment
为NULL
。
系统属性
系统属性函数: 这些函数获取和设置系统属性。
获取系统属性
jvmtiError GetSystemProperties(jvmtiEnv* env, jint* count_ptr, char*** property_ptr)
GetSystemProperty
被返回。强烈建议虚拟机提供以下属性键:java.vm.vendor
java.vm.version
java.vm.name
java.vm.info
java.library.path
java.class.path
java.lang.System.getProperties
中的属性集不同。JNI方法调用可用于访问java.lang.System.getProperties
。 属性集在执行过程中可能会增长。参数 名称 类型 描述 count_ptr
jint*
返回时,指向返回的属性键数。 代理传递一个指向 jint
的指针。返回时,jint
已设置。property_ptr
char***
返回时,指向以 修改的UTF-8 字符串编码的属性键数组。 代理传递一个指向 char**
的指针。返回时,char**
指向一个新分配的大小为*count_ptr
的数组,其中每个元素也是新分配的。应使用Deallocate
释放数组。每个元素应使用Deallocate
释放。错误 描述 JVMTI_ERROR_NULL_POINTER
count_ptr
为NULL
。JVMTI_ERROR_NULL_POINTER
property_ptr
为NULL
。
获取系统属性
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
数组。参数 名称 类型 描述 property
const char*
value_ptr
char**
返回时,指向属性值,编码为 修改的UTF-8 字符串。 代理传递一个指向 char*
的指针。返回时,char*
指向一个新分配的数组。应使用Deallocate
释放数组。GetSystemProperties
查找可用属性。错误 描述 JVMTI_ERROR_NOT_AVAILABLE
JVMTI_ERROR_NULL_POINTER
property
为NULL
。JVMTI_ERROR_NULL_POINTER
value_ptr
为NULL
。
设置系统属性
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
。参数 名称 类型 描述 property
const char*
value_ptr
const char *
错误 描述 JVMTI_ERROR_NOT_AVAILABLE
JVMTI_ERROR_NULL_POINTER
property
为NULL
。
通用
通用函数: 通用类型:jvmtiPhase
- 执行阶段jvmtiVerboseFlag
- 详细标志枚举jvmtiJlocationFormat
- JLocation格式枚举
获取阶段
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)
执行阶段 ( jvmtiPhase
)常量 值 描述 JVMTI_PHASE_ONLOAD
1 OnLoad
阶段: 在Agent_OnLoad
或者对于静态链接的代理,在Agent_OnLoad_<agent-lib-name>
函数中。JVMTI_PHASE_PRIMORDIAL
2 原始阶段: 在 Agent_OnLoad
或者Agent_OnLoad_<agent-lib-name>
返回后,以及VMStart
事件之前。JVMTI_PHASE_START
6 开始阶段: 当发送 VMStart
事件时,直到发送VMInit
事件为止。JVMTI_PHASE_LIVE
4 活动阶段: 当发送 VMInit
事件时,直到VMDeath
事件返回为止。JVMTI_PHASE_DEAD
8 死亡阶段: 在 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_ptr
jvmtiPhase*
返回时,指向阶段。 代理传递指向 jvmtiPhase
的指针。返回时,jvmtiPhase
已设置。错误 描述 JVMTI_ERROR_NULL_POINTER
phase_ptr
为NULL
。
释放环境
jvmtiError DisposeEnvironment(jvmtiEnv* env)
GetEnv
(参见JVM TI环境)。释放环境持有的任何资源。此环境挂起的线程不会在此调用中恢复,代理必须显式地执行此操作。通过此环境调用JVM分配的内存不会被释放,代理可以通过调用Deallocate
来显式释放。通过此环境创建的原始监视器不会被销毁,代理可以通过调用DestroyRawMonitor
来显式销毁。等待此环境创建的原始监视器的线程状态不受影响。 此环境的任何本地方法前缀将被取消设置;代理必须在调用dispose之前删除任何带前缀的本地方法。 此环境持有的任何功能将被放弃。 由此环境启用的事件将不再发送,但当前正在运行的事件处理程序将继续运行。在设计事件处理程序时必须谨慎,因为它们的环境可能在执行过程中被释放,从而变得无效。 此调用后不得再使用此环境。此调用返回给调用者。
设置环境本地存储
jvmtiError SetEnvironmentLocalStorage(jvmtiEnv* env, const void* data)
NULL
。代理可以分配内存来存储特定于环境的信息。通过设置环境本地存储,可以使用GetEnvironmentLocalStorage
来访问它。 代理调用此函数来设置JVM TI环境本地存储的值。JVM TI向代理提供一个指针大小的环境本地存储,可用于记录每个环境的信息。可在任何阶段调用1481.0参数 名称 类型 描述 data
const void *
要输入到环境本地存储中的值。 代理传入一个指针。如果 data
为NULL
,则值设置为NULL
。
获取环境本地存储
jvmtiError GetEnvironmentLocalStorage(jvmtiEnv* env, void** data_ptr)
可在任何阶段调用1471.0参数 名称 类型 描述 data_ptr
void**
用于返回环境本地存储值的指针。如果未使用 SetEnvironmentLocalStorage
设置环境本地存储,则返回的指针为NULL
。错误 描述 JVMTI_ERROR_NULL_POINTER
data_ptr
为NULL
。
获取版本号
jvmtiError GetVersionNumber(jvmtiEnv* env, jint* version_ptr)
version_ptr
返回JVM TI版本。返回值是版本标识符。版本标识符包括主要、次要和微版本号以及接口类型。版本接口类型 常量 值 描述 JVMTI_VERSION_INTERFACE_JNI
0x00000000 JVMTI_VERSION_MASK_INTERFACE_TYPE
用于JNI的值。JVMTI_VERSION_INTERFACE_JVMTI
0x30000000 JVMTI_VERSION_MASK_INTERFACE_TYPE
用于JVM TI的值。版本掩码 常量 值 描述 JVMTI_VERSION_MASK_INTERFACE_TYPE
0x70000000 用于提取接口类型的掩码。此函数返回的版本值与 JVMTI_VERSION_MASK_INTERFACE_TYPE
掩码相与的值始终为JVMTI_VERSION_INTERFACE_JVMTI
,因为这是一个JVM TI函数。JVMTI_VERSION_MASK_MAJOR
0x0FFF0000 用于提取主要版本号的掩码。 JVMTI_VERSION_MASK_MINOR
0x0000FF00 用于提取次要版本号的掩码。 JVMTI_VERSION_MASK_MICRO
0x000000FF 用于提取微版本号的掩码。 版本转换 常量 数值 描述 JVMTI_VERSION_SHIFT_MAJOR
16 用于提取主版本号。 JVMTI_VERSION_SHIFT_MINOR
8 用于提取次版本号。 JVMTI_VERSION_SHIFT_MICRO
0 用于提取微版本号。 参数 名称 类型 描述 version_ptr
jint*
返回时,指向JVM TI版本的指针。 代理传递一个指向 jint
的指针。 返回时,jint
已被设置。错误 描述 JVMTI_ERROR_NULL_POINTER
version_ptr
为NULL
。
获取错误名称
jvmtiError GetErrorName(jvmtiEnv* env, jvmtiError error, char** name_ptr)
GetErrorName(env, JVMTI_ERROR_NONE, &err_name)
将在err_name
中返回字符串"JVMTI_ERROR_NONE"
。参数 名称 类型 描述 error
jvmtiError
错误代码。 name_ptr
char**
返回时,指向错误名称。 名称被编码为修改的UTF-8字符串,但限制为ASCII子集。 代理传递一个指向 char*
的指针。 返回时,char*
指向一个新分配的数组。 应使用Deallocate
释放数组。错误 描述 JVMTI_ERROR_ILLEGAL_ARGUMENT
error
不是jvmtiError。JVMTI_ERROR_NULL_POINTER
name_ptr
为NULL
。
设置详细标志
typedef enum { JVMTI_VERBOSE_OTHER = 0, JVMTI_VERBOSE_GC = 1, JVMTI_VERBOSE_CLASS = 2, JVMTI_VERBOSE_JNI = 4 } jvmtiVerboseFlag;
jvmtiError SetVerboseFlag(jvmtiEnv* env, jvmtiVerboseFlag flag, jboolean value)
详细标志枚举( jvmtiVerboseFlag
)常量 数值 描述 JVMTI_VERBOSE_OTHER
0 除以下内容之外的详细输出。 JVMTI_VERBOSE_GC
1 详细的垃圾收集器输出,类似于使用 -verbose:gc
指定的内容。JVMTI_VERBOSE_CLASS
2 详细的类加载输出,类似于使用 -verbose:class
指定的内容。JVMTI_VERBOSE_JNI
4 详细的JNI输出,类似于使用 -verbose:jni
指定的内容。stderr
的输出。参数 名称 类型 描述 flag
jvmtiVerboseFlag
要设置的详细标志。 value
jboolean
标志的新值。 错误 描述 JVMTI_ERROR_ILLEGAL_ARGUMENT
flag
不是jvmtiVerboseFlag。
获取JLocation格式
typedef enum { JVMTI_JLOCATION_JVMBCI = 1, JVMTI_JLOCATION_MACHINEPC = 2, JVMTI_JLOCATION_OTHER = 0 } jvmtiJlocationFormat;
jvmtiError GetJLocationFormat(jvmtiEnv* env, jvmtiJlocationFormat* format_ptr)
jlocation
的定义被故意保留为不受限制的,以允许没有此信息的VM实现。 此函数描述了在此VM中使用的jlocation
的表示形式。 如果返回的格式是JVMTI_JLOCATION_JVMBCI
,则jlocation
可以用作对GetBytecodes
返回的数组中的索引。JLocation 格式枚举( jvmtiJlocationFormat
)常量 值 描述 JVMTI_JLOCATION_JVMBCI
1 jlocation
值表示虚拟机字节码索引--即方法的虚拟机代码偏移量。JVMTI_JLOCATION_MACHINEPC
2 jlocation
值表示本机机器程序计数器值。JVMTI_JLOCATION_OTHER
0 jlocation
值具有其他表示。参数 名称 类型 描述 format_ptr
jvmtiJlocationFormat*
返回时,指向 jlocation
值的格式标识符。 代理传递一个指向jvmtiJlocationFormat
的指针。返回时,jvmtiJlocationFormat
已设置。错误 描述 JVMTI_ERROR_NULL_POINTER
format_ptr
为NULL
。
堆监控
堆监控函数:
设置堆采样间隔
jvmtiError SetHeapSamplingInterval(jvmtiEnv* env, jint sampling_interval)
SampledObjectAlloc
事件。每个线程保留一个已分配字节的计数器。仅当该计数器超过自上次采样以来的平均sampling_interval
时,才会生成事件。 将sampling_interval
设置为 0 将导致每次分配都会生成一个事件,一旦新间隔生效。 请注意,更新新的采样间隔可能需要各种分配次数来引发内部数据结构的更新。因此,重要的是将采样间隔视为平均值。这包括间隔为 0 的情况,即事件可能不会立即为每次分配生成。能力 效果 can_generate_sampled_object_alloc_events
可以生成采样分配事件。如果启用了此功能,则可以调用堆采样方法 SetHeapSamplingInterval
并生成SampledObjectAlloc
事件。参数 名称 类型 描述 sampling_interval
jint
以字节为单位的采样间隔。采样器使用统计方法,平均每个给定线程分配的内存字节数为 sampling_interval
时生成一个事件。 一旦考虑了新的采样间隔,将 0 作为采样间隔将为每次分配生成一个样本。 注意:此功能的开销与采样间隔直接相关。较高的采样间隔,例如 1024 字节,将产生较高的开销。较低的间隔,例如 1024KB,将具有较低的开销。采样应仅在了解可能影响性能的情况下使用。错误 描述 JVMTI_ERROR_MUST_POSSESS_CAPABILITY
环境不具备 can_generate_sampled_object_alloc_events
能力。请使用AddCapabilities
。JVMTI_ERROR_ILLEGAL_ARGUMENT
sampling_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类型 类型 描述 jboolean
jchar
jint
jlong
jfloat
jdouble
jobject
jclass
jvalue
jfieldID
jmethodID
JNIEnv
JVM工具接口基本类型 类型 描述 jvmtiEnv
jthread
jobject
的子类型,保存线程。typedef jobject jthread;
jthreadGroup
jobject
的子类型,保存线程组。typedef jobject jthreadGroup;
jlocation
typedef jlong jlocation;
jrawMonitorID
struct _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
用于事件的回调。typedef struct { jvmtiEventVMInit VMInit; jvmtiEventVMDeath VMDeath; ... } jvmtiEventCallbacks;
typedef void (JNICALL *jvmtiEventVMInit) (jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread);
jniNativeInterface
typedef struct JNINativeInterface_ jniNativeInterface;
结构类型定义 类型 描述 jvmtiAddrLocationMap
本机地址到位置条目 jvmtiCapabilities
功能结构 jvmtiClassDefinition
类重定义描述 jvmtiExtensionEventInfo
扩展事件信息 jvmtiExtensionFunctionInfo
扩展函数信息 jvmtiFrameInfo
堆栈帧信息结构 jvmtiHeapCallbacks
堆回调函数结构 jvmtiHeapReferenceInfo
引用信息结构 jvmtiHeapReferenceInfoArray
数组引用信息结构 jvmtiHeapReferenceInfoConstantPool
常量池引用信息结构 jvmtiHeapReferenceInfoField
字段引用信息结构 jvmtiHeapReferenceInfoJniLocal
JNI本地引用信息结构 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
迭代控制枚举 jvmtiJlocationFormat
JLocation格式枚举 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
时设置断点,该断点将在线程移动到当前位置之前报告。 以下事件永远不被视为与其他事件共同位置。VMStart
VMInit
VMDeath
ThreadStart
ThreadEnd
VirtualThreadStart
VirtualThreadEnd
ClassLoad
ClassPrepare
事件回调
下面的事件回调结构用于指定事件的处理程序函数。它使用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 启动事件
单步
void JNICALL SingleStep(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method, jlocation location)
method
和location
参数唯一标识当前位置,并在可用时允许将其映射到源文件和行号。 Java™虚拟机规范。没有单步事件会从本地方法内部生成。 单步事件不会从本地方法内部生成。能力 效果 can_generate_single_step_events
可以获取单步事件 参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境 thread
jthread
即将执行新指令的线程 method
jmethodID
即将执行新指令的方法 location
jlocation
新指令的位置
断点
void JNICALL Breakpoint(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method, jlocation location)
SetBreakpoint
。能力 效果 can_generate_breakpoint_events
可以设置并获取 Breakpoint
事件参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境。 thread
jthread
触发断点的线程 method
jmethodID
触发断点的方法 location
jlocation
断点的位置
字段访问
void JNICALL FieldAccess(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method, jlocation location, jclass field_klass, jobject object, jfieldID field)
SetFieldAccessWatch
。能力 效果 can_generate_field_access_events
可以在字段访问上设置观察点 - SetFieldAccessWatch
参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境 thread
jthread
访问字段的线程 method
jmethodID
发生访问的方法 location
jlocation
发生访问的位置 field_klass
jclass
被访问字段的类 object
jobject
访问字段的对象(如果字段是实例字段);否则为 NULL
field
jfieldID
被访问的字段
字段修改
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
。方法
和位置
参数唯一标识当前位置,并在可用时允许将其映射到源文件和行号。能力 效果 can_generate_field_modification_events
可以在字段修改上设置监视点 - SetFieldModificationWatch
参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境 thread
jthread
修改字段的线程 method
jmethodID
发生修改的方法 location
jlocation
发生修改的位置 field_klass
jclass
正在修改的字段的类 object
jobject
如果字段是实例字段,则具有被修改字段的对象;否则为 NULL
field
jfieldID
正在修改的字段 signature_type
char
新值的签名类型 new_value
jvalue
新值
帧弹出
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的位置标识返回方法中的可执行位置,即在返回之前。能力 效果 can_generate_frame_pop_events
可以设置并因此获取 FramePop
事件参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境 thread
jthread
弹出帧的线程 method
jmethodID
正在弹出的方法 was_popped_by_exception
jboolean
如果帧是由抛出的异常弹出的,则为真。如果方法通过其返回指令退出,则为假。
方法进入
void JNICALL MethodEntry(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jmethodID method)
GetFrameLocation
报告的深度为0的位置标识方法中的初始可执行位置。 启用方法进入或退出事件将显著降低许多平台的性能,因此不建议用于性能关键的用途(如性能分析)。 字节码插装应在这些情况下使用。能力 效果 can_generate_method_entry_events
可以在进入方法时生成方法进入事件 参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境 thread
jthread
进入方法的线程 method
jmethodID
正在进入的方法
方法退出
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的位置标识着在返回方法中的可执行位置,即在返回之前。 启用方法进入或退出事件将严重降低许多平台的性能,因此不建议在对性能至关重要的用途(如分析)中使用。 字节码插装应在这些情况下使用。能力 效果 can_generate_method_exit_events
可以在退出方法时生成方法退出事件 参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境 thread
jthread
退出方法的线程 method
jmethodID
正在退出的方法 was_popped_by_exception
jboolean
如果帧是由抛出的异常弹出的,则为真。如果方法通过其返回指令退出,则为假。 return_value
jvalue
正在退出的方法的返回值。如果 was_popped_by_exception
为真,则未定义且不应使用。
本地方法绑定
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,但可以保存方法和地址以供以后使用。能力 效果 can_generate_native_method_bind_events
可以在将本地方法绑定到其实现时生成事件 参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境。如果在原始阶段发送,则为 NULL
。thread
jthread
请求绑定的线程 method
jmethodID
正在绑定的本地方法 address
void*
虚拟机即将绑定到的地址,即本地方法实现的地址 new_address_ptr
void**
如果引用的地址更改(即设置了 *new_address_ptr
),则绑定将改为绑定到提供的地址。
异常
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位置报告。能力 效果 can_generate_exception_events
可以获取抛出异常和捕获异常事件 参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境 thread
jthread
生成异常的线程 method
jmethodID
生成异常的方法 location
jlocation
异常发生的位置 exception
jobject
正在抛出的异常 catch_method
jmethodID
将捕获异常的方法,如果没有已知的捕获则为 NULL
catch_location
jlocation
将捕获异常的位置,如果没有已知的捕获则为零
异常捕获
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
。能力 效果 can_generate_exception_events
可以获取抛出异常和异常捕获事件 参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境 thread
jthread
捕获异常的线程 method
jmethodID
捕获异常的方法 location
jlocation
正在捕获异常的位置 exception
jobject
正在捕获的异常
线程启动
void JNICALL ThreadStart(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread)
can_support_virtual_threads
能力的代理可以启用VirtualThreadStart
事件,以便被新启动的虚拟线程通知。 平台线程可能在其线程启动事件生成之前在由GetAllThreads
返回的数组中列出。在生成线程启动事件之前,可能会为线程生成其他事件。 事件发送到新启动的thread
。参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境。 thread
jthread
正在启动的线程
线程结束
void JNICALL ThreadEnd(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread)
can_support_virtual_threads
能力的代理可以启用VirtualThreadEnd
事件,以便被终止的虚拟线程通知。 平台线程可能在其线程结束事件生成后在由GetAllThreads
返回的数组中列出。在线程结束事件生成后,不会在线程上生成任何事件。 事件发送到正在终止的thread
。参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境。 thread
jthread
结束的线程
虚拟线程启动
void JNICALL VirtualThreadStart(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread virtual_thread)
virtual_thread
。能力 效果 can_support_virtual_threads
可以支持虚拟线程 参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境。 virtual_thread
jthread
用于执行的虚拟线程。
虚拟线程结束
void JNICALL VirtualThreadEnd(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread virtual_thread)
virtual_thread
。能力 效果 can_support_virtual_threads
可以支持虚拟线程 参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境。 virtual_thread
jthread
正在结束的虚拟线程。
类加载
void JNICALL ClassLoad(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jclass klass)
ClassPrepare
事件将更有用。参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境 thread
jthread
加载类的线程 klass
jclass
正在加载的类
类准备
void JNICALL ClassPrepare(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jclass klass)
java.lang.Integer.TYPE
)不会生成类准备事件。参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境 thread
jthread
生成类准备的线程 klass
jclass
正在准备的类
类文件加载钩子
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_env
JNIEnv *
事件(当前)线程的JNI环境。 class_being_redefined
jclass
正在 重新定义 或 重新转换 的类。如果由类加载发送,则为 NULL
。loader
jobject
加载类的类加载器。如果是引导类加载器,则为 NULL
。name
const char*
作为VM内部限定名称加载的类的名称(例如,“java/util/List”),编码为 修改的UTF-8 字符串。注意:如果类以 NULL
名称定义或未指定名称,则name
将为NULL
。protection_domain
jobject
类的 ProtectionDomain
。class_data_len
jint
当前类文件数据缓冲区的长度。 class_data
const unsigned char*
指向当前类文件数据缓冲区的指针。 new_class_data_len
jint*
指向新类文件数据缓冲区的长度的指针。 new_class_data
unsigned char**
指向仪表化类文件数据缓冲区的指针。
虚拟机启动事件
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_env
JNIEnv *
事件(当前)线程的JNI环境。
VM 初始化事件
void JNICALL VMInit(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread)
参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境。 thread
jthread
初始线程
VM 死亡事件
void JNICALL VMDeath(jvmtiEnv *jvmti_env, JNIEnv* jni_env)
参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境
已编译方法加载
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_address
const void*
与位置对应的代码的起始本机地址 location
jlocation
对应的位置。有关位置含义,请参阅 GetJLocationFormat
。能力 效果 can_generate_compiled_method_load_events
可以在方法编译或卸载时生成事件 参数 名称 类型 描述 method
jmethodID
正在编译和加载的方法 code_size
jint
编译代码的大小 code_addr
const void*
编译方法代码加载的地址 map_length
jint
地址映射中的 jvmtiAddrLocationMap
条目数。如果无法提供映射信息,则为零。map
const jvmtiAddrLocationMap*
从本机地址到位置的映射。每个条目的本机地址范围从 start_address
到下一个条目的start_address-1
。如果无法提供映射信息,则为NULL
。compile_info
const void*
VM特定的编译信息。引用的编译信息由VM管理,不得依赖代理程序进行收集。VM实现定义信息的内容和生命周期。
编译方法卸载
void JNICALL CompiledMethodUnload(jvmtiEnv *jvmti_env, jmethodID method, const void* code_addr)
能力 效果 can_generate_compiled_method_load_events
可以在方法编译或卸载时生成事件 参数 名称 类型 描述 method
jmethodID
正在卸载的编译方法。仅用于标识编译方法 -- 类可能已被卸载,因此不应将方法用作进一步JNI或JVM TI函数的参数。 code_addr
const void*
编译方法代码加载的地址。仅用于标识编译方法 -- 空间可能已被回收。
动态生成的代码
void JNICALL DynamicCodeGenerated(jvmtiEnv *jvmti_env, const char* name, const void* address, jint length)
CompiledMethodLoad
。这是用于本机代码--例如,根据命令行选项生成不同的解释器。 请注意,此事件没有控制能力。如果VM无法生成这些事件,则不会发送任何事件。 这些事件可以在初始发生后使用GenerateEvents
再次发送。参数 名称 类型 描述 name
const char*
代码的名称,编码为修改的UTF-8字符串。用于向最终用户显示。名称可能不是唯一的。 address
const void*
代码的本机地址 length
jint
代码的字节长度
数据转储请求
void JNICALL DataDumpRequest(jvmtiEnv *jvmti_env)
争用监视器进入
void JNICALL MonitorContendedEnter(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jobject object)
能力 效果 can_generate_monitor_events
可以在监视器活动上生成事件 参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境 thread
jthread
尝试进入监视器的线程的JNI本地引用 object
jobject
监视器的JNI本地引用
监视器争用进入
void JNICALL MonitorContendedEntered(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jobject object)
能力 效果 can_generate_monitor_events
可以在监视器活动上生成事件 参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境 thread
jthread
完成等待进入监视器的线程的JNI本地引用 object
jobject
监视器的JNI本地引用
监视器等待
void JNICALL MonitorWait(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jobject object, jlong timeout)
能力 效果 can_generate_monitor_events
可以在监视器活动上生成事件 参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境 thread
jthread
即将等待的线程的JNI本地引用 object
jobject
监视器的JNI本地引用 timeout
jlong
线程将等待的毫秒数
监视器等待完成
void JNICALL MonitorWaited(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jobject object, jboolean timed_out)
能力 效果 can_generate_monitor_events
可以在监视器活动上生成事件 参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境 thread
jthread
完成等待的线程的JNI本地引用 object
jobject
监视器的JNI本地引用 timed_out
jboolean
如果监视器超时则为真
资源耗尽
void JNICALL ResourceExhausted(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jint flags, const void* reserved, const char* description)
资源耗尽标志 常量 值 描述 JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR
0x0001 此事件返回后,虚拟机将抛出一个 java.lang.OutOfMemoryError
。JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP
0x0002 虚拟机无法从JavaTM平台的堆中分配内存。 堆是运行时数据区,用于为所有类实例和数组分配内存。 JVMTI_RESOURCE_EXHAUSTED_THREADS
0x0004 虚拟机无法创建线程。 可选特性 能力 效果 can_generate_resource_exhaustion_heap_events
当虚拟机无法从堆中分配内存时,可以生成事件。 can_generate_resource_exhaustion_threads_events
当虚拟机无法创建线程时,可以生成事件。 参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境 flags
jint
由资源耗尽标志指定的资源耗尽属性的标志。 reserved
const void*
保留。 description
const char*
资源耗尽的描述,编码为修改的UTF-8字符串。
虚拟机对象分配
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
- 虚拟机初始化期间的分配
- 虚拟机内部对象
能力 效果 can_generate_vm_object_alloc_events
可以生成对象的虚拟机分配事件 参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境 thread
jthread
分配对象的线程。 object
jobject
分配的对象的JNI本地引用。 object_klass
jclass
对象的类的JNI本地引用。 size
jlong
对象的大小(以字节为单位)。请参阅 GetObjectSize
。
采样对象分配
void JNICALL SampledObjectAlloc(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jobject object, jclass object_klass, jlong size)
SetHeapSamplingInterval
,并提供严格正整数值,表示新的采样间隔。 一旦执行了采样分配,将发送此事件。它提供了对象、分配的堆栈跟踪、分配对象的线程、分配的大小和对象的类。 此系统的典型用例是确定堆分配的来源。结合弱引用和函数GetStackTrace
,用户可以跟踪哪些对象是从哪个堆栈跟踪分配的,哪些对象在程序执行期间仍然存活。能力 效果 can_generate_sampled_object_alloc_events
可以生成采样分配事件。如果启用了此能力,则可以调用堆采样方法 SetHeapSamplingInterval
,并生成SampledObjectAlloc
事件。参数 名称 类型 描述 jni_env
JNIEnv *
事件(当前)线程的JNI环境。 thread
jthread
分配对象的线程。 object
jobject
分配的对象的JNI本地引用。 object_klass
jclass
对象的类的JNI本地引用 size
jlong
对象的大小(以字节为单位)。请参阅 GetObjectSize
。
对象释放
void JNICALL ObjectFree(jvmtiEnv *jvmti_env, jlong tag)
能力 效果 can_generate_object_free_events
可以在垃圾收集器释放对象时生成事件 参数 名称 类型 描述 tag
jlong
被释放对象的标记
垃圾收集开始
void JNICALL GarbageCollectionStart(jvmtiEnv *jvmti_env)
GarbageCollectionFinish
(假设两个事件都已启用),并且它们之间不会发生垃圾收集事件。能力 效果 can_generate_garbage_collection_events
可以在垃圾收集开始或结束时生成事件
垃圾收集完成
void JNICALL GarbageCollectionFinish(jvmtiEnv *jvmti_env)
GarbageCollectionStart
(假设两个事件都已启用)。能力 效果 can_generate_garbage_collection_events
可以在垃圾回收开始或结束时生成事件
常量索引
JVMTI_CLASS_STATUS_ARRAY
JVMTI_CLASS_STATUS_ERROR
JVMTI_CLASS_STATUS_INITIALIZED
JVMTI_CLASS_STATUS_PREPARED
JVMTI_CLASS_STATUS_PRIMITIVE
JVMTI_CLASS_STATUS_VERIFIED
JVMTI_DISABLE
JVMTI_ENABLE
JVMTI_HEAP_FILTER_CLASS_TAGGED
JVMTI_HEAP_FILTER_CLASS_UNTAGGED
JVMTI_HEAP_FILTER_TAGGED
JVMTI_HEAP_FILTER_UNTAGGED
JVMTI_HEAP_OBJECT_EITHER
JVMTI_HEAP_OBJECT_TAGGED
JVMTI_HEAP_OBJECT_UNTAGGED
JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT
JVMTI_HEAP_REFERENCE_CLASS
JVMTI_HEAP_REFERENCE_CLASS_LOADER
JVMTI_HEAP_REFERENCE_CONSTANT_POOL
JVMTI_HEAP_REFERENCE_FIELD
JVMTI_HEAP_REFERENCE_INTERFACE
JVMTI_HEAP_REFERENCE_JNI_GLOBAL
JVMTI_HEAP_REFERENCE_JNI_LOCAL
JVMTI_HEAP_REFERENCE_MONITOR
JVMTI_HEAP_REFERENCE_OTHER
JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN
JVMTI_HEAP_REFERENCE_SIGNERS
JVMTI_HEAP_REFERENCE_STACK_LOCAL
JVMTI_HEAP_REFERENCE_STATIC_FIELD
JVMTI_HEAP_REFERENCE_SUPERCLASS
JVMTI_HEAP_REFERENCE_SYSTEM_CLASS
JVMTI_HEAP_REFERENCE_THREAD
JVMTI_HEAP_ROOT_JNI_GLOBAL
JVMTI_HEAP_ROOT_JNI_LOCAL
JVMTI_HEAP_ROOT_MONITOR
JVMTI_HEAP_ROOT_OTHER
JVMTI_HEAP_ROOT_STACK_LOCAL
JVMTI_HEAP_ROOT_SYSTEM_CLASS
JVMTI_HEAP_ROOT_THREAD
JVMTI_ITERATION_ABORT
JVMTI_ITERATION_CONTINUE
JVMTI_ITERATION_IGNORE
JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED
JVMTI_JAVA_LANG_THREAD_STATE_MASK
JVMTI_JAVA_LANG_THREAD_STATE_NEW
JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE
JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED
JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING
JVMTI_JAVA_LANG_THREAD_STATE_WAITING
JVMTI_JLOCATION_JVMBCI
JVMTI_JLOCATION_MACHINEPC
JVMTI_JLOCATION_OTHER
JVMTI_KIND_ALLOC_ALLOC_BUF
JVMTI_KIND_ALLOC_BUF
JVMTI_KIND_IN
JVMTI_KIND_IN_BUF
JVMTI_KIND_IN_PTR
JVMTI_KIND_OUT
JVMTI_KIND_OUT_BUF
JVMTI_PHASE_DEAD
JVMTI_PHASE_LIVE
JVMTI_PHASE_ONLOAD
JVMTI_PHASE_PRIMORDIAL
JVMTI_PHASE_START
JVMTI_PRIMITIVE_TYPE_BOOLEAN
JVMTI_PRIMITIVE_TYPE_BYTE
JVMTI_PRIMITIVE_TYPE_CHAR
JVMTI_PRIMITIVE_TYPE_DOUBLE
JVMTI_PRIMITIVE_TYPE_FLOAT
JVMTI_PRIMITIVE_TYPE_INT
JVMTI_PRIMITIVE_TYPE_LONG
JVMTI_PRIMITIVE_TYPE_SHORT
JVMTI_REFERENCE_ARRAY_ELEMENT
JVMTI_REFERENCE_CLASS
JVMTI_REFERENCE_CLASS_LOADER
JVMTI_REFERENCE_CONSTANT_POOL
JVMTI_REFERENCE_FIELD
JVMTI_REFERENCE_INTERFACE
JVMTI_REFERENCE_PROTECTION_DOMAIN
JVMTI_REFERENCE_SIGNERS
JVMTI_REFERENCE_STATIC_FIELD
JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP
JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR
JVMTI_RESOURCE_EXHAUSTED_THREADS
JVMTI_THREAD_MAX_PRIORITY
JVMTI_THREAD_MIN_PRIORITY
JVMTI_THREAD_NORM_PRIORITY
JVMTI_THREAD_STATE_ALIVE
JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER
JVMTI_THREAD_STATE_IN_NATIVE
JVMTI_THREAD_STATE_IN_OBJECT_WAIT
JVMTI_THREAD_STATE_INTERRUPTED
JVMTI_THREAD_STATE_PARKED
JVMTI_THREAD_STATE_RUNNABLE
JVMTI_THREAD_STATE_SLEEPING
JVMTI_THREAD_STATE_SUSPENDED
JVMTI_THREAD_STATE_TERMINATED
JVMTI_THREAD_STATE_VENDOR_1
JVMTI_THREAD_STATE_VENDOR_2
JVMTI_THREAD_STATE_VENDOR_3
JVMTI_THREAD_STATE_WAITING
JVMTI_THREAD_STATE_WAITING_INDEFINITELY
JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT
JVMTI_TIMER_ELAPSED
JVMTI_TIMER_TOTAL_CPU
JVMTI_TIMER_USER_CPU
JVMTI_TYPE_CCHAR
JVMTI_TYPE_CVOID
JVMTI_TYPE_JBOOLEAN
JVMTI_TYPE_JBYTE
JVMTI_TYPE_JCHAR
JVMTI_TYPE_JCLASS
JVMTI_TYPE_JDOUBLE
JVMTI_TYPE_JFIELDID
JVMTI_TYPE_JFLOAT
JVMTI_TYPE_JINT
JVMTI_TYPE_JLONG
JVMTI_TYPE_JMETHODID
JVMTI_TYPE_JNIENV
JVMTI_TYPE_JOBJECT
JVMTI_TYPE_JSHORT
JVMTI_TYPE_JTHREAD
JVMTI_TYPE_JVALUE
JVMTI_VERBOSE_CLASS
JVMTI_VERBOSE_GC
JVMTI_VERBOSE_JNI
JVMTI_VERBOSE_OTHER
JVMTI_VERSION_INTERFACE_JNI
JVMTI_VERSION_INTERFACE_JVMTI
JVMTI_VERSION_MASK_INTERFACE_TYPE
JVMTI_VERSION_MASK_MAJOR
JVMTI_VERSION_MASK_MICRO
JVMTI_VERSION_MASK_MINOR
JVMTI_VERSION_SHIFT_MAJOR
JVMTI_VERSION_SHIFT_MICRO
JVMTI_VERSION_SHIFT_MINOR
JVMTI_VISIT_ABORT
JVMTI_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日虚拟线程已最终确定为永久功能。现在规定在实时阶段代理启动将打印警告。