Commit 5196ea31 authored by Lubomir Bulej's avatar Lubomir Bulej

Tag classloader and send classloader tags to the server

parent 6d225ea9
......@@ -16,6 +16,8 @@
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <jni.h>
#include <jvmti.h>
......@@ -176,7 +178,7 @@ __safe (const char * class_name) {
static bool
__instrument_class (
jint request_flags, const char * class_name,
jvmtiClassDefinition * class_def
jvmtiClassDefinition * class_def, const jlong classloader_tag
) {
//
// Put the class data into a request message, acquire a connection and
......@@ -185,9 +187,14 @@ __instrument_class (
//
ClientMessage message = CLIENT_MESSAGE__INIT;
message.session_id = agent_config.session_id;
ClassInfo class_info = CLASS_INFO__INIT;
class_info.classname = (char *) class_name;
class_info.classloadertag = classloader_tag;
InstrumentClassRequest request = INSTRUMENT_CLASS_REQUEST__INIT;
request.flags = request_flags;
request.classname = (char *) class_name;
request.classinfo = &class_info;
request.classbytes.len = class_def->class_byte_count;
request.classbytes.data = (uint8_t *) class_def->class_bytes;
......@@ -426,21 +433,79 @@ __thread_info_done (jvmtiEnv * jvmti, struct thread_info * info) {
}
#define CLASSLOADER_TAG_INITIAL 100000
#define CLASSLOADER_TAG_BOOTSTRAP 0
#define CLASSLOADER_TAG_UNKNOWN -1
static jlong classloader_tag_next = CLASSLOADER_TAG_INITIAL;
static pthread_mutex_t classloader_tag_mutex = PTHREAD_MUTEX_INITIALIZER;
static jlong
__get_classloader_tag (jvmtiEnv * jvmti, jobject loader) {
//
// If loader is NULL, then we are dealing with the bootstrap
// classloader. We cannot tag it, so it is assigned a special tag.
//
if (loader == NULL) {
return CLASSLOADER_TAG_BOOTSTRAP;
}
//
// In other cases, check if the classloader has a tag and if not,
// assign one to it. We can only do this when we are past the
// PRIMORDIAL phase when the JVMTI calls to get/set tag are allowed.
//
if (!jvm_is_started) {
return CLASSLOADER_TAG_UNKNOWN;
}
//
// Check the tag without a lock first and if present, just return it.
// If not, lock and check the tag again and assign one if unset.
//
rdaprintf ("getting tag for class loader 0x%p: ", loader);
jlong tag = jvmti_get_object_tag (jvmti, loader);
if (tag == 0) {
int lock_result = pthread_mutex_lock (&classloader_tag_mutex);
check_error (lock_result != 0, "failed to lock tagging mutex");
tag = jvmti_get_object_tag (jvmti, loader);
if (tag == 0) {
tag = classloader_tag_next++;
jvmti_set_object_tag (jvmti, loader, tag);
}
int unlock_result = pthread_mutex_unlock (&classloader_tag_mutex);
check_error (unlock_result != 0, "failed to unlock tagging mutex");
}
rdaprintf ("%" PRId64 "\n", tag);
return tag;
}
static void JNICALL
jvmti_callback_class_file_load (
jvmtiEnv * jvmti, JNIEnv * jni,
jclass class_being_redefined, jobject loader,
jclass class_being_redefined, jobject classloader,
const char * class_name, jobject protection_domain,
jint class_byte_count, const unsigned char * class_bytes,
jint * new_class_byte_count, unsigned char ** new_class_bytes
) {
//
// Get classloader tag or assign a new one.
//
jlong classloader_tag = __get_classloader_tag (jvmti, classloader);
struct thread_info info = INIT_THREAD_INFO;
rdexec {
__thread_info_init (jvmti, jni, &info);
rdatiprefix (
&info, "processing %s (%ld bytes)\n",
__safe (class_name), (long) class_byte_count
&info, "processing %s of classloader %" PRId64 " (%ld bytes)\n",
__safe (class_name), classloader_tag, (long) class_byte_count
);
}
......@@ -476,7 +541,7 @@ jvmti_callback_class_file_load (
};
bool class_changed = __instrument_class (
agent_code_flags, class_name, &class_def
agent_code_flags, class_name, &class_def, classloader_tag
);
if (class_changed) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment