< prev index next >
src/jdk.jdwp.agent/share/native/libjdwp/classTrack.c
Print this page
*** 1,7 ****
/*
! * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
--- 1,7 ----
/*
! * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
*** 59,68 ****
--- 59,104 ----
* to a linked list of KlassNode.
*/
static KlassNode **table;
/*
+ * The JVMTI env we use to keep track of klass tags which allows us to detect class-unloads.
+ */
+ static jvmtiEnv *trackingEnv;
+
+ /*
+ * The current highest tag number in use by the trackingEnv.
+ *
+ * No need for synchronization since everything is done under the handlerLock.
+ */
+ static jlong currentKlassTag;
+
+ /*
+ * A lock to protect access to 'deletedTagBag'
+ */
+ static jrawMonitorID deletedTagLock;
+
+ /*
+ * A flag indicating whether classes have been unloaded.
+ *
+ * It is cleared each time classTrack_processUnloads is called.
+ */
+ jboolean hasUnloadedClasses;
+
+ /*
+ * The callback for when classes are freed. Only classes are called because this is registered with
+ * the trackingEnv which only tags classes.
+ */
+ static void JNICALL
+ cbTrackingObjectFree(jvmtiEnv* jvmti_env, jlong tag)
+ {
+ debugMonitorEnter(deletedTagLock);
+ hasUnloadedClasses = JNI_TRUE;
+ debugMonitorExit(deletedTagLock);
+ }
+
+ /*
* Return slot in hash table to use for this class.
*/
static jint
hashKlass(jclass klass)
{
*** 175,185 ****
--- 211,228 ----
jint classCount;
jclass *classes;
jvmtiError error;
int i;
+ jboolean hasUnloaded = JNI_FALSE;
+
+ debugMonitorEnter(deletedTagLock);
+ hasUnloaded = hasUnloadedClasses;
+ hasUnloadedClasses = JNI_FALSE;
+ debugMonitorExit(deletedTagLock);
+ if (hasUnloaded) {
error = allLoadedClasses(&classes, &classCount);
if ( error != JVMTI_ERROR_NONE ) {
jvmtiDeallocate(newTable);
EXIT_ERROR(error,"loaded classes");
} else {
*** 193,203 ****
/* Delete old table, install new one */
unloadedSignatures = deleteTable(env, table);
table = newTable;
}
!
} END_WITH_LOCAL_REFS(env)
}
return unloadedSignatures;
--- 236,246 ----
/* Delete old table, install new one */
unloadedSignatures = deleteTable(env, table);
table = newTable;
}
! }
} END_WITH_LOCAL_REFS(env)
}
return unloadedSignatures;
*** 232,241 ****
--- 275,291 ----
error = classSignature(klass, &(node->signature), NULL);
if (error != JVMTI_ERROR_NONE) {
jvmtiDeallocate(node);
EXIT_ERROR(error,"signature");
}
+ ++currentKlassTag;
+ error = JVMTI_FUNC_PTR(trackingEnv,SetTag)(trackingEnv, klass, currentKlassTag);
+ if (error != JVMTI_ERROR_NONE) {
+ jvmtiDeallocate(node->signature);
+ jvmtiDeallocate(node);
+ EXIT_ERROR(error,"SetTag");
+ }
if ((node->klass = JNI_FUNC_PTR(env,NewWeakGlobalRef)(env, klass)) == NULL) {
jvmtiDeallocate(node->signature);
jvmtiDeallocate(node);
EXIT_ERROR(AGENT_ERROR_NULL_POINTER,"NewWeakGlobalRef");
}
*** 243,258 ****
--- 293,347 ----
/* Insert the new node */
node->next = *head;
*head = node;
}
+ static jboolean
+ setupEvents()
+ {
+ jvmtiCapabilities caps;
+ memset(&caps, 0, sizeof(caps));
+ caps.can_generate_object_free_events = 1;
+ jvmtiError error = JVMTI_FUNC_PTR(trackingEnv,AddCapabilities)(trackingEnv, &caps);
+ if (error != JVMTI_ERROR_NONE) {
+ return JNI_FALSE;
+ }
+ jvmtiEventCallbacks cb;
+ memset(&cb, 0, sizeof(cb));
+ cb.ObjectFree = cbTrackingObjectFree;
+ error = JVMTI_FUNC_PTR(trackingEnv,SetEventCallbacks)(trackingEnv, &cb, sizeof(cb));
+ if (error != JVMTI_ERROR_NONE) {
+ return JNI_FALSE;
+ }
+ error = JVMTI_FUNC_PTR(trackingEnv,SetEventNotificationMode)
+ (trackingEnv, JVMTI_ENABLE, JVMTI_EVENT_OBJECT_FREE, NULL);
+ if (error != JVMTI_ERROR_NONE) {
+ return JNI_FALSE;
+ }
+ return JNI_TRUE;
+ }
+
/*
* Called once to build the initial prepared class hash table.
*/
void
classTrack_initialize(JNIEnv *env)
{
+ /* Setup the tracking env */
+ trackingEnv = getSpecialJvmti();
+ if ( trackingEnv == NULL ) {
+ EXIT_ERROR(AGENT_ERROR_INTERNAL,"Failed to allocate tag-tracking jvmtiEnv");
+ }
+ /* We want to create these before turning on the events or tagging anything. */
+ deletedTagLock = debugMonitorCreate("Deleted class tag lock");
+ hasUnloadedClasses = JNI_FALSE;
+ /* Setup the trackingEnv's ObjectFree event */
+ if (!setupEvents()) {
+ ERROR_MESSAGE(("Unable to setup class ObjectFree tracking! Class unloads will not "
+ "be reported!"));
+ }
+ currentKlassTag = 0l;
WITH_LOCAL_REFS(env, 1) {
jint classCount;
jclass *classes;
jvmtiError error;
< prev index next >