Skip to content

Commit ba4768b

Browse files
committed
JVM_getAllEventClasses support
Signed-off-by: Gengchen Tuo <gengchen.tuo@ibm.com>
1 parent f8b93be commit ba4768b

3 files changed

Lines changed: 187 additions & 1 deletion

File tree

runtime/jcl/common/jdk_jfr_internal_JVM_common.cpp

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "j9.h"
2424
#include "jni.h"
2525
#include "jclprots.h"
26+
#include "ut_j9jcl.h"
2627

2728
#include "ObjectAccessBarrierAPI.hpp"
2829
#include "VMHelpers.hpp"
@@ -100,10 +101,86 @@ Java_jdk_jfr_internal_JVM_getAllEventClasses(JNIEnv *env, jobject obj)
100101
J9VMThread *currentThread = (J9VMThread*) env;
101102
J9JavaVM *vm = currentThread->javaVM;
102103
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
104+
J9MemoryManagerFunctions *mmFuncs = vm->memoryManagerFunctions;
103105
jobject result = NULL;
104106

105107
vmFuncs->internalEnterVMFromJNI(currentThread);
106-
result = vmFuncs->j9jni_createLocalRef(env, vmFuncs->jvmUpcallTransformArrayToList(currentThread, NULL));
108+
109+
omrthread_monitor_enter(vm->jfrState.typeIDMonitor);
110+
111+
/* First pass: count event classes with valid eventClass pointers across all classloaders. */
112+
UDATA eventCount = 0;
113+
J9ClassLoaderWalkState walkState;
114+
J9ClassLoader *classLoader = vmFuncs->allClassLoadersStartDo(&walkState, vm, 0);
115+
116+
while (NULL != classLoader) {
117+
J9HashTable *typeIDTable = classLoader->typeIDs;
118+
if (NULL != typeIDTable) {
119+
J9HashTableState hashTableState = {0};
120+
J9JFRTypeID *entry = (J9JFRTypeID *)hashTableStartDo(typeIDTable, &hashTableState);
121+
122+
while (NULL != entry) {
123+
if (entry->isEvent && (NULL != entry->eventClass)) {
124+
eventCount += 1;
125+
}
126+
entry = (J9JFRTypeID *)hashTableNextDo(&hashTableState);
127+
}
128+
}
129+
classLoader = vmFuncs->allClassLoadersNextDo(&walkState);
130+
}
131+
vmFuncs->allClassLoadersEndDo(&walkState);
132+
133+
/* Get the Class class and create Class[] array class. */
134+
J9Class *javaLangClass = J9VMJAVALANGCLASS_OR_NULL(vm);
135+
UDATA arrayIndex = 0;
136+
j9array_t classArray = NULL;
137+
Assert_JCL_notNull(javaLangClass);
138+
139+
J9Class *classArrayClass = javaLangClass->arrayClass;
140+
if (NULL == classArrayClass) {
141+
J9ROMArrayClass *arrayOfObjectsROMClass = (J9ROMArrayClass*)J9ROMIMAGEHEADER_FIRSTCLASS(vm->arrayROMClasses);
142+
classArrayClass = vmFuncs->internalCreateArrayClass(currentThread, arrayOfObjectsROMClass, javaLangClass);
143+
if (NULL == classArrayClass) {
144+
goto done;
145+
}
146+
}
147+
148+
/* Allocate the Class[] array. */
149+
classArray = (j9array_t)mmFuncs->J9AllocateIndexableObject(
150+
currentThread, classArrayClass, (U_32)eventCount, J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);
151+
if (NULL == classArray) {
152+
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
153+
goto done;
154+
}
155+
156+
/* Second pass: populate the array with event classes from all classloaders */
157+
classLoader = vmFuncs->allClassLoadersStartDo(&walkState, vm, 0);
158+
159+
while (NULL != classLoader) {
160+
J9HashTable *typeIDTable = classLoader->typeIDs;
161+
if (NULL != typeIDTable) {
162+
J9HashTableState hashTableState = {0};
163+
J9JFRTypeID *entry = (J9JFRTypeID *)hashTableStartDo(typeIDTable, &hashTableState);
164+
165+
while (NULL != entry) {
166+
if (entry->isEvent && (NULL != entry->eventClass)) {
167+
/* Use the stored eventClass pointer directly */
168+
j9object_t classObject = J9VM_J9CLASS_TO_HEAPCLASS(entry->eventClass);
169+
J9JAVAARRAYOFOBJECT_STORE(currentThread, classArray, arrayIndex, classObject);
170+
arrayIndex += 1;
171+
}
172+
entry = (J9JFRTypeID *)hashTableNextDo(&hashTableState);
173+
}
174+
}
175+
classLoader = vmFuncs->allClassLoadersNextDo(&walkState);
176+
}
177+
vmFuncs->allClassLoadersEndDo(&walkState);
178+
179+
/* Convert array to list and create local ref */
180+
result = vmFuncs->j9jni_createLocalRef(env, vmFuncs->jvmUpcallTransformArrayToList(currentThread, (j9object_t)classArray));
181+
182+
done:
183+
omrthread_monitor_exit(vm->jfrState.typeIDMonitor);
107184
vmFuncs->internalExitVMToJNI(currentThread);
108185

109186
return result;

runtime/oti/j9nonbuilder.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,8 @@ typedef struct J9JFRTypeID {
554554
jlong id;
555555
struct J9UTF8 *className;
556556
BOOLEAN free;
557+
BOOLEAN isEvent;
558+
struct J9Class *eventClass;
557559
} J9JFRTypeID;
558560

559561
typedef struct J9JFRNetworkUtilization {

runtime/vm/jfr.cpp

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ static bool addEventIds(J9JavaVM *vm);
7575
static bool addTypeIds(J9JavaVM *vm);
7676
#endif /* JAVA_SPEC_VERSION >= 17 */
7777
static 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

7981
static void
8082
freeThreadIDs(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

Comments
 (0)