Archive for JVMTI

The Java Virtual Machine Tool Interface (JVMTI)

Posted in Java with tags , on November 17, 2006 by wsjoung

JVMTI is a new native interface available in J2SDK1.5.0. JVMPI is still also available though, SUN plan to drop JVMPI soon or later.

“JVMTI provides for all the functional capabilities of the previous native interfaces JVMDI and JVMPI. However, it does not have many of the limitations of those older interfaces. Some of the JVMPI capabilities require the use of JVMTI and the technique called Byte Code Insertion (BCI), sometimes referred to as Byte Code Injection or Byte Code Instrumentation. JVMTI allows for all JVM functionality to continue to operate, like JIT or JVM compilation and different GC implementations. Certain JVMTI features are controlled by asking for JVMTI Capabilities, and some of these can cause changes in JVM performance, but most features are available while the JVM is running “full speed”. All JVMTI object handles are JNI handles, and JVMTI Event callbacks always include a JNIEnv* argument to facilitate JNI usage. Multiple JVMTI agents can operate in a single JVM and all interfaces return an error code to determine success or failure of the request. It is the intention of JVMTI to displace both JVMPI and JVMDI, and to ultimately be the single native tool interface into the JVM. ” The JVMPI Transition to JVMTI

There is my sample code.

simpleAgent.c

#include
#include
#include
#include “jvmti.h”

static jvmtiEnv *jvmti = NULL;
static jvmtiCapabilities capa;

//****** Implementation from here ******//

static void
check_jvmti_error(jvmtiEnv *jvmti, jvmtiError errnum, const char *str)
{
if ( errnum != JVMTI_ERROR_NONE ) {
char *errnum_str;

errnum_str = NULL;
(void)(*jvmti)->GetErrorName(jvmti, errnum, &errnum_str);

printf(“ERROR: JVMTI: %d(%s): %s\n”, errnum, (errnum_str==NULL?”Unknown”:errnum_str), (str==NULL?””:str));
}
}

static void JNICALL
callbackVMInit(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread)
{
printf(“JVMTI_EVENT_VM_INIT is captured\n”);
}

static void
JNICALL callbackVMDeath(jvmtiEnv *jvmti_env, JNIEnv* jni_env)
{
printf(“JVMTI_EVENT_VM_DEATH is captured\n”);
}

static void JNICALL
callbackVMObjectAlloc(jvmtiEnv *jvmti_env, JNIEnv* jni_env, jthread thread, jobject object, jclass object_klass, jlong size)
{
printf(“JVMTI_EVENT_VM_OBJECT_ALLOC is captured:\n”);
}

/* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */
JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *jvm, char *options, void *reserved)
{

jint res;
jvmtiEventCallbacks callbacks;
jvmtiError error;

res = (*jvm)->GetEnv(jvm, (void **) &jvmti, JVMTI_VERSION);

if (res != JNI_OK || jvmti == NULL) {
/* This means that the VM was unable to obtain this version of the
* JVMTI interface, this is a fatal error.
*/
printf(“ERROR: Unable to access JVMTI Version 1 (0x%x),”
” is your J2SE a 1.5 or newer version?”
” JNIEnv’s GetEnv() returned %d\n”,
JVMTI_VERSION_1, res);

}

memset(&capa, 0, sizeof(jvmtiCapabilities));
error = (*jvmti)->GetPotentialCapabilities(jvmti, &capa);
if (error == JVMTI_ERROR_NONE) {
error = (*jvmti)->AddCapabilities(jvmti, &capa);
check_jvmti_error(jvmti, error, “Unable to get necessary JVMTI capabilities.”);
}

memset(&callbacks, 0, sizeof(callbacks));
callbacks.VMInit = &callbackVMInit; /* JVMTI_EVENT_VM_INIT */
callbacks.VMDeath = &callbackVMDeath; /* JVMTI_EVENT_VM_DEATH */
callbacks.VMObjectAlloc = &callbackVMObjectAlloc;/* JVMTI_EVENT_VM_OBJECT_ALLOC */

error = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, (jint)sizeof(callbacks));
check_jvmti_error(jvmti, error, “Cannot set jvmti callbacks”);

error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, (jthread)NULL);
error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, (jthread)NULL);
error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_OBJECT_ALLOC, (jthread)NULL);
check_jvmti_error(jvmti, error, “Cannot set event notification”);

return JNI_OK;

}

/* Agent_OnUnload() is called last */
JNIEXPORT void JNICALL
Agent_OnUnload(JavaVM *vm)
{
}

JVMTI Reference