blob: 4239a788250bda290a637312450fc25ba9ef0da4 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*
* author Ian Formanek
* Tomas Hurka
* Misha Dimitiev
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "jni.h"
#include "jvmti.h"
#include "common_functions.h"
#ifdef WIN32
#include <Windows.h>
#else
#include <sys/time.h>
#include <string.h>
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/** A hash table that maps class name/loader to class file bytes */
#define _CTABLE_INIT_SIZE 19
static char **_ctable_classnames = NULL;
static jobject *_ctable_loaders = NULL;
static char **_ctable_classdata = NULL;
static int *_ctable_classdata_lens = NULL;
static int _ctable_size = 0, _ctable_threshold = -1, _ctable_elements = 0, _total_cached_class_count = 0;
static jobject _ctable_lock = NULL;
static jboolean waitTrackingEnabled = FALSE;
static jboolean sleepTrackingEnabled = FALSE;
static jboolean parkTrackingEnabled = FALSE;
static jboolean lockContentionMonitoringEnabled = FALSE;
static jboolean trackingMethodsInitialized = FALSE;
static waitCall waitAddress = NULL;
static sleepCall sleepAddress = NULL;
static parkCall parkAddress = NULL;
static jclass profilerRuntimeID = NULL;
static jmethodID waitEntryID = NULL;
static jmethodID waitExitID = NULL;
static jmethodID monitorEntryID = NULL;
static jmethodID monitorExitID = NULL;
static jmethodID sleepEntryID = NULL;
static jmethodID sleepExitID = NULL;
static jmethodID parkEntryID = NULL;
static jmethodID parkExitID = NULL;
static jmethodID traceVMObjectAllocID = NULL;
static jboolean retransformIsRunning = FALSE;
static unsigned char BOGUS_CLASSFILE[] = "HAHA";
#define END_CLASS_NAME "org/netbeans/lib/profiler/server/ProfilerInterface$InitiateInstThread"
void cache_loaded_classes(jvmtiEnv *jvmti_env,jclass *classes,jint class_count) {
#ifdef JNI_VERSION_1_6
//fprintf(stderr,"cache_loade_classes, classes %d\n",(int)class_count);
jvmtiError res;
//fprintf(stderr,"Retransform called\n");
retransformIsRunning = TRUE;
res=(*jvmti_env)->RetransformClasses(jvmti_env,class_count,classes);
retransformIsRunning = FALSE;
//fprintf(stderr,"Retransform end\n");
if (res != JVMTI_ERROR_INVALID_CLASS_FORMAT && res != JVMTI_ERROR_NONE) {
fprintf(stderr,"Profiler Agent Warning: Retransform failed with status %d\n",res);
}
#endif
}
static jboolean isSameObject(JNIEnv *env, jobject obj1, jobject obj2) {
if (obj1 == NULL && obj2 == NULL) return JNI_TRUE;
if (obj1 == NULL || obj2 == NULL) return JNI_FALSE;
return (*env)->IsSameObject(env, obj1, obj2);
}
/*-------------------------------- Class hashtable management -------------------------------------*/
/** Currently doesn't take into account loader, though ideally it should. */
static int hash(const char *name, jobject loader) {
int i, code = 0;
int len = strlen(name);
for (i = 0; i < len; i++) {
code += name[i];
}
if (code < 0) {
code = -code;
}
return code;
}
static void grow_ctable() {
int i;
int old_size = _ctable_size;
char **old_classnames = _ctable_classnames;
jobject *old_loaders = _ctable_loaders;
char **old_classdata = _ctable_classdata;
int *old_classdata_lens = _ctable_classdata_lens;
if (_ctable_size == 0) {
_ctable_size = _CTABLE_INIT_SIZE;
} else {
_ctable_size = _ctable_size * 2 + 1;
}
_ctable_threshold = _ctable_size * 3 / 4;
_ctable_classnames = calloc(_ctable_size, sizeof(char*));
_ctable_loaders = calloc(_ctable_size, sizeof(jobject));
_ctable_classdata = calloc(_ctable_size, sizeof(char*));
_ctable_classdata_lens = calloc(_ctable_size, sizeof(int));
for (i = 0; i < old_size; i++) {
if (old_classnames[i] != NULL) {
int pos = hash(old_classnames[i], old_loaders[i]) % _ctable_size;
while (_ctable_classnames[pos] != NULL) {
pos = (pos + 1) % _ctable_size;
}
_ctable_classnames[pos] = old_classnames[i];
_ctable_loaders[pos] = old_loaders[i];
_ctable_classdata[pos] = old_classdata[i];
_ctable_classdata_lens[pos] = old_classdata_lens[i];
}
}
if (old_classnames != NULL) {
free(old_classnames);
free(old_loaders);
free(old_classdata);
free(old_classdata_lens);
}
}
/** For the given class with non-NULL, non-system loader, save the supplied class file bytes permanently */
static void save_class_file_bytes(JNIEnv *env, const char* name, jobject loader,
jint class_data_len, const unsigned char* class_data) {
int pos;
/*printf("!!! Gonna save classfilebytes for class %s\n", name);*/
(*env)->MonitorEnter(env, _ctable_lock);
if (_ctable_elements > _ctable_threshold) {
grow_ctable();
}
pos = hash(name, loader) % _ctable_size;
while (_ctable_classnames[pos] != NULL) {
if (strcmp(name, _ctable_classnames[pos]) == 0 && isSameObject(env, loader, _ctable_loaders[pos])) { /* do not save class' bytecode if it is already saved */
(*env)->MonitorExit(env, _ctable_lock);
return;
} else {
pos = (pos + 1) % _ctable_size;
}
}
_ctable_classnames[pos] = malloc(strlen(name) + 1);
strcpy(_ctable_classnames[pos], name);
if (loader != NULL) {
_ctable_loaders[pos] = (*env)->NewWeakGlobalRef(env, loader);
} else {
_ctable_loaders[pos] = NULL;
}
_ctable_classdata[pos] = malloc(class_data_len);
memcpy(_ctable_classdata[pos], class_data, class_data_len);
_ctable_classdata_lens[pos] = class_data_len;
_ctable_elements++;
/* Check if we should try to do some pruning */
if (++_total_cached_class_count % 250 == 0) {
fprintf(stdout, "Profiler Agent: 250 classes cached.\n");
try_removing_bytes_for_unloaded_classes(env);
}
(*env)->MonitorExit(env, _ctable_lock);
}
/** Returns a copy of class bytes for the given class. These bytes should be deallocated
* using free() when not needed anymore.
*
* TODO: free memory for classes that will be unloaded
*/
void get_saved_class_file_bytes(JNIEnv *env, char *name, jobject loader, jint *class_data_len, unsigned char **class_data) {
int len, pos;
(*env)->MonitorEnter(env, _ctable_lock);
pos = hash(name, loader) % _ctable_size;
while (_ctable_classnames[pos] != NULL) {
if (strcmp(name, _ctable_classnames[pos]) == 0 && isSameObject(env, loader, _ctable_loaders[pos])) {
break;
} else {
pos = (pos + 1) % _ctable_size;
}
}
if (_ctable_classnames[pos] == NULL) {
*class_data_len = 0;
*class_data = NULL;
(*env)->MonitorExit(env, _ctable_lock);
return;
}
len = _ctable_classdata_lens[pos];
*class_data_len = len;
*class_data = malloc(len);
memcpy(*class_data, _ctable_classdata[pos], len);
(*env)->MonitorExit(env, _ctable_lock);
}
/** When the Java agent learns that some class loader is going to be unloaded, it notifies the C agent
* about that. Here we check for any weak references to classloader that got nullified, and get rid of
* class file bytes for such class loaders.
*/
void try_removing_bytes_for_unloaded_classes(JNIEnv *env) {
}
static jthread getOwner(jvmtiEnv *jvmti_env, jobject object) {
jvmtiMonitorUsage usage;
jvmtiError res;
res = (*jvmti_env)->GetObjectMonitorUsage(jvmti_env, object, &usage);
assert(res == JVMTI_ERROR_NONE);
(*jvmti_env)->Deallocate(jvmti_env, (void*)usage.waiters);
(*jvmti_env)->Deallocate(jvmti_env, (void*)usage.notify_waiters);
/* if (usage.owner == NULL) {
* jint hash;
* res = (*jvmti_env)->GetObjectHashCode(jvmti_env, object, &hash);
* assert(res == JVMTI_ERROR_NONE);
* fprintf(stderr, "Profiler Agent Warning: NULL owner for lock %x.\n", (unsigned int)hash);
* }
*/
return usage.owner;
}
/** Class file load hook that the JVM calls whenever a class file is loaded and about to be parsed */
void JNICALL class_file_load_hook(
jvmtiEnv *jvmti_env,
JNIEnv* jni_env,
jclass class_being_redefined,
jobject loader,
const char* name,
jobject protection_domain,
jint class_data_len,
const unsigned char* class_data,
jint* new_class_data_len,
unsigned char** new_class_data)
{
jvmtiError res;
if (name == NULL) {
/* NULL name */
fprintf(stderr, "Profiler Agent Warning: JVMTI classLoadHook: class name is null.\n");
return;
}
if (class_being_redefined != NULL && !retransformIsRunning) {
/* Check if this class is being loaded for the first time (that is, not being redefined).
If it's being redefined, we return immediately. */
return;
}
if (loader == NULL) {
if (retransformIsRunning && strcmp(name,END_CLASS_NAME) == 0) {
/* Hack which will prevent unchanged classes to be redefined */
res=(*jvmti_env)->Allocate(jvmti_env,sizeof(BOGUS_CLASSFILE), new_class_data);
assert(res == JVMTI_ERROR_NONE);
memcpy(*new_class_data,BOGUS_CLASSFILE,sizeof(BOGUS_CLASSFILE));
*new_class_data_len = sizeof(BOGUS_CLASSFILE);
return;
}
}
if (_ctable_lock == NULL) {
jvmtiPhase phase;
(*jvmti_env)->GetPhase(jvmti_env, &phase);
if (phase >= JVMTI_PHASE_LIVE) {
jclass object_class;
/* Create a lock object used to synchronize access to _ctable */
object_class = (*jni_env)->FindClass(jni_env, "java/lang/Object");
_ctable_lock = (*jni_env)->AllocObject(jni_env, object_class);
_ctable_lock = (*jni_env)->NewGlobalRef(jni_env, _ctable_lock);
} else {
return;
}
}
save_class_file_bytes(jni_env, name, loader, class_data_len, class_data);
}
static void initializeMethods (JNIEnv *env) {
jclass localProfilerRuntimeID;
jclass localProfilerRuntimeMemoryID;
jboolean error = FALSE;
localProfilerRuntimeID = (*env)->FindClass (env, "org/netbeans/lib/profiler/server/ProfilerRuntime");
if (localProfilerRuntimeID == NULL) {
(*env)->ExceptionDescribe (env);
fprintf(stderr, "Profiler Agent Warning: Native bind failed to lookup org.netbeans.lib.profiler.server.ProfilerRuntime class!!!\n");
error = TRUE;
} else {
profilerRuntimeID = (*env)->NewGlobalRef(env, localProfilerRuntimeID);
waitEntryID = (*env)->GetStaticMethodID(env, profilerRuntimeID, "waitEntry", "()V");
if (waitEntryID == NULL) {
fprintf(stderr, "Profiler Agent Warning: Native bind failed to lookup waitEntry method!!! \n");
(*env)->ExceptionDescribe (env);
error = TRUE;
}
waitExitID = (*env)->GetStaticMethodID(env, profilerRuntimeID, "waitExit", "()V");
if (waitExitID == NULL) {
fprintf(stderr, "Profiler Agent Warning: Native bind failed to lookup waitExit method!!! \n");
(*env)->ExceptionDescribe (env);
error = TRUE;
}
sleepEntryID = (*env)->GetStaticMethodID(env, profilerRuntimeID, "sleepEntry", "()V");
if (sleepEntryID == NULL) {
fprintf(stderr, "Profiler Agent Warning: Native bind failed to lookup sleepEntry method!!! \n");
(*env)->ExceptionDescribe (env);
error = TRUE;
}
sleepExitID = (*env)->GetStaticMethodID(env, profilerRuntimeID, "sleepExit", "()V");
if (sleepExitID == NULL) {
fprintf(stderr, "Profiler Agent Warning: Native bind failed to lookup sleepExit method!!! \n");
(*env)->ExceptionDescribe (env);
error = TRUE;
}
monitorEntryID = (*env)->GetStaticMethodID(env, profilerRuntimeID, "monitorEntry", "(Ljava/lang/Thread;Ljava/lang/Object;Ljava/lang/Thread;)V");
if (monitorEntryID == NULL) {
fprintf(stderr, "Profiler Agent Warning: Native bind failed to lookup monitorEntry method!!! \n");
(*env)->ExceptionDescribe (env);
error = TRUE;
}
monitorExitID = (*env)->GetStaticMethodID(env, profilerRuntimeID, "monitorExit", "(Ljava/lang/Thread;Ljava/lang/Object;)V");
if (monitorExitID == NULL) {
fprintf(stderr, "Profiler Agent Warning: Native bind failed to lookup monitorExit method!!! \n");
(*env)->ExceptionDescribe (env);
error = TRUE;
}
parkEntryID = (*env)->GetStaticMethodID(env, profilerRuntimeID, "parkEntry", "()V");
if (parkEntryID == NULL) {
fprintf(stderr, "Profiler Agent Warning: Native bind failed to lookup parkEntry method!!! \n");
(*env)->ExceptionDescribe (env);
error = TRUE;
}
parkExitID = (*env)->GetStaticMethodID(env, profilerRuntimeID, "parkExit", "()V");
if (parkExitID == NULL) {
fprintf(stderr, "Profiler Agent Warning: Native bind failed to lookup parkExit method!!! \n");
(*env)->ExceptionDescribe (env);
error = TRUE;
}
}
localProfilerRuntimeMemoryID = (*env)->FindClass (env, "org/netbeans/lib/profiler/server/ProfilerRuntimeMemory");
if (localProfilerRuntimeMemoryID == NULL) {
(*env)->ExceptionDescribe (env);
fprintf(stderr, "Profiler Agent Warning: Native bind failed to lookup org.netbeans.lib.profiler.server.ProfilerRuntimeMemory class!!!\n");
error = TRUE;
} else {
traceVMObjectAllocID = (*env)->GetStaticMethodID(env, localProfilerRuntimeMemoryID, "traceVMObjectAlloc", "(Ljava/lang/Object;Ljava/lang/Class;)V");
if (traceVMObjectAllocID == NULL) {
fprintf(stderr, "Profiler Agent Warning: Native bind failed to lookup traceVMObjectAlloc method!!! \n");
(*env)->ExceptionDescribe (env);
error = TRUE;
}
}
if (error) {
// if there was an error initializing callbacks into agent, we disable wait,park and sleep tracking
waitTrackingEnabled = FALSE;
sleepTrackingEnabled = FALSE;
parkTrackingEnabled = FALSE;
}
trackingMethodsInitialized = TRUE;
}
void JNICALL native_method_bind_hook(
jvmtiEnv *jvmti_env,
JNIEnv* env,
jthread thread,
jmethodID method,
void* address,
void** new_address_ptr) {
jclass declaringClass;
char *className, *genericSignature, *methodName, *methodSig, *genericMethodSig;
int res;
if (env == NULL) {
return; // primordial phase
}
//fprintf (stderr, "Going to call GetMethodDeclaringClass for methodId = %d\n", *(int*)method);
res = (*_jvmti)->GetMethodDeclaringClass(_jvmti, method, &declaringClass);
if (res != JVMTI_ERROR_NONE || declaringClass == NULL || *((int*)declaringClass) == 0) { /* Also a bug workaround */
fprintf(stderr, "Profiler Agent Warning: Invalid declaringClass obtained from jmethodID\n");
fprintf(stderr, "Profiler Agent Warning: mId = %p, *mId = %d\n", method, *(int*)method);
fprintf(stderr, "Profiler Agent Warning: dCl = %p", declaringClass);
if (declaringClass != NULL) {
fprintf(stderr, ", *dCl = %d\n", *((int*)declaringClass));
} else {
fprintf(stderr, "\n");
}
//fprintf(stderr, "*** res = %d", res);
return;
}
//fprintf (stderr, "Going to call GetClassSignature for methodId = %d, last res = %d, declaring class: %d\n", *(int*)method, res, *((int*)declaringClass));
res = (*_jvmti)->GetClassSignature(_jvmti, declaringClass, &className, &genericSignature);
if (res != JVMTI_ERROR_NONE) {
fprintf(stderr, "Profiler Agent Warning: Couldn't obtain name of declaringClass = %p\n", declaringClass);
return;
}
//fprintf (stderr, "Going to call GetMethodName for methodId = %d, last res = %d, signature: %s\n", *(int*)method, res, genericSignature);
res = (*_jvmti)->GetMethodName(_jvmti, method, &methodName, &methodSig, &genericMethodSig);
if (res != JVMTI_ERROR_NONE) {
fprintf(stderr, "Profiler Agent Warning: Couldn't obtain name for methodID = %p\n", method);
return;
}
//fprintf (stderr, "Method class: %s, method name: %s, sig: %s\n", className, methodName, methodSig);
// check for java.lang.Object.wait(long )
if (strcmp("Ljava/lang/Object;",className)==0 && strcmp("wait",methodName)==0 && strcmp("(J)V",methodSig)==0) {
waitAddress = (waitCall)address;
*new_address_ptr = (void*) &waitInterceptor;
// fprintf(stderr, "Profiler Agent: Object.wait intercepted.\n");
} else // check for java.lang.Thread.sleep(long )
if (strcmp("Ljava/lang/Thread;",className)==0 && strcmp("sleep",methodName)==0 && strcmp("(J)V",methodSig)==0) {
sleepAddress = (sleepCall)address;
*new_address_ptr = (void*) &sleepInterceptor;
// fprintf(stderr, "Profiler Agent: Thread.sleep intercepted.\n");
} else // check for sun.misc.Unsafe.park(boolean, long )
if (strcmp("Lsun/misc/Unsafe;",className)==0 && strcmp("park",methodName)==0 && strcmp("(ZJ)V",methodSig)==0) {
parkAddress = (parkCall)address;
*new_address_ptr = (void*) &parkInterceptor;
// fprintf(stderr, "Profiler Agent: Unsafe.park intercepted.\n");
}
(*_jvmti)->Deallocate(_jvmti, (void*)className);
if (genericSignature != NULL) {
(*_jvmti)->Deallocate(_jvmti, (void*)genericSignature);
}
(*_jvmti)->Deallocate(_jvmti, (void*)methodName);
(*_jvmti)->Deallocate(_jvmti, (void*)methodSig);
if (genericMethodSig != NULL) {
(*_jvmti)->Deallocate(_jvmti, (void*)genericMethodSig);
}
}
void JNICALL waitInterceptor (JNIEnv *env, jobject obj, jlong arg) {
jthrowable exception = NULL;
if (waitTrackingEnabled) {
(*env)->CallStaticVoidMethod (env, profilerRuntimeID, waitEntryID, NULL);
(*env)->ExceptionDescribe (env);
}
waitAddress(env, obj, arg);
if (waitTrackingEnabled) {
// if an exception was thrown (InterruptedException), we need to catch and clear it for the exit handling
// and then rethrow
exception = (*env)->ExceptionOccurred (env);
if (exception != NULL) {
(*env)->ExceptionClear (env);
}
(*env)->CallStaticVoidMethod (env, profilerRuntimeID, waitExitID, NULL);
(*env)->ExceptionDescribe (env);
if (exception != NULL) {
(*env)->Throw (env, exception);
}
}
}
void JNICALL sleepInterceptor (JNIEnv *env, jclass clazz, jlong arg) {
jthrowable exception = NULL;
if (sleepTrackingEnabled) {
(*env)->CallStaticVoidMethod (env, profilerRuntimeID, sleepEntryID, NULL);
(*env)->ExceptionDescribe (env);
}
sleepAddress(env, clazz, arg);
if (sleepTrackingEnabled) {
// if an exception was thrown (InterruptedException), we need to catch and clear it for the exit handling
// and then rethrow
exception = (*env)->ExceptionOccurred (env);
if (exception != NULL) {
(*env)->ExceptionClear (env);
}
(*env)->CallStaticVoidMethod (env, profilerRuntimeID, sleepExitID, NULL);
(*env)->ExceptionDescribe (env);
if (exception != NULL) {
(*env)->Throw (env, exception);
}
}
}
void JNICALL parkInterceptor (JNIEnv *env, jobject obj, jboolean arg0, jlong arg1) {
jthrowable exception = NULL;
if (parkTrackingEnabled) {
(*env)->CallStaticVoidMethod (env, profilerRuntimeID, parkEntryID, NULL);
(*env)->ExceptionDescribe (env);
}
parkAddress(env, obj, arg0, arg1);
if (parkTrackingEnabled) {
// if an exception was thrown (InterruptedException), we need to catch and clear it for the exit handling
// and then rethrow
exception = (*env)->ExceptionOccurred (env);
if (exception != NULL) {
(*env)->ExceptionClear (env);
}
(*env)->CallStaticVoidMethod (env, profilerRuntimeID, parkExitID, NULL);
(*env)->ExceptionDescribe (env);
if (exception != NULL) {
(*env)->Throw (env, exception);
}
}
}
void JNICALL monitor_contended_enter_hook(
jvmtiEnv *jvmti_env,
JNIEnv* jni_env,
jthread thread,
jobject object) {
if (!trackingMethodsInitialized) {
initializeMethods (jni_env);
}
if (waitTrackingEnabled || lockContentionMonitoringEnabled) {
jthread owner = NULL;
if (lockContentionMonitoringEnabled) {
owner = getOwner(jvmti_env, object);
}
(*jni_env)->CallStaticVoidMethod (jni_env, profilerRuntimeID, monitorEntryID, thread, object, owner);
(*jni_env)->ExceptionDescribe (jni_env);
}
}
void JNICALL monitor_contended_entered_hook(
jvmtiEnv *jvmti_env,
JNIEnv* jni_env,
jthread thread,
jobject object) {
if (!trackingMethodsInitialized) {
initializeMethods (jni_env);
}
if (waitTrackingEnabled || lockContentionMonitoringEnabled) {
(*jni_env)->CallStaticVoidMethod (jni_env, profilerRuntimeID, monitorExitID, thread, object);
(*jni_env)->ExceptionDescribe (jni_env);
}
}
void JNICALL vm_object_alloc(jvmtiEnv *jvmti_env,
JNIEnv* jni_env,
jthread thread,
jobject object,
jclass object_klass,
jlong size) {
jthrowable exception = NULL;
if (jni_env == NULL) {
return; // primordial phase
}
if (!trackingMethodsInitialized) {
initializeMethods (jni_env);
}
// if an exception was thrown, we need to catch and clear it for the exit handling
// and then rethrow
exception = (*jni_env)->ExceptionOccurred (jni_env);
if (exception != NULL) {
(*jni_env)->ExceptionClear (jni_env);
}
(*jni_env)->CallStaticVoidMethod (jni_env, profilerRuntimeID, traceVMObjectAllocID, object, object_klass);
(*jni_env)->ExceptionDescribe (jni_env);
if (exception != NULL) {
(*jni_env)->Throw (jni_env, exception);
}
}
/*
* Class: org_netbeans_lib_profiler_server_system_Classes
* Method: setParkTrackingEnabled
* Signature: (Z)Z
*/
JNIEXPORT jboolean JNICALL Java_org_netbeans_lib_profiler_server_system_Classes_setParkTrackingEnabled
(JNIEnv *env, jclass clazz, jboolean value) {
if (!trackingMethodsInitialized) {
initializeMethods (env);
}
if (parkAddress != NULL && parkEntryID != NULL && parkExitID != NULL) {
parkTrackingEnabled = value;
return TRUE;
}
return FALSE;
}
/*
* Class: org_netbeans_lib_profiler_server_system_Classes
* Method: setLockContentionMonitoringEnabled
* Signature: (Z)Z
*/
JNIEXPORT jboolean JNICALL Java_org_netbeans_lib_profiler_server_system_Classes_setLockContentionMonitoringEnabled
(JNIEnv *env, jclass clazz, jboolean value) {
lockContentionMonitoringEnabled = value;
return TRUE;
}
/*
* Class: org_netbeans_lib_profiler_server_system_Classes
* Method: setWaitTrackingEnabled
* Signature: (Z)Z
*/
JNIEXPORT jboolean JNICALL Java_org_netbeans_lib_profiler_server_system_Classes_setWaitTrackingEnabled
(JNIEnv *env, jclass clazz, jboolean value) {
if (!trackingMethodsInitialized) {
initializeMethods (env);
}
if (waitAddress != NULL && waitEntryID != NULL && waitExitID != NULL && monitorEntryID != NULL && monitorExitID != NULL) {
waitTrackingEnabled = value;
return TRUE;
}
return FALSE;
}
/*
* Class: org_netbeans_lib_profiler_server_system_Classes
* Method: setSleepTrackingEnabled
* Signature: (Z)Z
*/
JNIEXPORT jboolean JNICALL Java_org_netbeans_lib_profiler_server_system_Classes_setSleepTrackingEnabled
(JNIEnv *env, jclass clazz, jboolean value) {
if (!trackingMethodsInitialized) {
initializeMethods (env);
}
if (sleepAddress != NULL && sleepEntryID != NULL && sleepExitID != NULL) {
sleepTrackingEnabled = value;
return TRUE;
}
return FALSE;
}
/*
* Class: org_netbeans_lib_profiler_server_system_Classes
* Method: setVMObjectAllocEnabled
* Signature: (Z)Z
*/
JNIEXPORT jboolean JNICALL Java_org_netbeans_lib_profiler_server_system_Classes_setVMObjectAllocEnabled
(JNIEnv *env, jclass clazz, jboolean value) {
jvmtiError res;
jvmtiEventMode mode;
if (value) {
mode = JVMTI_ENABLE;
} else {
mode = JVMTI_DISABLE;
}
res = (*_jvmti)->SetEventNotificationMode(_jvmti, mode, JVMTI_EVENT_VM_OBJECT_ALLOC, NULL);
assert(res == JVMTI_ERROR_NONE);
return TRUE;
}