JVMTM Tool Interface , Oracle Java se 21
https://docs.oracle.com/en/java/javase/21/docs/specs/jvmti.html
What is the JVM Tool Interface?
The JVMTM Tool Interface (JVM TI) is a programming interface used by development and monitoring tools. It provides both a way to inspect the state and to control the execution of applications running in the JavaTM virtual machine (VM).JVM TI is intended to provide a VM interface for the full breadth of tools that need access to VM state, including but not limited to: profiling, debugging, monitoring, thread analysis, and coverage analysis tools.JVM TI may not be available in all implementations of the JavaTM virtual machine.JVM TI is a two-way interface. A client of JVM TI, hereafter called an agent, can be notified of interesting occurrences through events. JVM TI can query and control the application through many functions, either in response to events or independent of them.Agents run in the same process with and communicate directly with the virtual machine executing the application being examined. This communication is through a native interface (JVM TI). The native in-process interface allows maximal control with minimal intrusion on the part of a tool. Typically, agents are relatively compact. They can be controlled by a separate process which implements the bulk of a tool's function without interfering with the target application's normal execution.
JVM工具接口(JVM TI)是供开发和监控工具使用的编程接口。该接口既能检查运行在Java虚拟机(VM)中的应用程序状态,又能控制其执行流程。
JVM TI旨在为各类需要访问虚拟机状态的工具提供统一接口,涵盖但不限于:性能分析工具、调试工具、监控工具、线程分析工具以及覆盖率分析工具。需要注意的是,并非所有Java虚拟机实现都支持JVM TI功能。
该接口采用双向交互机制。JVM TI的客户端(后文称为"代理")可通过事件机制接收关键状态通知,同时JVM TI也提供大量函数供代理主动查询和控制应用程序——这些操作既可响应事件触发,也可独立执行。
代理程序与待检测应用程序运行在同一进程空间,并通过原生接口(JVM TI)直接与虚拟机通信。这种原生进程内交互架构既能实现工具对虚拟机的深度控制,又能将对目标应用程序的侵入性降至最低。典型场景下,代理程序本身十分轻量,可由独立进程控制——该进程承载工具的核心功能模块,从而避免干扰目标应用程序的正常运行。
Architecture
Tools can be written directly to JVM TI or indirectly through higher level interfaces. The Java Platform Debugger Architecture includes JVM TI, but also contains higher-level, out-of-process debugger interfaces. The higher-level interfaces are more appropriate than JVM TI for many tools. For more information on the Java Platform Debugger Architecture, see the Java Platform Debugger Architecture website.
Writing Agents
Agents can be written in any native language that supports C language calling conventions and C or C++ definitions.The function, event, data type, and constant definitions needed for using JVM TI are defined in the include file jvmti.h. To use these definitions add the J2SETM include directory to your include path and add
#include <jvmti.h>
to your source code.
Deploying Agents
An agent is deployed in a platform specific manner but is typically the platform equivalent of a dynamic library. On the WindowsTM operating system, for example, an agent library is a "Dynamic Linked Library" (DLL). On LinuxTM Operating Environment, an agent library is a shared object (.so file).An agent may be started at VM startup by specifying the agent library name using a command line option. Some implementations may support a mechanism to start agents in the live phase. The details of how this is initiated are implementation specific.
Statically Linked Agents (since version 1.2.3)
A native JVMTI Agent may be statically linked with the VM. The manner in which the library and VM image are combined is implementation-dependent. An agent L whose image has been combined with the VM is defined as statically linked if and only if the agent exports a function called Agent_OnLoad_L.If a statically linked agent L exports a function called Agent_OnLoad_L and a function called Agent_OnLoad, the Agent_OnLoad function will be ignored. If an agent L is statically linked, an Agent_OnLoad_L function will be invoked with the same arguments and expected return value as specified for the Agent_OnLoad function. An agent L that is statically linked will prohibit an agent of the same name from being loaded dynamically.The VM will invoke the Agent_OnUnload_L function of the agent, if such a function is exported, at the same point during VM execution as it would have called the dynamic entry point Agent_OnUnLoad. A statically loaded agent cannot be unloaded. The Agent_OnUnload_L function will still be called to do any other agent shutdown related tasks. If a statically linked agent L exports a function called Agent_OnUnLoad_L and a function called Agent_OnUnLoad, the Agent_OnUnLoad function will be ignored.If an agent L is statically linked, an Agent_OnAttach_L function will be invoked with the same arguments and expected return value as specified for the Agent_OnAttach function. If a statically linked agent L exports a function called Agent_OnAttach_L and a function called Agent_OnAttach, the Agent_OnAttach function will be ignored.
Agent Command Line Options
The term "command-line option" is used below to mean options supplied in the JavaVMInitArgs argument to the JNI_CreateJavaVM function of the JNI Invocation API.One of the two following command-line options is used on VM startup to properly load and run agents. These arguments identify the library containing the agent as well as an options string to be passed in at startup.
-agentlib:<agent-lib-name>=<options>
The name following -agentlib: is the name of the library to load. Lookup of the library, both its full name and location, proceeds in a platform-specific manner. Typically, the <agent-lib-name> is expanded to an operating system specific file name. The <options> will be passed to the agent on start-up. For example, if the option -agentlib:foo=opt1,opt2 is specified, the VM will attempt to load the shared library foo.dll from the system PATH under WindowsTM or libfoo.so from the LD_LIBRARY_PATH under LinuxTM . If the agent library is statically linked into the executable then no actual loading takes place.
-agentpath:<path-to-agent>=<options>
The path following -agentpath: is the absolute path from which to load the library. No library name expansion will occur. The <options> will be passed to the agent on start-up. For example, if the option -agentpath:c:\myLibs\foo.dll=opt1,opt2 is specified, the VM will attempt to load the shared library c:\myLibs\foo.dll. If the agent library is statically linked into the executable then no actual loading takes place.
For a dynamic shared library agent, the start-up routine Agent_OnLoad in the library will be invoked. If the agent library is statically linked into the executable then the system will attempt to invoke the Agent_OnLoad_<agent-lib-name> entry point where <agent-lib-name> is the basename of the agent. In the above example -agentpath:c:\myLibs\foo.dll=opt1,opt2, the system will attempt to find and call the Agent_OnLoad_foo start-up routine.Libraries loaded with -agentlib: or -agentpath: will be searched for JNI native method implementations to facilitate the use of Java programming language code in tools, as is needed for bytecode instrumentation.The agent libraries will be searched after all other libraries have been searched (agents wishing to override or intercept the native method implementations of non-agent methods can use the NativeMethodBind event).These switches do the above and nothing more - they do not change the state of the VM or JVM TI. No command line options are needed to enable JVM TI or aspects of JVM TI, this is handled programmatically by the use of capabilities.
Agent Start-Up
The VM starts each agent by invoking a start-up function. If the agent is started in the OnLoad phase the function Agent_OnLoad or Agent_OnLoad_L for statically linked agents will be invoked. If the agent is started in the live phase the function Agent_OnAttach or Agent_OnAttach_L for statically linked agents will be invoked. Exactly one call to a start-up function is made per agent.
Agent Start-Up (OnLoad phase)
If an agent is started during the OnLoad phase then its agent library must export a start-up function with the following prototype:
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
Or for a statically linked agent named 'L':
JNIEXPORT jint JNICALL Agent_OnLoad_L(JavaVM *vm, char *options, void *reserved)
The VM will start the agent by calling this function. It will be called early enough in VM initialization that:
- system properties may be set before they have been used in the start-up of the VM
- the full set of capabilities is still available (note that capabilities that configure the VM may only be available at this time--see the Capability function section)
- no bytecodes have executed
- no classes have been loaded
- no objects have been created
The VM will call the Agent_OnLoad or Agent_OnLoad_<agent-lib-name> function with <options> as the second argument - that is, using the command-line option examples, "opt1,opt2" will be passed to the char *options argument of Agent_OnLoad. The options argument is encoded as a modified UTF-8 string. If =<options> is not specified, a zero length string is passed to options. The lifespan of the options string is the Agent_OnLoad or Agent_OnLoad_<agent-lib-name> call. If needed beyond this time the string or parts of the string must be copied. The period between when Agent_OnLoad is called and when it returns is called the OnLoad phase. Since the VM is not initialized during the OnLoad phase, the set of allowed operations inside Agent_OnLoad is restricted (see the function descriptions for the functionality available at this time). The agent can safely process the options and set event callbacks with SetEventCallbacks. Once the VM initialization event is received (that is, the VMInit callback is invoked), the agent can complete its initialization.
Rationale: Early startup is required so that agents can set the desired capabilities, many of which must be set before the VM is initialized. In JVMDI, the -Xdebug command-line option provided very coarse-grain control of capabilities. JVMPI implementations use various tricks to provide a single "JVMPI on" switch. No reasonable command-line option could provide the fine-grain of control required to balance needed capabilities vs performance impact. Early startup is also needed so that agents can control the execution environment - modifying the file system and system properties to install their functionality.
The return value from Agent_OnLoad or Agent_OnLoad_<agent-lib-name> is used to indicate an error. Any value other than zero indicates an error and causes termination of the VM.
Agent Start-Up (Live phase)
A VM may support a mechanism that allows agents to be started in the VM during the live phase. The details of how this is supported, are implementation specific. For example, a tool may use some platform specific mechanism, or implementation specific API, to attach to the running VM, and request it start a given agent.The VM prints a warning on the standard error stream for each agent that it attempts to start in the live phase. If an agent was previously started (in the OnLoad phase or in the live phase), then it is implementation specific as to whether a warning is printed when attempting to start the same agent a second or subsequent time. Warnings can be disabled by means of an implementation-specific command line option.Implementation Note: For the HotSpot VM, the VM option -XX:+EnableDynamicAgentLoading is used to opt-in to allow dynamic loading of agents in the live phase. This option suppresses the warning to standard error when starting an agent in the live phase.If an agent is started during the live phase then its agent library must export a start-up function with the following prototype:
JNIEXPORT jint JNICALL Agent_OnAttach(JavaVM* vm, char *options, void *reserved)
Or for a statically linked agent named 'L':
JNIEXPORT jint JNICALL Agent_OnAttach_L(JavaVM* vm, char *options, void *reserved)
The VM will start the agent by calling this function. It will be called in the context of a thread that is attached to the VM. The first argument <vm> is the Java VM. The <options> argument is the startup options provided to the agent. <options> is encoded as a modified UTF-8 string. If startup options were not provided, a zero length string is passed to options. The lifespan of the options string is the Agent_OnAttach or Agent_OnAttach_<agent-lib-name> call. If needed beyond this time the string or parts of the string must be copied.Note that some capabilities may not be available in the live phase.The Agent_OnAttach or Agent_OnAttach_<agent-lib-name > function initializes the agent and returns a value to the VM to indicate if an error occurred. Any value other than zero indicates an error. An error does not cause the VM to terminate. Instead the VM ignores the error, or takes some implementation specific action -- for example it might print an error to standard error, or record the error in a system log.
Agent Shutdown
The library may optionally export a shutdown function with the following prototype:
JNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm)
Or for a statically linked agent named 'L':
JNIEXPORT void JNICALL Agent_OnUnload_L(JavaVM *vm)
This function will be called by the VM when the library is about to be unloaded. The library will be unloaded (unless it is statically linked into the executable) and this function will be called if some platform specific mechanism causes the unload (an unload mechanism is not specified in this document) or the library is (in effect) unloaded by the termination of the VM. VM termination includes normal termination and VM failure, including start-up failure, but not, of course, uncontrolled shutdown. An implementation may also choose to not call this function if the Agent_OnAttach/ Agent_OnAttach_L function reported an error (returned a non-zero value). Note the distinction between this function and the VM Death event: for the VM Death event to be sent, the VM must have run at least to the point of initialization and a valid JVM TI environment must exist which has set a callback for VMDeath and enabled the event. None of these are required for Agent_OnUnload or Agent_OnUnload_<agent-lib-name> and this function is also called if the library is unloaded for other reasons. In the case that a VM Death event is sent, it will be sent before this function is called (assuming this function is called due to VM termination). This function can be used to clean-up resources allocated by the agent.
JAVA_TOOL_OPTIONS
Since the command-line cannot always be accessed or modified, for example in embedded VMs or simply VMs launched deep within scripts, a JAVA_TOOL_OPTIONS variable is provided so that agents may be launched in these cases.Platforms which support environment variables or other named strings, may support the JAVA_TOOL_OPTIONS variable. This variable will be broken into options at white-space boundaries. White-space characters include space, tab, carriage-return, new-line, vertical-tab, and form-feed. Sequences of white-space characters are considered equivalent to a single white-space character. No white-space is included in the options unless quoted. Quoting is as follows:
- All characters enclosed between a pair of single quote marks (''), except a single quote, are quoted.
- Double quote characters have no special meaning inside a pair of single quote marks.
- All characters enclosed between a pair of double quote marks (""), except a double quote, are quoted.
- Single quote characters have no special meaning inside a pair of double quote marks.
- A quoted part can start or end anywhere in the variable.
- White-space characters have no special meaning when quoted -- they are included in the option like any other character and do not mark white-space boundaries.
- The pair of quote marks is not included in the option.
JNI_CreateJavaVM (in the JNI Invocation API) will prepend these options to the options supplied in its JavaVMInitArgs argument. Platforms may disable this feature in cases where security is a concern; for example, the Reference Implementation disables this feature on Unix systems when the effective user or group ID differs from the real ID. This feature is intended to support the initialization of tools -- specifically including the launching of native or Java programming language agents. Multiple tools may wish to use this feature, so the variable should not be overwritten, instead, options should be appended to the variable. Note that since the variable is processed at the time of the JNI Invocation API create VM call, options processed by a launcher (e.g., VM selection options) will not be handled.
Environments
The JVM TI specification supports the use of multiple simultaneous JVM TI agents. Each agent has its own JVM TI environment. That is, the JVM TI state is separate for each agent - changes to one environment do not affect the others. The state of a JVM TI environment includes:
- the event callbacks
- the set of events which are enabled
- the capabilities
- the memory allocation/deallocation hooks
Although their JVM TI state is separate, agents inspect and modify the shared state of the VM, they also share the native environment in which they execute. As such, an agent can perturb the results of other agents or cause them to fail. It is the responsibility of the agent writer to specify the level of compatibility with other agents. JVM TI implementations are not capable of preventing destructive interactions between agents. Techniques to reduce the likelihood of these occurrences are beyond the scope of this document.An agent creates a JVM TI environment by passing a JVM TI version as the interface ID to the JNI Invocation API function GetEnv. See Accessing JVM TI Functions for more details on the creation and use of JVM TI environments. Typically, JVM TI environments are created by calling GetEnv from Agent_OnLoad.
Bytecode Instrumentation
This interface does not include some events that one might expect in an interface with profiling support. Some examples include full speed method enter and exit events. The interface instead provides support for bytecode instrumentation, the ability to alter the Java virtual machine bytecode instructions which comprise the target program. Typically, these alterations are to add "events" to the code of a method - for example, to add, at the beginning of a method, a call to MyProfiler.methodEntered(). Since the changes are purely additive, they do not modify application state or behavior. Because the inserted agent code is standard bytecodes, the VM can run at full speed, optimizing not only the target program but also the instrumentation. If the instrumentation does not involve switching from bytecode execution, no expensive state transitions are needed. The result is high performance events. This approach also provides complete control to the agent: instrumentation can be restricted to "interesting" portions of the code (e.g., the end user's code) and can be conditional. Instrumentation can run entirely in Java programming language code or can call into the native agent. Instrumentation can simply maintain counters or can statistically sample events.Instrumentation can be inserted in one of three ways:
- Static Instrumentation: The class file is instrumented before it is loaded into the VM - for example, by creating a duplicate directory of
*.classfiles which have been modified to add the instrumentation. This method is extremely awkward and, in general, an agent cannot know the origin of the class files which will be loaded. - Load-Time Instrumentation: When a class file is loaded by the VM, the raw bytes of the class file are sent for instrumentation to the agent. The ClassFileLoadHook event, triggered by the class load, provides this functionality. This mechanism provides efficient and complete access to one-time instrumentation.
- Dynamic Instrumentation: A class which is already loaded (and possibly even running) is modified. This optional feature is provided by the ClassFileLoadHook event, triggered by calling the RetransformClasses function. Classes can be modified multiple times and can be returned to their original state. The mechanism allows instrumentation which changes during the course of execution.
The class modification functionality provided in this interface is intended to provide a mechanism for instrumentation (the ClassFileLoadHook event and the RetransformClasses function) and, during development, for fix-and-continue debugging (the RedefineClasses function).Care must be taken to avoid perturbing dependencies, especially when instrumenting core classes. For example, an approach to getting notification of every object allocation is to instrument the constructor on Object. Assuming that the constructor is initially empty, the constructor could be changed to:
public Object() {
MyProfiler.allocationTracker(this);
}
However, if this change was made using the ClassFileLoadHook event then this might impact a typical VM as follows: the first created object will call the constructor causing a class load of MyProfiler; which will then cause object creation, and since MyProfiler isn't loaded yet, infinite recursion; resulting in a stack overflow. A refinement of this would be to delay invoking the tracking method until a safe time. For example, trackAllocations could be set in the handler for the VMInit event.
static boolean trackAllocations = false;
public Object() {
if (trackAllocations) {
MyProfiler.allocationTracker(this);
}
}
The SetNativeMethodPrefix allows native methods to be instrumented by the use of wrapper methods.
Bytecode Instrumentation of code in modules
Agents can use the functions AddModuleReads, AddModuleExports, AddModuleOpens, AddModuleUses and AddModuleProvides to update a module to expand the set of modules that it reads, the set of packages that it exports or opens to other modules, or the services that it uses and provides.As an aid to agents that deploy supporting classes on the search path of the bootstrap class loader, or the search path of the class loader that loads the main class, the Java virtual machine arranges for the module of classes transformed by the ClassFileLoadHook event to read the unnamed module of both class loaders.
Modified UTF-8 String Encoding
JVM TI uses modified UTF-8 to encode character strings. This is the same encoding used by JNI. Modified UTF-8 differs from standard UTF-8 in the representation of supplementary characters and of the null character. See the Modified UTF-8 Strings section of the JNI specification for details.
Specification Context
Since this interface provides access to the state of applications running in the Java virtual machine; terminology refers to the Java platform and not the native platform (unless stated otherwise). For example:
- "thread" means Java programming language thread.
- "stack frame" means Java virtual machine stack frame.
- "class" means Java programming language class.
- "heap" means Java virtual machine heap.
- "monitor" means Java programming language object monitor.
Sun, Sun Microsystems, the Sun logo, Java, and JVM are trademarks or registered trademarks of Oracle and/or its affiliates, in the U.S. and other countries.
Functions
Accessing Functions
Native code accesses JVM TI features by calling JVM TI functions. Access to JVM TI functions is by use of an interface pointer in the same manner as Java Native Interface (JNI) functions are accessed. The JVM TI interface pointer is called the environment pointer.An environment pointer is a pointer to an environment and has the type jvmtiEnv*. An environment has information about its JVM TI connection. The first value in the environment is a pointer to the function table. The function table is an array of pointers to JVM TI functions. Every function pointer is at a predefined offset inside the array.When used from the C language: double indirection is used to access the functions; the environment pointer provides context and is the first parameter of each function call; for example:
jvmtiEnv *jvmti;
...
jvmtiError err = (*jvmti)->GetLoadedClasses(jvmti, &class_count, &classes);
When used from the C++ language: functions are accessed as member functions of jvmtiEnv; the environment pointer is not passed to the function call; for example:
jvmtiEnv *jvmti;
...
jvmtiError err = jvmti->GetLoadedClasses(&class_count, &classes);
Unless otherwise stated, all examples and declarations in this specification use the C language.A JVM TI environment can be obtained through the JNI Invocation API GetEnv function:
jvmtiEnv *jvmti;
...
(*jvm)->GetEnv(jvm, &jvmti, JVMTI_VERSION_1_0);
Each call to GetEnv creates a new JVM TI connection and thus a new JVM TI environment. The version argument of GetEnv must be a JVM TI version. The returned environment may have a different version than the requested version but the returned environment must be compatible. GetEnv will return JNI_EVERSION if a compatible version is not available, if JVM TI is not supported or JVM TI is not supported in the current VM configuration. Other interfaces may be added for creating JVM TI environments in specific contexts. Each environment has its own state (for example, desired events, event handling functions, and capabilities). An environment is released with DisposeEnvironment. Thus, unlike JNI which has one environment per thread, JVM TI environments work across threads and are created dynamically.
Function Return Values
JVM TI functions always return an error code via the jvmtiError function return value. Some functions can return additional values through pointers provided by the calling function. In some cases, JVM TI functions allocate memory that your program must explicitly deallocate. This is indicated in the individual JVM TI function descriptions. Empty lists, arrays, sequences, etc are returned as NULL.In the event that the JVM TI function encounters an error (any return value other than JVMTI_ERROR_NONE) the values of memory referenced by argument pointers is undefined, but no memory will have been allocated and no global references will have been allocated. If the error occurs because of invalid input, no action will have occurred.
Managing JNI Object References
JVM TI functions identify objects with JNI references (jobject and jclass) and their derivatives (jthread and jthreadGroup). References passed to JVM TI functions can be either global or local, but they must be strong references. All references returned by JVM TI functions are local references--these local references are created during the JVM TI call. Local references are a resource that must be managed (see the JNI Documentation). When threads return from native code all local references are freed. Note that some threads, including typical agent threads, will never return from native code. A thread is ensured the ability to create sixteen local references without the need for any explicit management. For threads executing a limited number of JVM TI calls before returning from native code (for example, threads processing events), it may be determined that no explicit management is needed. However, long running agent threads will need explicit local reference management--usually with the JNI functions PushLocalFrame and PopLocalFrame. Conversely, to preserve references beyond the return from native code, they must be converted to global references. These rules do not apply to jmethodID and jfieldID as they are not jobjects.
Prerequisite State for Calling Functions
Unless the function explicitly states that the agent must bring a thread or the VM to a particular state (for example, suspended), the JVM TI implementation is responsible for bringing the VM to a safe and consistent state for performing the function.
Exceptions and Functions
JVM TI functions never throw exceptions; error conditions are communicated via the function return value. Any existing exception state is preserved across a call to a JVM TI function. See the Java Exceptions section of the JNI specification for information on handling exceptions.
Function Index
- Memory Management
- Thread
- Get Thread State
- Get Current Thread
- Get All Threads
- Suspend Thread
- Suspend Thread List
- Suspend All Virtual Threads
- Resume Thread
- Resume Thread List
- Resume All Virtual Threads
- Stop Thread
- Interrupt Thread
- Get Thread Info
- Get Owned Monitor Info
- Get Owned Monitor Stack Depth Info
- Get Current Contended Monitor
- Run Agent Thread
- Set Thread Local Storage
- Get Thread Local Storage
- Thread Group
- Stack Frame
- Force Early Return
- Heap
- Heap (1.0)
- Local Variable
- Breakpoint
- Watched Field
- Module
- Class
- Get Loaded Classes
- Get Classloader Classes
- Get Class Signature
- Get Class Status
- Get Source File Name
- Get Class Modifiers
- Get Class Methods
- Get Class Fields
- Get Implemented Interfaces
- Get Class Version Numbers
- Get Constant Pool
- Is Interface
- Is Array Class
- Is Modifiable Class
- Get Class Loader
- Get Source Debug Extension
- Retransform Classes
- Redefine Classes
- Object
- Field
- Method
- Get Method Name (and Signature)
- Get Method Declaring Class
- Get Method Modifiers
- Get Max Locals
- Get Arguments Size
- Get Line Number Table
- Get Method Location
- Get Local Variable Table
- Get Bytecodes
- Is Method Native
- Is Method Synthetic
- Is Method Obsolete
- Set Native Method Prefix
- Set Native Method Prefixes
- Raw Monitor
- JNI Function Interception
- Event Management
- Extension Mechanism
- Capability
- Timers
- Class Loader Search
- System Properties
- General
- Heap Monitoring
Memory Management
Memory Management functions:
These functions provide for the allocation and deallocation of memory used by JVM TI functionality and can be used to provide working memory for agents. Memory managed by JVM TI is not compatible with other memory allocation libraries and mechanisms.
Allocate
jvmtiError
Allocate(jvmtiEnv* env,
jlong size,
unsigned char** mem_ptr)
Allocate an area of memory through the JVM TI allocator. The allocated memory should be freed with Deallocate.
may be called during any phase
This function may be called from the callbacks to the Heap iteration functions, or from the event handlers for the GarbageCollectionStart, GarbageCollectionFinish, and ObjectFree events.
46
1.0
Capabilities
Required Functionality
| Name | Type | Description |
|---|---|---|
size |
jlong |
The number of bytes to allocate.
Rationale: |
mem_ptr |
unsigned char** |
On return, a pointer to the beginning of the allocated memory. If size is zero, NULL is returned.Agent passes a pointer to a unsigned char*. On return, the unsigned char* points to a newly allocated array of size size. The array should be freed with Deallocate. |
| Error | Description |
|---|---|
| JVMTI_ERROR_OUT_OF_MEMORY | Memory request cannot be honored. |
| JVMTI_ERROR_ILLEGAL_ARGUMENT | size is less than zero. |
| JVMTI_ERROR_NULL_POINTER | mem_ptr is NULL. |
Deallocate
jvmtiError
Deallocate(jvmtiEnv* env,
unsigned char* mem)
Deallocate mem using the JVM TI allocator. This function should be used to deallocate any memory allocated and returned by a JVM TI function (including memory allocated with Allocate). All allocated memory must be deallocated or the memory cannot be reclaimed.
may be called during any phase
This function may be called from the callbacks to the Heap iteration functions, or from the event handlers for the GarbageCollectionStart, GarbageCollectionFinish, and ObjectFree events.
47
1.0
Capabilities
Required Functionality
| Name | Type | Description |
|---|---|---|
mem |
unsigned char * |
A pointer to the beginning of the allocated memory. Please ignore "On return, the elements are set."Agent passes an array of unsigned char. The incoming values of the elements of the array are ignored. On return, the elements are set. If mem is NULL, the call is ignored. |
Errors
This function returns a universal error
Thread
Thread functions:
- Get Thread State
- Get Current Thread
- Get All Threads
- Suspend Thread
- Suspend Thread List
- Suspend All Virtual Threads
- Resume Thread
- Resume Thread List
- Resume All Virtual Threads
- Stop Thread
- Interrupt Thread
- Get Thread Info
- Get Owned Monitor Info
- Get Owned Monitor Stack Depth Info
- Get Current Contended Monitor
- Run Agent Thread
- Set Thread Local Storage
- Get Thread Local Storage
Thread function types:
Thread types:
- jvmtiThreadInfo - Thread information structure
- jvmtiMonitorStackDepthInfo - Monitor stack depth information structure
Thread flags and constants:
These functions provide information about threads and allow an agent to suspend and resume threads.The jthread specified to these functions can be a JNI reference to a platform thread or virtual thread. Some functions are not supported on virtual threads and return JVMTI_ERROR_UNSUPPORTED_OPERATION when called with a reference to a virtual thread.
Get Thread State
jvmtiError
GetThreadState(jvmtiEnv* env,
jthread thread,
jint* thread_state_ptr)
Get the state of a thread. The state of the thread is represented by the answers to the hierarchical set of questions below:
- Alive?
- Not alive.
- Why not alive?
- New.
- Terminated (JVMTI_THREAD_STATE_TERMINATED)
- Why not alive?
- Alive (JVMTI_THREAD_STATE_ALIVE)
- Suspended?
- Suspended (JVMTI_THREAD_STATE_SUSPENDED)
- Not suspended
- Interrupted?
- Interrupted (JVMTI_THREAD_STATE_INTERRUPTED)
- Not interrupted.
- In native?
- In native code (JVMTI_THREAD_STATE_IN_NATIVE)
- In Java programming language code
- What alive state?
- Runnable (JVMTI_THREAD_STATE_RUNNABLE)
- Blocked (JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER)
- Waiting (JVMTI_THREAD_STATE_WAITING)
- Timed wait?
- Indefinite (JVMTI_THREAD_STATE_WAITING_INDEFINITELY
- Timed (JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT)
- Why waiting?
- Object.wait (JVMTI_THREAD_STATE_IN_OBJECT_WAIT)
- LockSupport.park (JVMTI_THREAD_STATE_PARKED)
- Sleeping (JVMTI_THREAD_STATE_SLEEPING)
- Timed wait?
- Suspended?
- Not alive.
The answers are represented by the following bit vector.
Thread State Flags Constant Value Description JVMTI_THREAD_STATE_ALIVE0x0001 Thread is alive. Zero if thread is new (not started) or terminated. JVMTI_THREAD_STATE_TERMINATED0x0002 Thread has completed execution. JVMTI_THREAD_STATE_RUNNABLE0x0004 Thread is runnable. JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER0x0400 Thread is waiting to enter a synchronized block/method or, after an Object.wait(), waiting to re-enter a synchronized block/method.JVMTI_THREAD_STATE_WAITING0x0080 Thread is waiting. JVMTI_THREAD_STATE_WAITING_INDEFINITELY0x0010 Thread is waiting without a timeout. For example, Object.wait().JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT0x0020 Thread is waiting with a maximum time to wait specified. For example, Object.wait(long).JVMTI_THREAD_STATE_SLEEPING0x0040 Thread is sleeping -- Thread.sleep.JVMTI_THREAD_STATE_IN_OBJECT_WAIT0x0100 Thread is waiting on an object monitor -- Object.wait.JVMTI_THREAD_STATE_PARKED0x0200 Thread is parked, for example: LockSupport.park,LockSupport.parkUtilandLockSupport.parkNanos. A virtual thread that is sleeping, inThread.sleep, may have this state flag set instead ofJVMTI_THREAD_STATE_SLEEPING.JVMTI_THREAD_STATE_SUSPENDED0x100000 Thread is suspended by a suspend function (such as SuspendThread). If this bit is set, the other bits refer to the thread state before suspension. JVMTI_THREAD_STATE_INTERRUPTED0x200000 Thread has been interrupted. JVMTI_THREAD_STATE_IN_NATIVE0x400000 Thread is in native code--that is, a native method is running which has not called back into the VM or Java programming language code.This flag is not set when running VM compiled Java programming language code nor is it set when running VM code or VM support code. Native VM interface functions, such as JNI and JVM TI functions, may be implemented as VM code. JVMTI_THREAD_STATE_VENDOR_10x10000000 Defined by VM vendor. JVMTI_THREAD_STATE_VENDOR_20x20000000 Defined by VM vendor. JVMTI_THREAD_STATE_VENDOR_30x40000000 Defined by VM vendor.
The following definitions are used to convert JVM TI thread state to java.lang.Thread.State style states.
java.lang.Thread.State Conversion Masks Constant Value Description JVMTI_JAVA_LANG_THREAD_STATE_MASKJVMTI_THREAD_STATE_TERMINATED | JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT Mask the state with this before comparison JVMTI_JAVA_LANG_THREAD_STATE_NEW0 java.lang.Thread.State.NEWJVMTI_JAVA_LANG_THREAD_STATE_TERMINATEDJVMTI_THREAD_STATE_TERMINATED java.lang.Thread.State.TERMINATEDJVMTI_JAVA_LANG_THREAD_STATE_RUNNABLEJVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE java.lang.Thread.State.RUNNABLEJVMTI_JAVA_LANG_THREAD_STATE_BLOCKEDJVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER java.lang.Thread.State.BLOCKEDJVMTI_JAVA_LANG_THREAD_STATE_WAITINGJVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY java.lang.Thread.State.WAITINGJVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITINGJVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT java.lang.Thread.State.TIMED_WAITING
RulesThere can be no more than one answer to a question, although there can be no answer (because the answer is unknown, does not apply, or none of the answers is correct). An answer is set only when the enclosing answers match. That is, no more than one of
JVMTI_THREAD_STATE_RUNNABLEJVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTERJVMTI_THREAD_STATE_WAITING
can be set (a J2SETM compliant implementation will always set one of these if JVMTI_THREAD_STATE_ALIVE is set). And if any of these are set, the enclosing answer JVMTI_THREAD_STATE_ALIVE is set. No more than one of
JVMTI_THREAD_STATE_WAITING_INDEFINITELYJVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT
can be set (a J2SETM compliant implementation will always set one of these if JVMTI_THREAD_STATE_WAITING is set). And if either is set, the enclosing answers JVMTI_THREAD_STATE_ALIVE and JVMTI_THREAD_STATE_WAITING are set. No more than one of
JVMTI_THREAD_STATE_IN_OBJECT_WAITJVMTI_THREAD_STATE_PARKEDJVMTI_THREAD_STATE_SLEEPING
can be set. And if any of these is set, the enclosing answers JVMTI_THREAD_STATE_ALIVE and JVMTI_THREAD_STATE_WAITING are set. Also, if JVMTI_THREAD_STATE_SLEEPING is set, then JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT is set. If a state A is implemented using the mechanism of state B then it is state A which is returned by this function. For example, if Thread.sleep(long) is implemented using Object.wait(long) then it is still JVMTI_THREAD_STATE_SLEEPING which is returned. More than one of
JVMTI_THREAD_STATE_SUSPENDEDJVMTI_THREAD_STATE_INTERRUPTEDJVMTI_THREAD_STATE_IN_NATIVE
can be set, but if any is set, JVMTI_THREAD_STATE_ALIVE is set.And finally, JVMTI_THREAD_STATE_TERMINATED cannot be set unless JVMTI_THREAD_STATE_ALIVE is not set.The thread state representation is designed for extension in future versions of the specification; thread state values should be used accordingly, that is they should not be used as ordinals. Most queries can be made by testing a single bit, if use in a switch statement is desired, the state bits should be masked with the interesting bits. All bits not defined above are reserved for future use. A VM, compliant to the current specification, must set reserved bits to zero. An agent should ignore reserved bits -- they should not be assumed to be zero and thus should not be included in comparisons.ExamplesNote that the values below exclude reserved and vendor bits.The state of a thread blocked at a synchronized-statement would be:
JVMTI_THREAD_STATE_ALIVE + JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER
The state of a thread which hasn't started yet would be:
0
The state of a thread at a Object.wait(3000) would be:
JVMTI_THREAD_STATE_ALIVE + JVMTI_THREAD_STATE_WAITING +
JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT +
JVMTI_THREAD_STATE_MONITOR_WAITING
The state of a thread suspended while runnable would be:
JVMTI_THREAD_STATE_ALIVE + JVMTI_THREAD_STATE_RUNNABLE + JVMTI_THREAD_STATE_SUSPENDED
Testing the StateIn most cases, the thread state can be determined by testing the one bit corresponding to that question. For example, the code to test if a thread is sleeping:
jint state;
jvmtiError err;
err = (*jvmti)->GetThreadState(jvmti, thread, &state);
if (err == JVMTI_ERROR_NONE) {
if (state & JVMTI_THREAD_STATE_SLEEPING) { ...
For waiting (that is, in Object.wait, parked, or sleeping) it would be:
if (state & JVMTI_THREAD_STATE_WAITING) { ...
For some states, more than one bit will need to be tested as is the case when testing if a thread has not yet been started:
if ((state & (JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_TERMINATED)) == 0) { ...
To distinguish timed from untimed 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");
}
}
Relationship to java.lang.Thread.StateThe thread state represented by java.lang.Thread.State returned from java.lang.Thread.getState() is a subset of the information returned from this function. The corresponding java.lang.Thread.State can be determined by using the provided conversion masks. For example, this returns the name of the java.lang.Thread.State 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";
}
may only be called during the live phase
No
17
1.0
Capabilities
Required Functionality
| Name | Type | Description |
|---|---|---|
thread |
jthread |
The thread to query. If thread is NULL, the current thread is used. |
thread_state_ptr |
jint* |
On return, points to state flags, as defined by the Thread State Flags.Agent passes a pointer to a jint. On return, the jint has been set. |
| Error | Description |
|---|---|
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_NULL_POINTER | thread_state_ptr is NULL. |
Get Current Thread
jvmtiError
GetCurrentThread(jvmtiEnv* env,
jthread* thread_ptr)
Get the current thread. The current thread is the Java programming language thread which has called the function. The function may return NULL in the start phase if the can_generate_early_vmstart capability is enabled and the java.lang.Thread class has not been initialized yet.Note that most JVM TI functions that take a thread as an argument will accept NULL to mean the current thread.
may only be called during the start or the live phase
No
18
1.1
Capabilities
Required Functionality
| Name | Type | Description |
|---|---|---|
thread_ptr |
jthread* |
On return, points to the current thread, or NULL.Agent passes a pointer to a jthread. On return, the jthread has been set. The object returned by thread_ptr is a JNI local reference and must be managed. |
| Error | Description |
|---|---|
| JVMTI_ERROR_NULL_POINTER | thread_ptr is NULL. |
Get All Threads
jvmtiError
GetAllThreads(jvmtiEnv* env,
jint* threads_count_ptr,
jthread** threads_ptr)
Get all live platform threads that are attached to the VM. The list of threads includes agent threads. It does not include virtual threads. A thread is live if java.lang.Thread.isAlive() would return true, that is, the thread has been started and has not yet terminated. The universe of threads is determined by the context of the JVM TI environment, which typically is all threads attached to the VM.
may only be called during the live phase
No
4
1.0
Capabilities
Required Functionality
| Name | Type | Description |
|---|---|---|
threads_count_ptr |
jint* |
On return, points to the number of threads.Agent passes a pointer to a jint. On return, the jint has been set. |
threads_ptr |
jthread** |
On return, points to an array of references, one for each thread.Agent passes a pointer to a jthread*. On return, the jthread* points to a newly allocated array of size *threads_count_ptr. The array should be freed with Deallocate. The objects returned by threads_ptr are JNI local references and must be managed. |
| Error | Description |
|---|---|
| JVMTI_ERROR_NULL_POINTER | threads_count_ptr is NULL. |
| JVMTI_ERROR_NULL_POINTER | threads_ptr is NULL. |
Suspend Thread
jvmtiError
SuspendThread(jvmtiEnv* env,
jthread thread)
Suspend the specified thread. If the calling thread is specified, this function will not return until some other thread calls ResumeThread. If the thread is currently suspended, this function does nothing and returns an error.
may only be called during the live phase
No
5
1.0
| Capability | Effect |
|---|---|
| can_suspend | Can suspend and resume threads |
| Name | Type | Description |
|---|---|---|
thread |
jthread |
The thread to suspend. If thread is NULL, the current thread is used. |
| Error | Description |
|---|---|
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_suspend. Use AddCapabilities. |
| JVMTI_ERROR_THREAD_SUSPENDED | Thread already suspended. |
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_THREAD_NOT_ALIVE | thread is not alive (has not been started or has terminated). |
Suspend Thread List
jvmtiError
SuspendThreadList(jvmtiEnv* env,
jint request_count,
const jthread* request_list,
jvmtiError* results)
Suspend the request_count threads specified in the request_list array. Threads may be resumed with ResumeThreadList or ResumeThread. If the calling thread is specified in the request_list array, this function will not return until some other thread resumes it. Errors encountered in the suspension of a thread are returned in the results array, not in the return value of this function. Threads that are currently suspended do not change state.
may only be called during the live phase
No
92
1.0
| Capability | Effect |
|---|---|
| can_suspend | Can suspend and resume threads |
| Name | Type | Description |
|---|---|---|
request_count |
jint |
The number of threads to suspend. |
request_list |
const jthread* |
The list of threads to suspend.Agent passes in an array of request_count elements of jthread. |
results |
jvmtiError* |
An agent supplied array of request_count elements. On return, filled with the error code for the suspend of the corresponding thread. The error code will be JVMTI_ERROR_NONE if the thread was suspended by this call. Possible error codes are those specified for SuspendThread.Agent passes an array large enough to hold request_count elements of jvmtiError. The incoming values of the elements of the array are ignored. On return, the elements are set. |
| Error | Description |
|---|---|
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_suspend. Use AddCapabilities. |
| JVMTI_ERROR_ILLEGAL_ARGUMENT | request_count is less than 0. |
| JVMTI_ERROR_NULL_POINTER | request_list is NULL. |
| JVMTI_ERROR_NULL_POINTER | results is NULL. |
Suspend All Virtual Threads
jvmtiError
SuspendAllVirtualThreads(jvmtiEnv* env,
jint except_count,
const jthread* except_list)
Suspend all virtual threads except those in the exception list. Virtual threads that are currently suspended do not change state. Virtual threads may be resumed with ResumeAllVirtualThreads or ResumeThreadList or ResumeThread.
may only be called during the live phase
No
118
21
| Capability | Effect |
|---|---|
| can_suspend | Can suspend and resume threads |
| can_support_virtual_threads | Can support virtual threads |
| Name | Type | Description |
|---|---|---|
except_count |
jint |
The number of threads in the list of threads not to be suspended. |
except_list |
const jthread * |
The list of threads not to be suspended.Agent passes in an array of except_count elements of jthread. If except_list is NULL, not an error if except_count == 0. |
| Error | Description |
|---|---|
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_suspend. Use AddCapabilities. |
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_support_virtual_threads. Use AddCapabilities. |
| JVMTI_ERROR_INVALID_THREAD | A thread in except_list was invalid. |
| JVMTI_ERROR_NULL_POINTER | Both except_list was NULL and except_count was non-zero. |
| JVMTI_ERROR_ILLEGAL_ARGUMENT | except_count is less than 0. |
Resume Thread
jvmtiError
ResumeThread(jvmtiEnv* env,
jthread thread)
Resume a suspended thread. Any threads currently suspended through a JVM TI suspend function (eg. SuspendThread) will resume execution; all other threads are unaffected.
may only be called during the live phase
No
6
1.0
| Capability | Effect |
|---|---|
| can_suspend | Can suspend and resume threads |
| Name | Type | Description |
|---|---|---|
thread |
jthread |
The thread to resume. |
| Error | Description |
|---|---|
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_suspend. Use AddCapabilities. |
| JVMTI_ERROR_THREAD_NOT_SUSPENDED | Thread was not suspended. |
| JVMTI_ERROR_INVALID_TYPESTATE | The state of the thread has been modified, and is now inconsistent. |
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_THREAD_NOT_ALIVE | thread is not alive (has not been started or has terminated). |
Resume Thread List
jvmtiError
ResumeThreadList(jvmtiEnv* env,
jint request_count,
const jthread* request_list,
jvmtiError* results)
Resume the request_count threads specified in the request_list array. Any thread suspended through a JVM TI suspend function (eg. SuspendThreadList) will resume execution.
may only be called during the live phase
No
93
1.0
| Capability | Effect |
|---|---|
| can_suspend | Can suspend and resume threads |
| Name | Type | Description |
|---|---|---|
request_count |
jint |
The number of threads to resume. |
request_list |
const jthread* |
The threads to resume.Agent passes in an array of request_count elements of jthread. |
results |
jvmtiError* |
An agent supplied array of request_count elements. On return, filled with the error code for the resume of the corresponding thread. The error code will be JVMTI_ERROR_NONE if the thread was suspended by this call. Possible error codes are those specified for ResumeThread.Agent passes an array large enough to hold request_count elements of jvmtiError. The incoming values of the elements of the array are ignored. On return, the elements are set. |
| Error | Description |
|---|---|
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_suspend. Use AddCapabilities. |
| JVMTI_ERROR_ILLEGAL_ARGUMENT | request_count is less than 0. |
| JVMTI_ERROR_NULL_POINTER | request_list is NULL. |
| JVMTI_ERROR_NULL_POINTER | results is NULL. |
Resume All Virtual Threads
jvmtiError
ResumeAllVirtualThreads(jvmtiEnv* env,
jint except_count,
const jthread* except_list)
Resume all virtual threads except those in the exception list. Virtual threads that are currently resumed do not change state. Virtual threads may be suspended with SuspendAllVirtualThreads or SuspendThreadList or SuspendThread.
may only be called during the live phase
No
119
21
| Capability | Effect |
|---|---|
| can_suspend | Can suspend and resume threads |
| can_support_virtual_threads | Can support virtual threads |
| Name | Type | Description |
|---|---|---|
except_count |
jint |
The number of threads in the list of threads not to be resumed. |
except_list |
const jthread * |
The list of threads not to be resumed.Agent passes in an array of except_count elements of jthread. If except_list is NULL, not an error if except_count == 0. |
| Error | Description |
|---|---|
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_suspend. Use AddCapabilities. |
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_support_virtual_threads. Use AddCapabilities. |
| JVMTI_ERROR_INVALID_THREAD | A thread in except_list was invalid. |
| JVMTI_ERROR_NULL_POINTER | Both except_list was NULL and except_count was non-zero. |
| JVMTI_ERROR_ILLEGAL_ARGUMENT | except_count is less than 0. |
Stop Thread
jvmtiError
StopThread(jvmtiEnv* env,
jthread thread,
jobject exception)
Send the specified asynchronous exception to the specified thread.
may only be called during the live phase
No
7
1.0
| Capability | Effect |
|---|---|
| can_signal_thread | Can send stop or interrupt to threads |
| Name | Type | Description |
|---|---|---|
thread |
jthread |
The thread to stop. The StopThread function may be used to send an asynchronous exception to a virtual thread when it is suspended at an event. An implementation may support sending an asynchronous exception to a suspended virtual thread in other cases. |
exception |
jobject |
The asynchronous exception object. |
| Error | Description |
|---|---|
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_signal_thread. Use AddCapabilities. |
| JVMTI_ERROR_THREAD_NOT_SUSPENDED | Thread is a virtual thread and was not suspended and was not the current thread. |
| JVMTI_ERROR_OPAQUE_FRAME | The thread is a suspended virtual thread and the implementation was unable to throw an asynchronous exception from the current frame. |
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_THREAD_NOT_ALIVE | thread is not alive (has not been started or has terminated). |
| JVMTI_ERROR_INVALID_OBJECT | exception is not an object. |
Interrupt Thread
jvmtiError
InterruptThread(jvmtiEnv* env,
jthread thread)
Interrupt the specified thread (similar to java.lang.Thread.interrupt).
may only be called during the live phase
No
8
1.0
| Capability | Effect |
|---|---|
| can_signal_thread | Can send stop or interrupt to threads |
| Name | Type | Description |
|---|---|---|
thread |
jthread |
The thread to interrupt. |
| Error | Description |
|---|---|
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_signal_thread. Use AddCapabilities. |
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_THREAD_NOT_ALIVE | thread is not alive (has not been started or has terminated). |
Get Thread Info
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)
Get thread information. The fields of the jvmtiThreadInfo structure are filled in with details of the specified thread.
may only be called during the live phase
No
9
1.0
Capabilities
Required Functionality
| Field | Type | Description |
|---|---|---|
name |
char* |
The thread name, encoded as a modified UTF-8 string. |
priority |
jint |
The thread priority. See the thread priority constants: jvmtiThreadPriority. The priority of a virtual thread is always JVMTI_THREAD_NORM_PRIORITY. |
is_daemon |
jboolean |
Is this a daemon thread? The daemon status of a virtual thread is always JNI_TRUE. |
thread_group |
jthreadGroup |
The thread group to which this thread belongs. NULL if the thread has terminated. |
context_class_loader |
jobject |
The context class loader associated with this thread. |
| Name | Type | Description |
|---|---|---|
thread |
jthread |
The thread to query. If thread is NULL, the current thread is used. |
info_ptr |
jvmtiThreadInfo* |
On return, filled with information describing the specified thread.Agent passes a pointer to a jvmtiThreadInfo. On return, the jvmtiThreadInfo has been set. The pointer returned in the field name of jvmtiThreadInfo is a newly allocated array. The array should be freed with Deallocate. The object returned in the field thread_group of jvmtiThreadInfo is a JNI local reference and must be managed. The object returned in the field context_class_loader of jvmtiThreadInfo is a JNI local reference and must be managed. |
| Error | Description |
|---|---|
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_NULL_POINTER | info_ptr is NULL. |
Get Owned Monitor Info
jvmtiError
GetOwnedMonitorInfo(jvmtiEnv* env,
jthread thread,
jint* owned_monitor_count_ptr,
jobject** owned_monitors_ptr)
Get information about the monitors owned by the specified thread.
may only be called during the live phase
No
10
1.0
| Capability | Effect |
|---|---|
| can_get_owned_monitor_info | Can get information about ownership of monitors - GetOwnedMonitorInfo |
| Name | Type | Description |
|---|---|---|
thread |
jthread |
The thread to query. If thread is NULL, the current thread is used. |
owned_monitor_count_ptr |
jint* |
The number of monitors returned.Agent passes a pointer to a jint. On return, the jint has been set. |
owned_monitors_ptr |
jobject** |
The array of owned monitors.Agent passes a pointer to a jobject*. On return, the jobject* points to a newly allocated array of size *owned_monitor_count_ptr. The array should be freed with Deallocate. The objects returned by owned_monitors_ptr are JNI local references and must be managed. |
| Error | Description |
|---|---|
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_get_owned_monitor_info. Use AddCapabilities. |
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_THREAD_NOT_ALIVE | thread is not alive (has not been started or has terminated). |
| JVMTI_ERROR_NULL_POINTER | owned_monitor_count_ptr is NULL. |
| JVMTI_ERROR_NULL_POINTER | owned_monitors_ptr is NULL. |
Get Owned Monitor Stack Depth Info
typedef struct { jobject monitor; jint stack_depth; } jvmtiMonitorStackDepthInfo;jvmtiError GetOwnedMonitorStackDepthInfo(jvmtiEnv* env, jthread thread, jint* monitor_info_count_ptr, jvmtiMonitorStackDepthInfo** monitor_info_ptr)
Get information about the monitors owned by the specified thread and the depth of the stack frame which locked them.
may only be called during the live phase
No
153
1.1
| Capability | Effect |
|---|---|
| can_get_owned_monitor_stack_depth_info | Can get information about owned monitors with stack depth - GetOwnedMonitorStackDepthInfo |
| Field | Type | Description |
|---|---|---|
monitor |
jobject |
The owned monitor. |
stack_depth |
jint |
The stack depth. Corresponds to the stack depth used in the Stack Frame functions. That is, zero is the current frame, one is the frame which called the current frame. And it is negative one if the implementation cannot determine the stack depth (e.g., for monitors acquired by JNI MonitorEnter). |
| Name | Type | Description |
|---|---|---|
thread |
jthread |
The thread to query. If thread is NULL, the current thread is used. |
monitor_info_count_ptr |
jint* |
The number of monitors returned.Agent passes a pointer to a jint. On return, the jint has been set. |
monitor_info_ptr |
jvmtiMonitorStackDepthInfo ** |
The array of owned monitor depth information.Agent passes a pointer to a jvmtiMonitorStackDepthInfo*. On return, the jvmtiMonitorStackDepthInfo* points to a newly allocated array of size *monitor_info_count_ptr. The array should be freed with Deallocate. The objects returned in the field monitor of jvmtiMonitorStackDepthInfo are JNI local references and must be managed. |
| Error | Description |
|---|---|
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_get_owned_monitor_stack_depth_info. Use AddCapabilities. |
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_THREAD_NOT_ALIVE | thread is not alive (has not been started or has terminated). |
| JVMTI_ERROR_NULL_POINTER | monitor_info_count_ptr is NULL. |
| JVMTI_ERROR_NULL_POINTER | monitor_info_ptr is NULL. |
Get Current Contended Monitor
jvmtiError
GetCurrentContendedMonitor(jvmtiEnv* env,
jthread thread,
jobject* monitor_ptr)
Get the object, if any, whose monitor the specified thread is waiting to enter or waiting to regain through java.lang.Object.wait.
may only be called during the live phase
No
11
1.0
| Capability | Effect |
|---|---|
| can_get_current_contended_monitor | Can GetCurrentContendedMonitor |
| Name | Type | Description |
|---|---|---|
thread |
jthread |
The thread to query. If thread is NULL, the current thread is used. |
monitor_ptr |
jobject* |
On return, filled with the current contended monitor, or NULL if there is none.Agent passes a pointer to a jobject. On return, the jobject has been set. The object returned by monitor_ptr is a JNI local reference and must be managed. |
| Error | Description |
|---|---|
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_get_current_contended_monitor. Use AddCapabilities. |
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_THREAD_NOT_ALIVE | thread is not alive (has not been started or has terminated). |
| JVMTI_ERROR_NULL_POINTER | monitor_ptr is NULL. |
Agent Start Function
typedef void (JNICALL *jvmtiStartFunction)
(jvmtiEnv* jvmti_env,
JNIEnv* jni_env,
void* arg);
Agent supplied callback function. This function is the entry point for an agent thread started with RunAgentThread.
| Name | Type | Description |
|---|---|---|
jvmti_env |
jvmtiEnv * |
The JVM TI environment. |
jni_env |
JNIEnv * |
The JNI environment. |
arg |
void * |
The arg parameter passed to RunAgentThread. |
Run Agent Thread
jvmtiError
RunAgentThread(jvmtiEnv* env,
jthread thread,
jvmtiStartFunction proc,
const void* arg,
jint priority)
Starts the execution of an agent thread. with the specified native function. The parameter arg is forwarded on to the start function (specified with proc) as its single argument. This function allows the creation of agent threads for handling communication with another process or for handling events without the need to load a special subclass of java.lang.Thread or implementer of java.lang.Runnable. Instead, the created thread can run entirely in native code. However, the created thread does require a newly created instance of java.lang.Thread (referenced by the argument thread) to which it will be associated. The thread object can be created with JNI calls.The following common thread priorities are provided for your convenience:
Thread Priority Constants Constant Value Description JVMTI_THREAD_MIN_PRIORITY1 Minimum possible thread priority JVMTI_THREAD_NORM_PRIORITY5 Normal thread priority JVMTI_THREAD_MAX_PRIORITY10 Maximum possible thread priority
The new thread is started as a daemon thread with the specified priority. If enabled, a ThreadStart event will be sent.Since the thread has been started, the thread will be live when this function returns, unless the thread terminated immediately.The thread group of the thread is ignored -- specifically, the thread is not added to the thread group and the thread is not seen on queries of the thread group at either the Java programming language or JVM TI levels.The thread is not visible to Java programming language queries but is included in JVM TI queries (for example, GetAllThreads and GetAllStackTraces).Upon execution of proc, the new thread will be attached to the VM -- see the JNI documentation on Attaching to the VM.
may only be called during the live phase
No
12
1.0
Capabilities
Required Functionality
| Name | Type | Description |
|---|---|---|
thread |
jthread |
The thread to run. The thread may not be a virtual thread. Otherwise, the error code JVMTI_ERROR_UNSUPPORTED_OPERATION will be returned. |
proc |
jvmtiStartFunction |
The start function. |
arg |
const void * |
The argument to the start function.Agent passes in a pointer. If arg is NULL, NULL is passed to the start function. |
priority |
jint |
The priority of the started thread. Any thread priority allowed by java.lang.Thread.setPriority can be used including those in jvmtiThreadPriority. |
| Error | Description |
|---|---|
| JVMTI_ERROR_INVALID_PRIORITY | priority is less than JVMTI_THREAD_MIN_PRIORITY or greater than JVMTI_THREAD_MAX_PRIORITY |
| JVMTI_ERROR_UNSUPPORTED_OPERATION | thread is a virtual thread. |
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_NULL_POINTER | proc is NULL. |
Set Thread Local Storage
jvmtiError
SetThreadLocalStorage(jvmtiEnv* env,
jthread thread,
const void* data)
The VM stores a pointer value associated with each environment-thread pair. This pointer value is called thread-local storage. This value is NULL unless set with this function. Agents can allocate memory in which they store thread specific information. By setting thread-local storage it can then be accessed with GetThreadLocalStorage.This function is called by the agent to set the value of the JVM TI thread-local storage. JVM TI supplies to the agent a pointer-size thread-local storage that can be used to record per-thread information.
may only be called during the start or the live phase
No
103
1.0
Capabilities
Required Functionality
| Name | Type | Description |
|---|---|---|
thread |
jthread |
Store to this thread. If thread is NULL, the current thread is used. |
data |
const void * |
The value to be entered into the thread-local storage.Agent passes in a pointer. If data is NULL, value is set to NULL. |
| Error | Description |
|---|---|
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_THREAD_NOT_ALIVE | thread is not alive (has not been started or has terminated). |
Get Thread Local Storage
jvmtiError
GetThreadLocalStorage(jvmtiEnv* env,
jthread thread,
void** data_ptr)
Called by the agent to get the value of the JVM TI thread-local storage.
may only be called during the start or the live phase
No
102
1.0
Capabilities
Required Functionality
| Name | Type | Description |
|---|---|---|
thread |
jthread |
Retrieve from this thread. If thread is NULL, the current thread is used. |
data_ptr |
void** |
Pointer through which the value of the thread local storage is returned. If thread-local storage has not been set with SetThreadLocalStorage the returned pointer is NULL. |
| Error | Description |
|---|---|
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_THREAD_NOT_ALIVE | thread is not alive (has not been started or has terminated). |
| JVMTI_ERROR_NULL_POINTER | data_ptr is NULL. |
Thread Group
Thread Group functions:
Thread Group types:
- jvmtiThreadGroupInfo - Thread group information structure
Get Top Thread Groups
jvmtiError
GetTopThreadGroups(jvmtiEnv* env,
jint* group_count_ptr,
jthreadGroup** groups_ptr)
Return all top-level (parentless) thread groups in the VM.
may only be called during the live phase
No
13
1.0
Capabilities
Required Functionality
| Name | Type | Description |
|---|---|---|
group_count_ptr |
jint* |
On return, points to the number of top-level thread groups.Agent passes a pointer to a jint. On return, the jint has been set. |
groups_ptr |
jthreadGroup** |
On return, refers to a pointer to the top-level thread group array.Agent passes a pointer to a jthreadGroup*. On return, the jthreadGroup* points to a newly allocated array of size *group_count_ptr. The array should be freed with Deallocate. The objects returned by groups_ptr are JNI local references and must be managed. |
| Error | Description |
|---|---|
| JVMTI_ERROR_NULL_POINTER | group_count_ptr is NULL. |
| JVMTI_ERROR_NULL_POINTER | groups_ptr is NULL. |
Get Thread Group Info
typedef struct { jthreadGroup parent; char* name; jint max_priority; jboolean is_daemon; } jvmtiThreadGroupInfo;jvmtiError GetThreadGroupInfo(jvmtiEnv* env, jthreadGroup group, jvmtiThreadGroupInfo* info_ptr)
Get information about the thread group. The fields of the jvmtiThreadGroupInfo structure are filled in with details of the specified thread group.
may only be called during the live phase
No
14
1.0
Capabilities
Required Functionality
| Field | Type | Description |
|---|---|---|
parent |
jthreadGroup |
The parent thread group. |
name |
char* |
The thread group's name, encoded as a modified UTF-8 string. |
max_priority |
jint |
The maximum priority for this thread group. |
is_daemon |
jboolean |
Is this a daemon thread group? |
| Name | Type | Description |
|---|---|---|
group |
jthreadGroup |
The thread group to query. |
info_ptr |
jvmtiThreadGroupInfo* |
On return, filled with information describing the specified thread group.Agent passes a pointer to a jvmtiThreadGroupInfo. On return, the jvmtiThreadGroupInfo has been set. The object returned in the field parent of jvmtiThreadGroupInfo is a JNI local reference and must be managed. The pointer returned in the field name of jvmtiThreadGroupInfo is a newly allocated array. The array should be freed with Deallocate. |
| Error | Description |
|---|---|
| JVMTI_ERROR_INVALID_THREAD_GROUP | group is not a thread group object. |
| JVMTI_ERROR_NULL_POINTER | info_ptr is NULL. |
Get Thread Group Children
jvmtiError
GetThreadGroupChildren(jvmtiEnv* env,
jthreadGroup group,
jint* thread_count_ptr,
jthread** threads_ptr,
jint* group_count_ptr,
jthreadGroup** groups_ptr)
Get the live platform threads and the child thread groups in this thread group. Virtual threads are not returned by this function.
may only be called during the live phase
No
15
1.0
Capabilities
Required Functionality
| Name | Type | Description |
|---|---|---|
group |
jthreadGroup |
The group to query. |
thread_count_ptr |
jint* |
On return, points to the number of live threads in this thread group.Agent passes a pointer to a jint. On return, the jint has been set. |
threads_ptr |
jthread** |
On return, points to an array of the live threads in this thread group.Agent passes a pointer to a jthread*. On return, the jthread* points to a newly allocated array of size *thread_count_ptr. The array should be freed with Deallocate. The objects returned by threads_ptr are JNI local references and must be managed. |
group_count_ptr |
jint* |
On return, points to the number of child thread groupsAgent passes a pointer to a jint. On return, the jint has been set. |
groups_ptr |
jthreadGroup** |
On return, points to an array of the child thread groups.Agent passes a pointer to a jthreadGroup*. On return, the jthreadGroup* points to a newly allocated array of size *group_count_ptr. The array should be freed with Deallocate. The objects returned by groups_ptr are JNI local references and must be managed. |
| Error | Description |
|---|---|
| JVMTI_ERROR_INVALID_THREAD_GROUP | group is not a thread group object. |
| JVMTI_ERROR_NULL_POINTER | thread_count_ptr is NULL. |
| JVMTI_ERROR_NULL_POINTER | threads_ptr is NULL. |
| JVMTI_ERROR_NULL_POINTER | group_count_ptr is NULL. |
| JVMTI_ERROR_NULL_POINTER | groups_ptr is NULL. |
Stack Frame
Stack Frame functions:
- Get Stack Trace
- Get All Stack Traces
- Get Thread List Stack Traces
- Get Frame Count
- Pop Frame
- Get Frame Location
- Notify Frame Pop
Stack Frame types:
- jvmtiFrameInfo - Stack frame information structure
- jvmtiStackInfo - Stack information structure
These functions provide information about the stack of a thread. Stack frames are referenced by depth. The frame at depth zero is the current frame.Stack frames are as described in The Java™ Virtual Machine Specification, Chapter 3.6, That is, they correspond to method invocations (including native methods) but do not correspond to platform native or VM internal frames.A JVM TI implementation may use method invocations to launch a thread and the corresponding frames may be included in the stack as presented by these functions -- that is, there may be frames shown deeper than main() and run(). However this presentation must be consistent across all JVM TI functionality which uses stack frames or stack depth.
Stack frame information structure
Information about a stack frame is returned in this structure.
typedef struct { jmethodID method; jlocation location; } jvmtiFrameInfo;
jvmtiFrameInfo- Stack frame information structureField Type Description methodjmethodIDThe method executing in this frame. locationjlocationThe index of the instruction executing in this frame. -1if the frame is executing a native method.
Stack information structure
Information about a set of stack frames is returned in this structure.
typedef struct { jthread thread; jint state; jvmtiFrameInfo* frame_buffer; jint frame_count; } jvmtiStackInfo;
jvmtiStackInfo- Stack information structureField Type Description threadjthreadOn return, the thread traced. statejintOn return, the thread state. See GetThreadState. frame_bufferjvmtiFrameInfo *On return, this agent allocated buffer is filled with stack frame information. frame_countjintOn return, the number of records filled into frame_buffer. This will be min(max_frame_count, stackDepth).
Get Stack Trace
jvmtiError
GetStackTrace(jvmtiEnv* env,
jthread thread,
jint start_depth,
jint max_frame_count,
jvmtiFrameInfo* frame_buffer,
jint* count_ptr)
Get information about the stack of a thread. If max_frame_count is less than the depth of the stack, the max_frame_count topmost frames are returned, otherwise the entire stack is returned. The topmost frames, those most recently invoked, are at the beginning of the returned buffer.The following example causes up to five of the topmost frames to be returned and (if there are any frames) the currently executing method name to be printed.
jvmtiFrameInfo frames[5];
jint count;
jvmtiError err;
err = (*jvmti)->GetStackTrace(jvmti, aThread, 0, 5,
frames, &count);
if (err == JVMTI_ERROR_NONE && count >= 1) {
char *methodName;
err = (*jvmti)->GetMethodName(jvmti, frames[0].method,
&methodName, NULL, NULL);
if (err == JVMTI_ERROR_NONE) {
printf("Executing method: %s", methodName);
}
}
The thread need not be suspended to call this function.The GetLineNumberTable function can be used to map locations to line numbers. Note that this mapping can be done lazily.
may only be called during the live phase
No
104
1.0
Capabilities
Required Functionality
| Name | Type | Description |
|---|---|---|
thread |
jthread |
Fetch the stack trace of this thread. If thread is NULL, the current thread is used. |
start_depth |
jint |
Begin retrieving frames at this depth. If non-negative, count from the current frame, the first frame retrieved is at depth start_depth. For example, if zero, start from the current frame; if one, start from the caller of the current frame; if two, start from the caller of the caller of the current frame; and so on. If negative, count from below the oldest frame, the first frame retrieved is at depth stackDepth + start_depth, where stackDepth is the count of frames on the stack. For example, if negative one, only the oldest frame is retrieved; if negative two, start from the frame called by the oldest frame. |
max_frame_count |
jint |
The maximum number of jvmtiFrameInfo records to retrieve. |
frame_buffer |
jvmtiFrameInfo * |
On return, this agent allocated buffer is filled with stack frame information.Agent passes an array large enough to hold max_frame_count elements of jvmtiFrameInfo. The incoming values of the elements of the array are ignored. On return, *count_ptr of the elements are set. |
count_ptr |
jint* |
On return, points to the number of records filled in. For non-negative start_depth, this will be min(max_frame_count, stackDepth - start_depth). For negative start_depth, this will be min(max_frame_count, -start_depth).Agent passes a pointer to a jint. On return, the jint has been set. |
| Error | Description |
|---|---|
| JVMTI_ERROR_ILLEGAL_ARGUMENT | start_depth is positive and greater than or equal to stackDepth. Or start_depth is negative and less than -stackDepth. |
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_THREAD_NOT_ALIVE | thread is not alive (has not been started or has terminated). |
| JVMTI_ERROR_ILLEGAL_ARGUMENT | max_frame_count is less than 0. |
| JVMTI_ERROR_NULL_POINTER | frame_buffer is NULL. |
| JVMTI_ERROR_NULL_POINTER | count_ptr is NULL. |
Get All Stack Traces
jvmtiError
GetAllStackTraces(jvmtiEnv* env,
jint max_frame_count,
jvmtiStackInfo** stack_info_ptr,
jint* thread_count_ptr)
Get the stack traces of all live platform threads attached to the VM. The list includes the stack traces of agent threads. It does not include the stack traces of virtual threads.If max_frame_count is less than the depth of a stack, the max_frame_count topmost frames are returned for that thread, otherwise the entire stack is returned. The topmost frames, those most recently invoked, are at the beginning of the returned buffer.All stacks are collected simultaneously, that is, no changes will occur to the thread state or stacks between the sampling of one thread and the next. The threads need not be suspended.
jvmtiStackInfo *stack_info;
jint thread_count;
int ti;
jvmtiError err;
err = (*jvmti)->GetAllStackTraces(jvmti, MAX_FRAMES, &stack_info, &thread_count);
if (err != JVMTI_ERROR_NONE) {
...
}
for (ti = 0; ti < thread_count; ++ti) {
jvmtiStackInfo *infop = &stack_info[ti];
jthread thread = infop->thread;
jint state = infop->state;
jvmtiFrameInfo *frames = infop->frame_buffer;
int fi;
myThreadAndStatePrinter(thread, state);
for (fi = 0; fi < infop->frame_count; fi++) {
myFramePrinter(frames[fi].method, frames[fi].location);
}
}
/* this one Deallocate call frees all data allocated by GetAllStackTraces */
err = (*jvmti)->Deallocate(jvmti, stack_info);
may only be called during the live phase
No
100
1.0
Capabilities
Required Functionality
| Name | Type | Description |
|---|---|---|
max_frame_count |
jint |
The maximum number of jvmtiFrameInfo records to retrieve per thread. |
stack_info_ptr |
jvmtiStackInfo ** |
On return, this buffer is filled with stack information for each thread. The number of jvmtiStackInfo records is determined by thread_count_ptr.Note that this buffer is allocated to include the jvmtiFrameInfo buffers pointed to by jvmtiStackInfo.frame_buffer. These buffers must not be separately deallocated.Agent passes a pointer to a jvmtiStackInfo*. On return, the jvmtiStackInfo* points to a newly allocated array. The array should be freed with Deallocate. The objects returned in the field thread of jvmtiStackInfo are JNI local references and must be managed. |
thread_count_ptr |
jint* |
The number of threads traced.Agent passes a pointer to a jint. On return, the jint has been set. |
| Error | Description |
|---|---|
| JVMTI_ERROR_ILLEGAL_ARGUMENT | max_frame_count is less than 0. |
| JVMTI_ERROR_NULL_POINTER | stack_info_ptr is NULL. |
| JVMTI_ERROR_NULL_POINTER | thread_count_ptr is NULL. |
Get Thread List Stack Traces
jvmtiError
GetThreadListStackTraces(jvmtiEnv* env,
jint thread_count,
const jthread* thread_list,
jint max_frame_count,
jvmtiStackInfo** stack_info_ptr)
Get information about the stacks of the supplied threads. If max_frame_count is less than the depth of a stack, the max_frame_count topmost frames are returned for that thread, otherwise the entire stack is returned. The topmost frames, those most recently invoked, are at the beginning of the returned buffer.All stacks are collected simultaneously, that is, no changes will occur to the thread state or stacks between the sampling one thread and the next. The threads need not be suspended.If a thread has not yet started or terminates before the stack information is collected, a zero length stack (jvmtiStackInfo.frame_count will be zero) will be returned and the thread jvmtiStackInfo.state can be checked.See the example for the similar function GetAllStackTraces.
may only be called during the live phase
No
101
1.0
Capabilities
Required Functionality
| Name | Type | Description |
|---|---|---|
thread_count |
jint |
The number of threads to trace. |
thread_list |
const jthread* |
The list of threads to trace.Agent passes in an array of thread_count elements of jthread. |
max_frame_count |
jint |
The maximum number of jvmtiFrameInfo records to retrieve per thread. |
stack_info_ptr |
jvmtiStackInfo ** |
On return, this buffer is filled with stack information for each thread. The number of jvmtiStackInfo records is determined by thread_count.Note that this buffer is allocated to include the jvmtiFrameInfo buffers pointed to by jvmtiStackInfo.frame_buffer. These buffers must not be separately deallocated.Agent passes a pointer to a jvmtiStackInfo*. On return, the jvmtiStackInfo* points to a newly allocated array of size *thread_count. The array should be freed with Deallocate. The objects returned in the field thread of jvmtiStackInfo are JNI local references and must be managed. |
| Error | Description |
|---|---|
| JVMTI_ERROR_INVALID_THREAD | An element in thread_list is not a thread object. |
| JVMTI_ERROR_ILLEGAL_ARGUMENT | thread_count is less than 0. |
| JVMTI_ERROR_NULL_POINTER | thread_list is NULL. |
| JVMTI_ERROR_ILLEGAL_ARGUMENT | max_frame_count is less than 0. |
| JVMTI_ERROR_NULL_POINTER | stack_info_ptr is NULL. |
Get Frame Count
jvmtiError
GetFrameCount(jvmtiEnv* env,
jthread thread,
jint* count_ptr)
Get the number of frames currently in the specified thread's call stack.If this function is called for a thread actively executing bytecodes (for example, not the current thread and not suspended), the information returned is transient.
may only be called during the live phase
No
16
1.0
Capabilities
Required Functionality
| Name | Type | Description |
|---|---|---|
thread |
jthread |
The thread to query. If thread is NULL, the current thread is used. |
count_ptr |
jint* |
On return, points to the number of frames in the call stack.Agent passes a pointer to a jint. On return, the jint has been set. |
| Error | Description |
|---|---|
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_THREAD_NOT_ALIVE | thread is not alive (has not been started or has terminated). |
| JVMTI_ERROR_NULL_POINTER | count_ptr is NULL. |
Pop Frame
jvmtiError
PopFrame(jvmtiEnv* env,
jthread thread)
Pop the current frame of thread's stack. Popping a frame takes you to the previous frame. When the thread is resumed, the execution state of the thread is reset to the state immediately before the called method was invoked. That is (using The Java™ Virtual Machine Specification terminology):
- the current frame is discarded as the previous frame becomes the current one
- the operand stack is restored--the argument values are added back and if the invoke was not
invokestatic,objectrefis added back as well - the Java virtual machine PC is restored to the opcode of the invoke instruction
Note however, that any changes to the arguments, which occurred in the called method, remain; when execution continues, the first instruction to execute will be the invoke.Between calling PopFrame and resuming the thread the state of the stack is undefined. To pop frames beyond the first, these three steps must be repeated:
- suspend the thread via an event (step, breakpoint, ...)
- call
PopFrame - resume the thread
A lock acquired by calling the called method (if it is a synchronized method) and locks acquired by entering synchronized blocks within the called method are released. Note: this does not apply to native locks or java.util.concurrent.locks locks.Finally blocks are not executed.Changes to global state are not addressed and thus remain changed.The specified thread must be suspended or must be the current thread.Both the called method and calling method must be non-native Java programming language methods.No JVM TI events are generated by this function.
may only be called during the live phase
No
80
1.0
| Capability | Effect |
|---|---|
| can_pop_frame | Can pop frames off the stack - PopFrame |
| Name | Type | Description |
|---|---|---|
thread |
jthread |
The thread whose current frame is to be popped. The PopFrame function may be used to pop the current frame of a virtual thread when it is suspended at an event. An implementation may support popping the current frame of a suspended virtual thread in other cases. |
| Error | Description |
|---|---|
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_pop_frame. Use AddCapabilities. |
| JVMTI_ERROR_OPAQUE_FRAME | Called or calling method is a native method. The implementation is unable to pop this frame. |
| JVMTI_ERROR_OPAQUE_FRAME | The thread is a suspended virtual thread and the implementation was unable to pop the current frame. |
| JVMTI_ERROR_THREAD_NOT_SUSPENDED | Thread was not suspended and was not the current thread. |
| JVMTI_ERROR_NO_MORE_FRAMES | There are less than two stack frames on the call stack. |
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_THREAD_NOT_ALIVE | thread is not alive (has not been started or has terminated). |
Get Frame Location
jvmtiError
GetFrameLocation(jvmtiEnv* env,
jthread thread,
jint depth,
jmethodID* method_ptr,
jlocation* location_ptr)
For a Java programming language frame, return the location of the instruction currently executing.
may only be called during the live phase
No
19
1.0
Capabilities
Required Functionality
| Name | Type | Description |
|---|---|---|
thread |
jthread |
The thread of the frame to query. If thread is NULL, the current thread is used. |
depth |
jint |
The depth of the frame to query. |
method_ptr |
jmethodID* |
On return, points to the method for the current location.Agent passes a pointer to a jmethodID. On return, the jmethodID has been set. |
location_ptr |
jlocation* |
On return, points to the index of the currently executing instruction. Is set to -1 if the frame is executing a native method.Agent passes a pointer to a jlocation. On return, the jlocation has been set. |
| Error | Description |
|---|---|
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_THREAD_NOT_ALIVE | thread is not alive (has not been started or has terminated). |
| JVMTI_ERROR_ILLEGAL_ARGUMENT | depth is less than zero. |
| JVMTI_ERROR_NO_MORE_FRAMES | There are no stack frames at the specified depth. |
| JVMTI_ERROR_NULL_POINTER | method_ptr is NULL. |
| JVMTI_ERROR_NULL_POINTER | location_ptr is NULL. |
Notify Frame Pop
jvmtiError
NotifyFramePop(jvmtiEnv* env,
jthread thread,
jint depth)
When the frame that is currently at depth is popped from the stack, generate a FramePop event. See the FramePop event for details. Only frames corresponding to non-native Java programming language methods can receive notification.The specified thread must be suspended or must be the current thread.
may only be called during the live phase
No
20
1.0
| Capability | Effect |
|---|---|
| can_generate_frame_pop_events | Can set and thus get FramePop events |
| Name | Type | Description |
|---|---|---|
thread |
jthread |
The thread of the frame for which the frame pop event will be generated. If thread is NULL, the current thread is used. |
depth |
jint |
The depth of the frame for which the frame pop event will be generated. |
| Error | Description |
|---|---|
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_generate_frame_pop_events. Use AddCapabilities. |
| JVMTI_ERROR_OPAQUE_FRAME | The frame at depth is executing a native method. |
| JVMTI_ERROR_THREAD_NOT_SUSPENDED | Thread was not suspended and was not the current thread. |
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_THREAD_NOT_ALIVE | thread is not alive (has not been started or has terminated). |
| JVMTI_ERROR_ILLEGAL_ARGUMENT | depth is less than zero. |
| JVMTI_ERROR_NO_MORE_FRAMES | There are no stack frames at the specified depth. |
Force Early Return
Force Early Return functions:
- Force Early Return - Object
- Force Early Return - Int
- Force Early Return - Long
- Force Early Return - Float
- Force Early Return - Double
- Force Early Return - Void
These functions allow an agent to force a return from the current frame. The specified thread must be suspended or must be the current thread. These functions may be used to force a return from the current frame of a virtual thread when it is suspended at an event. An implementation may support forcing a return from the current frame of a suspended virtual thread in other cases. The method which will return early is referred to as the called method. The called method is the current method (as defined by The Java™ Virtual Machine Specification, Chapter 3.6) for the specified thread at the time the function is called.The return occurs when execution of Java programming language code is resumed on this thread. Between calling one of these functions and resumption of thread execution, the state of the stack is undefined.No further instructions are executed in the called method. Specifically, finally blocks are not executed. Note: this can cause inconsistent states in the application.A lock acquired by calling the called method (if it is a synchronized method) and locks acquired by entering synchronized blocks within the called method are released. Note: this does not apply to native locks or java.util.concurrent.locks locks.Events, such as MethodExit, are generated as they would be in a normal return.The called method must be a non-native Java programming language method. Forcing return on a thread with only one frame on the stack causes the thread to exit when resumed.
Force Early Return - Object
jvmtiError
ForceEarlyReturnObject(jvmtiEnv* env,
jthread thread,
jobject value)
This function can be used to return from a method whose result type is Object or a subclass of Object.
may only be called during the live phase
No
81
1.1
| Capability | Effect |
|---|---|
| can_force_early_return | Can return early from a method, as described in the Force Early Return category. |
| Name | Type | Description |
|---|---|---|
thread |
jthread |
The thread whose current frame is to return early. If thread is NULL, the current thread is used. |
value |
jobject |
The return value for the called frame. An object or NULL. |
| Error | Description |
|---|---|
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_force_early_return. Use AddCapabilities. |
| JVMTI_ERROR_OPAQUE_FRAME | Attempted to return early from a frame corresponding to a native method. The thread is a suspended virtual thread and the implementation was unable to force its current frame to return. Or the implementation is unable to provide this functionality on this frame. |
| JVMTI_ERROR_TYPE_MISMATCH | The result type of the called method is not Object or a subclass of Object. |
| JVMTI_ERROR_TYPE_MISMATCH | The supplied value is not compatible with the result type of the called method. |
| JVMTI_ERROR_THREAD_NOT_SUSPENDED | Thread was not suspended and was not the current thread. |
| JVMTI_ERROR_NO_MORE_FRAMES | There are no more frames on the call stack. |
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_THREAD_NOT_ALIVE | thread is not alive (has not been started or has terminated). |
| JVMTI_ERROR_INVALID_OBJECT | value is not an object. |
Force Early Return - Int
jvmtiError
ForceEarlyReturnInt(jvmtiEnv* env,
jthread thread,
jint value)
This function can be used to return from a method whose result type is int, short, char, byte, or boolean.
may only be called during the live phase
No
82
1.1
| Capability | Effect |
|---|---|
| can_force_early_return | Can return early from a method, as described in the Force Early Return category. |
| Name | Type | Description |
|---|---|---|
thread |
jthread |
The thread whose current frame is to return early. If thread is NULL, the current thread is used. |
value |
jint |
The return value for the called frame. |
| Error | Description |
|---|---|
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_force_early_return. Use AddCapabilities. |
| JVMTI_ERROR_OPAQUE_FRAME | Attempted to return early from a frame corresponding to a native method. The thread is a suspended virtual thread and the implementation was unable to force its current frame to return. Or the implementation is unable to provide this functionality on this frame. |
| JVMTI_ERROR_TYPE_MISMATCH | The result type of the called method is not int, short, char, byte, or boolean. |
| JVMTI_ERROR_THREAD_NOT_SUSPENDED | Thread was not suspended and was not the current thread. |
| JVMTI_ERROR_NO_MORE_FRAMES | There are no frames on the call stack. |
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_THREAD_NOT_ALIVE | thread is not alive (has not been started or has terminated). |
Force Early Return - Long
jvmtiError
ForceEarlyReturnLong(jvmtiEnv* env,
jthread thread,
jlong value)
This function can be used to return from a method whose result type is long.
may only be called during the live phase
No
83
1.1
| Capability | Effect |
|---|---|
| can_force_early_return | Can return early from a method, as described in the Force Early Return category. |
| Name | Type | Description |
|---|---|---|
thread |
jthread |
The thread whose current frame is to return early. If thread is NULL, the current thread is used. |
value |
jlong |
The return value for the called frame. |
| Error | Description |
|---|---|
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_force_early_return. Use AddCapabilities. |
| JVMTI_ERROR_OPAQUE_FRAME | Attempted to return early from a frame corresponding to a native method. The thread is a suspended virtual thread and the implementation was unable to force its current frame to return. Or the implementation is unable to provide this functionality on this frame. |
| JVMTI_ERROR_TYPE_MISMATCH | The result type of the called method is not long. |
| JVMTI_ERROR_THREAD_NOT_SUSPENDED | Thread was not suspended and was not the current thread. |
| JVMTI_ERROR_NO_MORE_FRAMES | There are no frames on the call stack. |
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_THREAD_NOT_ALIVE | thread is not alive (has not been started or has terminated). |
Force Early Return - Float
jvmtiError
ForceEarlyReturnFloat(jvmtiEnv* env,
jthread thread,
jfloat value)
This function can be used to return from a method whose result type is float.
may only be called during the live phase
No
84
1.1
| Capability | Effect |
|---|---|
| can_force_early_return | Can return early from a method, as described in the Force Early Return category. |
| Name | Type | Description |
|---|---|---|
thread |
jthread |
The thread whose current frame is to return early. If thread is NULL, the current thread is used. |
value |
jfloat |
The return value for the called frame. |
| Error | Description |
|---|---|
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_force_early_return. Use AddCapabilities. |
| JVMTI_ERROR_OPAQUE_FRAME | Attempted to return early from a frame corresponding to a native method. The thread is a suspended virtual thread and the implementation was unable to force its current frame to return. Or the implementation is unable to provide this functionality on this frame. |
| JVMTI_ERROR_TYPE_MISMATCH | The result type of the called method is not float. |
| JVMTI_ERROR_THREAD_NOT_SUSPENDED | Thread was not suspended and was not the current thread. |
| JVMTI_ERROR_NO_MORE_FRAMES | There are no frames on the call stack. |
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_THREAD_NOT_ALIVE | thread is not alive (has not been started or has terminated). |
Force Early Return - Double
jvmtiError
ForceEarlyReturnDouble(jvmtiEnv* env,
jthread thread,
jdouble value)
This function can be used to return from a method whose result type is double.
may only be called during the live phase
No
85
1.1
| Capability | Effect |
|---|---|
| can_force_early_return | Can return early from a method, as described in the Force Early Return category. |
| Name | Type | Description |
|---|---|---|
thread |
jthread |
The thread whose current frame is to return early. If thread is NULL, the current thread is used. |
value |
jdouble |
The return value for the called frame. |
| Error | Description |
|---|---|
| JVMTI_ERROR_MUST_POSSESS_CAPABILITY | The environment does not possess the capability can_force_early_return. Use AddCapabilities. |
| JVMTI_ERROR_OPAQUE_FRAME | Attempted to return early from a frame corresponding to a native method. The thread is a suspended virtual thread and the implementation was unable to force its current frame to return. Or the implementation is unable to provide this functionality on this frame. |
| JVMTI_ERROR_TYPE_MISMATCH | The result type of the called method is not double. |
| JVMTI_ERROR_THREAD_NOT_SUSPENDED | Thread was not suspended and was not the current thread. |
| JVMTI_ERROR_NO_MORE_FRAMES | There are no frames on the call stack. |
| JVMTI_ERROR_INVALID_THREAD | thread is not a thread object. |
| JVMTI_ERROR_THREAD_NOT_ALIVE | thread is not alive (has not been started or has terminated). |
Force Early Return - Void
jvmtiError
ForceEarlyReturnVoid(jvmtiEnv* env,
jthread thread)
更多推荐

所有评论(0)