--- old/src/jdk.jdwp.agent/share/native/libjdwp/classTrack.c 2019-11-22 22:43:39.502603951 +0100 +++ new/src/jdk.jdwp.agent/share/native/libjdwp/classTrack.c 2019-11-22 22:43:39.274603964 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -61,6 +61,42 @@ 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 @@ -177,25 +213,32 @@ jclass *classes; jvmtiError error; int i; + jboolean hasUnloaded = JNI_FALSE; - error = allLoadedClasses(&classes, &classCount); - if ( error != JVMTI_ERROR_NONE ) { - jvmtiDeallocate(newTable); - EXIT_ERROR(error,"loaded classes"); - } else { - - /* Transfer each current class into the new table */ - for (i=0; isignature); + jvmtiDeallocate(node); + EXIT_ERROR(error,"SetTag"); + } if ((node->klass = JNI_FUNC_PTR(env,NewWeakGlobalRef)(env, klass)) == NULL) { jvmtiDeallocate(node->signature); jvmtiDeallocate(node); @@ -245,12 +295,51 @@ *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; --- old/src/jdk.jdwp.agent/share/native/libjdwp/util.c 2019-11-22 22:43:40.371603904 +0100 +++ new/src/jdk.jdwp.agent/share/native/libjdwp/util.c 2019-11-22 22:43:40.172603915 +0100 @@ -1742,7 +1742,7 @@ } /* Get the jvmti environment to be used with tags */ -static jvmtiEnv * +jvmtiEnv * getSpecialJvmti(void) { jvmtiEnv *jvmti; --- old/src/jdk.jdwp.agent/share/native/libjdwp/util.h 2019-11-22 22:43:41.156603860 +0100 +++ new/src/jdk.jdwp.agent/share/native/libjdwp/util.h 2019-11-22 22:43:40.967603871 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -414,4 +414,9 @@ void saveGlobalRef(JNIEnv *env, jobject obj, jobject *pobj); void tossGlobalRef(JNIEnv *env, jobject *pobj); +/* JDK-8227269: Expose this method publicly. + * This returns a newly allocated jvmtiEnv* with the can_tag_objects capability. + */ +jvmtiEnv *getSpecialJvmti(void); + #endif