< 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 >