@@ -75,6 +75,8 @@ static bool addEventIds(J9JavaVM *vm);
7575static bool addTypeIds (J9JavaVM *vm);
7676#endif /* JAVA_SPEC_VERSION >= 17 */
7777static void jfrShutdownInternalStructures (J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData);
78+ static void addEventClass (J9VMThread *currentThread, J9Class *clazz);
79+ static void jfrClassInitialize (J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData);
7880
7981static void
8082freeThreadIDs (J9VMThread *currentThread)
@@ -1152,6 +1154,10 @@ stopJFRRecording(J9JavaVM *vm)
11521154 (*vmHooks)->J9HookUnregister (vmHooks, J9HOOK_VM_MONITOR_CONTENDED_ENTERED , jfrVMMonitorEntered, NULL );
11531155 (*vmHooks)->J9HookUnregister (vmHooks, J9HOOK_VM_UNPARKED , jfrVMThreadParked, NULL );
11541156 (*vmHooks)->J9HookUnregister (vmHooks, J9HOOK_SYSTEM_GC_CALLED , jfrSystemGC, NULL );
1157+ if (J9_ARE_ALL_BITS_SET (vm->extendedRuntimeFlags3 , J9_EXTENDED_RUNTIME3_JFR_V2_SUPPORT )) {
1158+ (*vmHooks)->J9HookUnregister (vmHooks, J9HOOK_VM_CLASS_INITIALIZE , jfrClassInitialize, NULL );
1159+ }
1160+
11551161 /* Deregister GC-related hooks via gc_base */
11561162 vm->memoryManagerFunctions ->j9gc_deregister_jfr_hooks (vm);
11571163}
@@ -1770,6 +1776,8 @@ getTypeIdImpl(J9VMThread *currentThread, J9ClassLoader *classLoader, J9UTF8 *cla
17701776 jfrTypeID = &entry;
17711777 jfrTypeID->id = vm->jfrState .typeIDcount ;
17721778 jfrTypeID->free = freeName;
1779+ jfrTypeID->isEvent = FALSE ;
1780+ jfrTypeID->eventClass = NULL ;
17731781
17741782 vm->jfrState .typeIDcount += 1 ;
17751783 Assert_VM_true (vm->jfrState .typeIDcount > 0 );
@@ -1802,6 +1810,12 @@ initializeJFRv2(J9JavaVM *vm)
18021810 goto done;
18031811 }
18041812
1813+ if (J9_ARE_ALL_BITS_SET (vm->extendedRuntimeFlags3 , J9_EXTENDED_RUNTIME3_JFR_V2_SUPPORT )) {
1814+ if ((*vmHooks)->J9HookRegisterWithCallSite (vmHooks, J9HOOK_VM_CLASS_INITIALIZE , jfrClassInitialize, OMR_GET_CALLSITE (), NULL )) {
1815+ goto done;
1816+ }
1817+ }
1818+
18051819 if (0 != initializeJFRIDs (vm)) {
18061820 goto done;
18071821 }
@@ -2017,6 +2031,8 @@ addType(J9JavaVM *vm, const char *eventOrTypeName, UDATA id, bool isEvent)
20172031 entry.id = id;
20182032 entry.className = className;
20192033 entry.free = TRUE ;
2034+ entry.isEvent = isEvent;
2035+ entry.eventClass = NULL ;
20202036
20212037 /* Add to hash table */
20222038 if (NULL == hashTableAdd (typeIDTable, &entry)) {
@@ -2332,6 +2348,97 @@ requestJFREvent(J9VMThread *currentThread, jlong id)
23322348#endif /* JAVA_SPEC_VERSION >= 17 */
23332349}
23342350
2351+ void
2352+ jfrClassInitialize (J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData)
2353+ {
2354+ J9VMClassInitializeEvent *event = (J9VMClassInitializeEvent *)eventData;
2355+ J9VMThread *currentThread = event->currentThread ;
2356+ J9Class *clazz = event->clazz ;
2357+
2358+ addEventClass (currentThread, clazz);
2359+ }
2360+
2361+ /* *
2362+ * Add an event class to the typeIDs table after it has been loaded.
2363+ * This function is called from the class loading hook to register event classes.
2364+ *
2365+ * @param currentThread[in] the current J9VMThread
2366+ * @param clazz[in] the loaded class to check and potentially add
2367+ */
2368+ static void
2369+ addEventClass (J9VMThread *currentThread, J9Class *clazz)
2370+ {
2371+ J9JavaVM *vm = currentThread->javaVM ;
2372+ J9UTF8 *className = J9ROMCLASS_CLASSNAME (clazz->romClass );
2373+ J9ClassLoader *classLoader = clazz->classLoader ;
2374+
2375+ if (NULL == vm->jfrState .jfrEventClassRef ) {
2376+ return ;
2377+ }
2378+
2379+ /* Check if this class is a subclass of jdk.jfr.Event and not an abstract class */
2380+ J9Class *eventClass = J9VMJAVALANGCLASS_VMREF (currentThread, J9_JNI_UNWRAP_REFERENCE (vm->jfrState .jfrEventClassRef ));
2381+ if (isSameOrSuperClassOf (eventClass, clazz)
2382+ && J9_ARE_NO_BITS_SET (clazz->romClass ->modifiers , J9AccAbstract)
2383+ ) {
2384+ omrthread_monitor_enter (vm->jfrState .typeIDMonitor );
2385+
2386+ J9HashTable *typeIDTable = classLoader->typeIDs ;
2387+ J9JFRTypeID query = {0 };
2388+ J9JFRTypeID *existingEntry = NULL ;
2389+
2390+ /* Create typeIDs table if it doesn't exist */
2391+ if (NULL == typeIDTable) {
2392+ PORT_ACCESS_FROM_JAVAVM (vm);
2393+
2394+ typeIDTable = hashTableNew (OMRPORT_FROM_J9PORT (privatePortLibrary),
2395+ J9_GET_CALLSITE (),
2396+ 0 ,
2397+ sizeof (J9JFRTypeID),
2398+ sizeof (J9JFRTypeID *),
2399+ 0 ,
2400+ J9MEM_CATEGORY_JFR ,
2401+ jfrTypeIDHashFn,
2402+ jfrTypeIDHashEqualFn,
2403+ NULL ,
2404+ NULL );
2405+
2406+ if (NULL == typeIDTable) {
2407+ goto done;
2408+ }
2409+ classLoader->typeIDs = typeIDTable;
2410+ }
2411+
2412+ /* Check if entry already exists */
2413+ query.className = className;
2414+ existingEntry = (J9JFRTypeID *)hashTableFind (typeIDTable, &query);
2415+
2416+ if (NULL != existingEntry) {
2417+ /* Update existing entry with event class pointer */
2418+ existingEntry->isEvent = TRUE ;
2419+ existingEntry->eventClass = clazz;
2420+ } else {
2421+ /* Create new entry */
2422+ J9JFRTypeID newEntry = {0 };
2423+ newEntry.id = vm->jfrState .typeIDcount ;
2424+ newEntry.className = className;
2425+ newEntry.free = FALSE ;
2426+ newEntry.isEvent = TRUE ;
2427+ newEntry.eventClass = clazz;
2428+
2429+ vm->jfrState .typeIDcount += 1 ;
2430+ Assert_VM_true (vm->jfrState .typeIDcount > 0 );
2431+
2432+ if (NULL == hashTableAdd (typeIDTable, &newEntry)) {
2433+ setNativeOutOfMemoryError (currentThread, 0 , 0 );
2434+ goto done;
2435+ }
2436+ }
2437+ done:
2438+ omrthread_monitor_exit (vm->jfrState .typeIDMonitor );
2439+ }
2440+ }
2441+
23352442} /* extern "C" */
23362443
23372444#endif /* defined(J9VM_OPT_JFR) */
0 commit comments