JVMTM Tool InterfaceVersion 1.0 |
jvmti.h.
To use these definitions add the J2SETM include directory
to your include path and add
#include <jvmti.h>
to your source code.
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>
-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 the SolarisTM operating environment.
-agentpath:<path-to-agent>=<options>
-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.
-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.
This function will be called by the VM when the library is loaded. The VM should load the library early enough in VM initialization that:JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
Agent_OnLoad 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
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 provides 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 fromAgent_OnLoad is used to indicate an error.
Any value other than zero indicates an error and causes termination of the VM.
This function will be called by the VM when the library is about to be unloaded. The library will be unloaded 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 whether through normal termination or VM failure, including start-up failure. Uncontrolled shutdown is, of couse, an exception to this rule. 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 forJNIEXPORT void JNICALL Agent_OnUnload(JavaVM *vm)
Agent_OnUnload 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 during
Agent_OnLoad.
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:
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.
GetEnv from
Agent_OnLoad.
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:
*.class files 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.
ClassFileLoadHook
event provides this functionality. This mechanism provides efficient
and complete access to one-time instrumentation.
RedefineClasses 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.
ClassFileLoadHook event
and the RedefineClasses function)
is intended to provide a mechanism for instrumentation (described above)
and, during development, for fix-and-continue debugging.
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);
}
}
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 supposed 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.
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.
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.
Allocate an area of memory through the JVM TI allocator.
The allocated
memory should be freed with Deallocate.
This function may
be called during any
phase.
This function may be called from the callbacks to the
Heap iteration functions, or from the
event handles for the
GarbageCollectionStart,
GarbageCollectionFinish,
and ObjectFree events.
|
||||||||||||||||||||||||||||
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.
This function may
be called during any
phase.
This function may be called from the callbacks to the
Heap iteration functions, or from the
event handles for the
GarbageCollectionStart,
GarbageCollectionFinish,
and ObjectFree events.
|
|||||||||||||||||
jvmtiThreadInfo - Thread information structure
Get the state of a thread. The state of the thread is represented by the
answers to the hierarchical set of questions below:
The following definitions are used to convert JVM TI thread state to java.lang.Thread.State style states.
Rules There 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_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 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_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_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.
Examples
Note that the values below exclude reserved and vendor bits.
The state of a thread blocked at a synchronized-statement would be:
The state of a thread which hasn't started yet would be:
The state of a thread at a Object.wait(3000) would be:
The state of a thread suspended while runnable would be:
Testing the State
In 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:
For waiting (that is, in Object.wait, parked, or sleeping) it would be:
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:
To distinguish timed from untimed Object.wait:
Relationship to java.lang.Thread.State
The 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:
This function may
only be called during the live
phase.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Get all live threads.
The threads are Java programming language threads;
that is, threads that are attached to the VM.
A thread is live if java.lang.Thread.isAlive()
would return true, that is, the thread has
been started and has not yet died.
The universe of threads is determined by the context of the JVM TI
environment, which typically is all threads attached to the VM.
Note that this includes JVM TI agent threads
(see RunAgentThread).
This function may
only be called during the live
phase.
|
||||||||||||||||||||||||||
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.
This function may
only be called during the live
phase.
|
|||||||||||||||||||||||||||||||
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 are not suspended.
This function may
only be called during the live
phase.
|
|||||||||||||||||||||||||||||||||||||
Resume a suspended thread.
Any threads currently suspended through
a JVM TI suspend function (eg.
SuspendThread)
or java.lang.Thread.suspend()
will resume execution;
all other threads are unaffected.
This function may
only be called during the live
phase.
|
|||||||||||||||||||||||||||||||||
Resume the request_count
threads specified in the
request_list array.
Any thread suspended through
a JVM TI suspend function (eg.
SuspendThreadList)
or java.lang.Thread.suspend()
will resume execution.
This function may
only be called during the live
phase.
|
|||||||||||||||||||||||||||||||||||||
Send the specified asynchronous exception to the specified thread
(similar to java.lang.Thread.stop).
Normally, this function is used to kill the specified thread with an
instance of the exception ThreadDeath.
This function may
only be called during the live
phase.
|
||||||||||||||||||||||||||||||||||
Interrupt the specified thread
(similar to java.lang.Thread.interrupt).
This function may
only be called during the live
phase.
|
|||||||||||||||||||||||||||||
Get thread information. The fields of the jvmtiThreadInfo structure
are filled in with details of the specified thread.
This function may
only be called during the live
phase.
|
|||||||||||||||||||||||||||||||||||||||||||||||
Get information about the monitors owned by the
specified thread.
This function may
only be called during the live
phase.
|
|||||||||||||||||||||||||||||||||||||||
Get the object, if any, whose monitor the specified thread is waiting to
enter or waiting to regain through java.lang.Object.wait.
This function may
only be called during the live
phase.
|
||||||||||||||||||||||||||||||||||
Agent supplied callback function.
This function is the entry point for an agent thread
started with
RunAgentThread.
|
|||||||||||||||
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.
Ideally,
all calls to Java programming language
code should be done during the callback for the
VMInit event
to avoid any interaction with the target application.
The following thread priorities are useful:
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 has died 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.
This function may
only be called during the live
phase.
|
|||||||||||||||||||||||||||||||||||||||||||||||||
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.
This function may
only be called during the start or the live
phase.
|
||||||||||||||||||||||||||
Called by the agent to get the value of the JVM TI thread-local
storage.
This function may
only be called during the start or the live
phase.
|
||||||||||||||||||||||||||||
jvmtiThreadGroupInfo - Thread group information structure
Return all top-level (parentless) thread groups in the VM.
This function may
only be called during the live
phase.
|
||||||||||||||||||||||||||
Get information about th |