diff --git a/runtime/oti/j9nonbuilder.h b/runtime/oti/j9nonbuilder.h index a5e83f265aa..5aee4e37420 100644 --- a/runtime/oti/j9nonbuilder.h +++ b/runtime/oti/j9nonbuilder.h @@ -4873,7 +4873,7 @@ typedef struct J9InternalVMFunctions { struct J9Class* ( *internalFindClassUTF8)(struct J9VMThread *currentThread, U_8 *className, UDATA classNameLength, struct J9ClassLoader *classLoader, UDATA options) ; struct J9Class* ( *internalFindClassInModule)(struct J9VMThread *currentThread, struct J9Module *j9module, U_8 *className, UDATA classNameLength, struct J9ClassLoader *classLoader, UDATA options) ; struct J9Class* ( *internalFindClassString)(struct J9VMThread* currentThread, j9object_t moduleName, j9object_t className, struct J9ClassLoader* classLoader, UDATA options, UDATA allowedBitsForClassName) ; - struct J9Class* ( *hashClassTableAt)(struct J9ClassLoader *classLoader, U_8 *className, UDATA classNameLength) ; + struct J9Class * (*hashClassTableAt)(struct J9ClassLoader *classLoader, U_8 *className, UDATA classNameLength); UDATA ( *hashClassTableAtPut)(struct J9VMThread *vmThread, struct J9ClassLoader *classLoader, U_8 *className, UDATA classNameLength, struct J9Class *value) ; UDATA ( *hashClassTableDelete)(struct J9ClassLoader *classLoader, U_8 *className, UDATA classNameLength) ; void ( *hashClassTableReplace)(struct J9VMThread* vmThread, struct J9ClassLoader *classLoader, struct J9Class *originalClass, struct J9Class *replacementClass) ; diff --git a/runtime/oti/vm_api.h b/runtime/oti/vm_api.h index 3d742913a6c..b766b6099ff 100644 --- a/runtime/oti/vm_api.h +++ b/runtime/oti/vm_api.h @@ -871,10 +871,11 @@ iterateStackTrace(J9VMThread * vmThread, j9object_t* exception, UDATA (*callba * @param skipHiddenFrames * @param sizeOfWalkstateCache * @param exceptionIsJavaObject +* @param revealAnonAndHiddenClass * @return UDATA */ UDATA -iterateStackTraceImpl(J9VMThread * vmThread, j9object_t* exception, UDATA (*callback) (J9VMThread * vmThread, void * userData, UDATA bytecodeOffset, J9ROMClass * romClass, J9ROMMethod * romMethod, J9UTF8 * fileName, UDATA lineNumber, J9ClassLoader* classLoader, J9Class* ramClass, UDATA frameType), void * userData, UDATA pruneConstructors, UDATA skipHiddenFrames, UDATA sizeOfWalkstateCache, BOOLEAN exceptionIsJavaObject); +iterateStackTraceImpl(J9VMThread * vmThread, j9object_t* exception, UDATA (*callback) (J9VMThread * vmThread, void * userData, UDATA bytecodeOffset, J9ROMClass * romClass, J9ROMMethod * romMethod, J9UTF8 * fileName, UDATA lineNumber, J9ClassLoader* classLoader, J9Class* ramClass, UDATA frameType), void * userData, UDATA pruneConstructors, UDATA skipHiddenFrames, UDATA sizeOfWalkstateCache, BOOLEAN exceptionIsJavaObject, BOOLEAN revealAnonAndHiddenClass); /* ---------------- exceptionsupport.c ---------------- */ @@ -2080,6 +2081,16 @@ isAnyClassLoadedFromPackage(J9ClassLoader* classLoader, U_8 *pkgName, UDATA pkgN void hashClassTableFree(J9ClassLoader* classLoader); +/** +* @brief +* @param *classLoader +* @param *className +* @param classNameLength +* @param ignoreAnonAndHiddenClass +* @return J9Class * +*/ +J9Class * +hashClassTableAtImpl(J9ClassLoader *classLoader, U_8 *className, UDATA classNameLength, BOOLEAN ignoreAnonAndHiddenClass); /** * @brief diff --git a/runtime/vm/JFRConstantPoolTypes.hpp b/runtime/vm/JFRConstantPoolTypes.hpp index ecdc350f827..11f5611a66c 100644 --- a/runtime/vm/JFRConstantPoolTypes.hpp +++ b/runtime/vm/JFRConstantPoolTypes.hpp @@ -906,7 +906,7 @@ class VM_JFRConstantPoolTypes { goto done; } - expandedStackTraceCount = iterateStackTraceImpl(_currentThread, (j9object_t*)walkStateCache, NULL, NULL, FALSE, FALSE, numberOfFrames, FALSE); + expandedStackTraceCount = iterateStackTraceImpl(_currentThread, (j9object_t*)walkStateCache, NULL, NULL, FALSE, FALSE, numberOfFrames, FALSE, TRUE); _currentStackFrameBuffer = (StackFrame*) j9mem_allocate_memory(sizeof(StackFrame) * expandedStackTraceCount, J9MEM_CATEGORY_CLASSES); _currentFrameCount = 0; @@ -915,7 +915,7 @@ class VM_JFRConstantPoolTypes { goto done; } - iterateStackTraceImpl(_currentThread, (j9object_t*)walkStateCache, &stackTraceCallback, this, FALSE, FALSE, numberOfFrames, FALSE); + iterateStackTraceImpl(_currentThread, (j9object_t*)walkStateCache, &stackTraceCallback, this, FALSE, FALSE, numberOfFrames, FALSE, TRUE); index = addStackTraceEntry(walkThread, j9time_nano_time(), _currentFrameCount); _stackFrameCount += expandedStackTraceCount; diff --git a/runtime/vm/KeyHashTable.c b/runtime/vm/KeyHashTable.c index 957875d111d..6d0142c0606 100644 --- a/runtime/vm/KeyHashTable.c +++ b/runtime/vm/KeyHashTable.c @@ -126,12 +126,12 @@ classHashEqualFn(void *tableNode, void *queryNode, void *userData) UDATA tableNodeType = classHashGetName(tableNode, &tableNodeName, &tableNodeLength); UDATA queryNodeType = classHashGetName(queryNode, &queryNodeName, &queryNodeLength); UDATA tableNodeTag = ((KeyHashTableClassEntry *)tableNode)->tag; - BOOLEAN isTableNodeHiddenClass = (TYPE_CLASS == tableNodeType) + BOOLEAN isTableNodeAnonOrHiddenClass = (TYPE_CLASS == tableNodeType) && (TAG_RAM_CLASS == (tableNodeTag & MASK_RAM_CLASS)) - && J9ROMCLASS_IS_HIDDEN(((KeyHashTableClassEntry *)tableNode)->ramClass->romClass); + && J9ROMCLASS_IS_ANON_OR_HIDDEN(((KeyHashTableClassEntry *)tableNode)->ramClass->romClass); - if (isTableNodeHiddenClass) { - /* Hidden class is keyed on its rom address, not on its name. */ + if (isTableNodeAnonOrHiddenClass) { + /* Anon and Hidden class is keyed on its rom address, not on its name. */ PORT_ACCESS_FROM_JAVAVM(javaVM); j9str_printf(PORTLIB, buf, ROM_ADDRESS_LENGTH + 1, ROM_ADDRESS_FORMAT, (UDATA)((KeyHashTableClassEntry *)tableNode)->ramClass->romClass); tableNodeName = (const U_8 *)buf; @@ -225,12 +225,12 @@ classHashFn(void *key, void *userData) UDATA type = classHashGetName(key, &name, &length); UDATA keyTag = ((KeyHashTableClassEntry *)key)->tag; char buf[ROM_ADDRESS_LENGTH + 1] = {0}; - BOOLEAN isTableNodeHiddenClass = (TYPE_CLASS == type) + BOOLEAN isTableNodeHiddenOrAnonClass = (TYPE_CLASS == type) && (TAG_RAM_CLASS == (keyTag & MASK_RAM_CLASS)) - && J9ROMCLASS_IS_HIDDEN(((KeyHashTableClassEntry *)key)->ramClass->romClass); + && J9ROMCLASS_IS_ANON_OR_HIDDEN(((KeyHashTableClassEntry *)key)->ramClass->romClass); - if (isTableNodeHiddenClass) { - /* for hidden class, do not key on its name, key on its rom address */ + if (isTableNodeHiddenOrAnonClass) { + /* For anon or hidden class, do not key on its name, key on its rom address */ PORT_ACCESS_FROM_JAVAVM(javaVM); j9str_printf(PORTLIB, buf, ROM_ADDRESS_LENGTH + 1, ROM_ADDRESS_FORMAT, (UDATA)((KeyHashTableClassEntry *)key)->ramClass->romClass); name = (const U_8 *)buf; @@ -333,7 +333,7 @@ hashClassTableNew(J9JavaVM *javaVM, U_32 initialSize) } J9Class * -hashClassTableAt(J9ClassLoader *classLoader, U_8 *className, UDATA classNameLength) +hashClassTableAtImpl(J9ClassLoader *classLoader, U_8 *className, UDATA classNameLength, BOOLEAN ignoreAnonAndHiddenClass) { J9HashTable *table = classLoader->classHashTable; KeyHashTableClassQueryEntry key; @@ -346,7 +346,7 @@ hashClassTableAt(J9ClassLoader *classLoader, U_8 *className, UDATA classNameLeng if (NULL != result) { J9Class *clazz = result->ramClass; checkClassAlignment(clazz, "hashClassTableAt"); - if (J9ROMCLASS_IS_HIDDEN(clazz->romClass)) { + if ((TRUE == ignoreAnonAndHiddenClass) && J9ROMCLASS_IS_ANON_OR_HIDDEN(clazz->romClass)) { return NULL; } return clazz; @@ -355,6 +355,12 @@ hashClassTableAt(J9ClassLoader *classLoader, U_8 *className, UDATA classNameLeng } } +J9Class * +hashClassTableAt(J9ClassLoader *classLoader, U_8 *className, UDATA classNameLength) +{ + return hashClassTableAtImpl(classLoader, className, classNameLength, TRUE); +} + BOOLEAN isAnyClassLoadedFromPackage(J9ClassLoader *classLoader, U_8 *pkgName, UDATA pkgNameLength) { diff --git a/runtime/vm/createramclass.cpp b/runtime/vm/createramclass.cpp index 598aa6a74b6..ea15386fdcd 100644 --- a/runtime/vm/createramclass.cpp +++ b/runtime/vm/createramclass.cpp @@ -2392,7 +2392,6 @@ internalCreateRAMClassDone(J9VMThread *vmThread, J9ClassLoader *classLoader, J9C /* Put the new class in the table or arrayClass field. */ if ((!fastHCR) && (0 == J9ROMCLASS_IS_PRIMITIVE_OR_ARRAY(romClass)) - && J9_ARE_NO_BITS_SET(options, J9_FINDCLASS_FLAG_ANON) ) { if (hashClassTableAtPut(vmThread, classLoader, J9UTF8_DATA(className), J9UTF8_LENGTH(className), state->ramClass)) { if (hotswapping) { diff --git a/runtime/vm/exceptiondescribe.c b/runtime/vm/exceptiondescribe.c index 1ff39fd6412..fa29fc808cf 100644 --- a/runtime/vm/exceptiondescribe.c +++ b/runtime/vm/exceptiondescribe.c @@ -40,7 +40,7 @@ typedef UDATA (*callback_func_t) (J9VMThread * vmThread, void * userData, UDATA static void printExceptionInThread (J9VMThread* vmThread); static UDATA isSubclassOfThreadDeath (J9VMThread *vmThread, j9object_t exception); static void printExceptionMessage (J9VMThread* vmThread, j9object_t exception); -static J9Class* findJ9ClassForROMClass(J9VMThread *vmThread, J9ROMClass *romClass, J9ClassLoader **resultClassLoader); +static J9Class* findJ9ClassForROMClass(J9VMThread *vmThread, J9ROMClass *romClass, J9ClassLoader **resultClassLoader, BOOLEAN revealAnonAndHiddenClass); /* assumes VM access */ @@ -220,18 +220,19 @@ printStackTraceEntry(J9VMThread * vmThread, void * voidUserData, UDATA bytecodeO * @param[in] ROMClass The J9ROMClass from which the J9Class is created. * @param[in, out] resultClassLoader This is the classLoader that owns the memory segment that the ROMClass was found in. * The romclass memory segment in the shared cache always belongs to vm->systemClassLoader. Set it to the actual class loader which loaded the class in this case. +* @param[in] revealAnonAndHiddenClass Whether to return the J9Class of a hidden or anonymous class. * * @return The J9class, or NULL on failure. */ static J9Class* -findJ9ClassForROMClass(J9VMThread *vmThread, J9ROMClass *romClass, J9ClassLoader **resultClassLoader) +findJ9ClassForROMClass(J9VMThread *vmThread, J9ROMClass *romClass, J9ClassLoader **resultClassLoader, BOOLEAN revealAnonAndHiddenClass) { J9UTF8 const *utfClassName = J9ROMCLASS_CLASSNAME(romClass); J9JavaVM *vm = vmThread->javaVM; J9SharedClassConfig *config = vm->sharedClassConfig; J9Class* ret = NULL; - if (_J9ROMCLASS_J9MODIFIER_IS_SET(romClass, J9AccClassAnonClass)) { + if ((FALSE == revealAnonAndHiddenClass) && _J9ROMCLASS_J9MODIFIER_IS_SET(romClass, J9AccClassAnonClass)) { /* Anonymous classes are not allowed in any class loader hash table. */ return NULL; } @@ -332,7 +333,27 @@ findJ9ClassForROMClass(J9VMThread *vmThread, J9ROMClass *romClass, J9ClassLoader omrthread_rwmutex_exit_write(config->romToRamHashTableMutex); } } else { - ret = peekClassHashTable(vmThread, *resultClassLoader, J9UTF8_DATA(utfClassName), J9UTF8_LENGTH(utfClassName)); + if ((TRUE == revealAnonAndHiddenClass) && J9ROMCLASS_IS_ANON_OR_HIDDEN(romClass)) { + PORT_ACCESS_FROM_JAVAVM(vmThread->javaVM); + char buf[ROM_ADDRESS_LENGTH + 1] = {0}; + BOOLEAN fastMode = J9_ARE_ALL_BITS_SET(vm->extendedRuntimeFlags, J9_EXTENDED_RUNTIME_FAST_CLASS_HASH_TABLE); + + /* A hidden or anonymous class is keyed on its address */ + j9str_printf(PORTLIB, buf, ROM_ADDRESS_LENGTH + 1, ROM_ADDRESS_FORMAT, romClass); + if (!fastMode) { + omrthread_monitor_enter(vm->classTableMutex); + } + if (_J9ROMCLASS_J9MODIFIER_IS_SET(romClass, J9AccClassAnonClass)) { + ret = hashClassTableAtImpl(vm->anonClassLoader, (U_8 *)buf, ROM_ADDRESS_LENGTH, FALSE); + } else { + ret = hashClassTableAtImpl(*resultClassLoader, (U_8 *)buf, ROM_ADDRESS_LENGTH, FALSE); + } + if (!fastMode) { + omrthread_monitor_exit(vm->classTableMutex); + } + } else { + ret = peekClassHashTable(vmThread, *resultClassLoader, J9UTF8_DATA(utfClassName), J9UTF8_LENGTH(utfClassName)); + } } done: return ret; @@ -349,12 +370,13 @@ findJ9ClassForROMClass(J9VMThread *vmThread, J9ROMClass *romClass, J9ClassLoader * @param pruneConstructors Non-zero if constructors should be pruned from the stack trace. * @param sizeOfWalkstateCache Non-zero if exception is walkstate cache instead of exception object. * Indicatest the size of cache. + * @param revealAnonAndHiddenClass Whether to show methods of hidden and anonymous classes. * @return The number of times the callback function was invoked. * * @note Assumes VM access **/ UDATA -iterateStackTraceImpl(J9VMThread * vmThread, j9object_t* exception, callback_func_t callback, void * userData, UDATA pruneConstructors, UDATA skipHiddenFrames, UDATA sizeOfWalkstateCache, BOOLEAN exceptionIsJavaObject) +iterateStackTraceImpl(J9VMThread * vmThread, j9object_t* exception, callback_func_t callback, void * userData, UDATA pruneConstructors, UDATA skipHiddenFrames, UDATA sizeOfWalkstateCache, BOOLEAN exceptionIsJavaObject, BOOLEAN revealAnonAndHiddenClass) { J9JavaVM * vm = vmThread->javaVM; UDATA totalEntries = 0; @@ -473,7 +495,7 @@ iterateStackTraceImpl(J9VMThread * vmThread, j9object_t* exception, callback_fun #endif romClass = findROMClassFromPC(vmThread, methodPC, &classLoader); if (NULL != romClass) { - ramClass = findJ9ClassForROMClass(vmThread, romClass, &classLoader); + ramClass = findJ9ClassForROMClass(vmThread, romClass, &classLoader, revealAnonAndHiddenClass); while (NULL != ramClass) { U_32 i = 0; J9Method *methods = ramClass->ramMethods; @@ -582,7 +604,7 @@ foundROMMethod: ; UDATA iterateStackTrace(J9VMThread * vmThread, j9object_t* exception, callback_func_t callback, void * userData, UDATA pruneConstructors, UDATA skipHiddenFrames) { - return iterateStackTraceImpl(vmThread, exception, callback, userData, pruneConstructors, skipHiddenFrames, 0, TRUE); + return iterateStackTraceImpl(vmThread, exception, callback, userData, pruneConstructors, skipHiddenFrames, 0, TRUE, FALSE); } /** diff --git a/runtime/vm/jvminit.c b/runtime/vm/jvminit.c index 9a6afecb62d..1cc6e7432f2 100644 --- a/runtime/vm/jvminit.c +++ b/runtime/vm/jvminit.c @@ -8322,10 +8322,11 @@ freeClassNativeMemory(J9HookInterface** hook, UDATA eventNum, void* eventData, v static void vmHookAnonClassesUnload(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData) { - J9VMAnonymousClassesUnloadEvent * unloadedEvent = (J9VMAnonymousClassesUnloadEvent *)eventData; - J9VMThread * vmThread = unloadedEvent->currentThread; + J9VMAnonymousClassesUnloadEvent *unloadedEvent = (J9VMAnonymousClassesUnloadEvent *)eventData; + J9VMThread *vmThread = unloadedEvent->currentThread; J9JavaVM *vm = vmThread->javaVM; for (J9Class* j9clazz = unloadedEvent->anonymousClassesToUnload; j9clazz; j9clazz = j9clazz->gcLink) { + J9UTF8 const *className = J9ROMCLASS_CLASSNAME(j9clazz->romClass); /* AnonClass->classLoader points to the hostclass->classLoader not the anonClassLoader. */ if (J9VM_SHOULD_CLEAR_JNIIDS_FOR_ASGCT(vm, j9clazz->classLoader)) { void **jniIDs = j9clazz->jniIDs; @@ -8337,6 +8338,7 @@ vmHookAnonClassesUnload(J9HookInterface** hook, UDATA eventNum, void* eventData, } } } + hashClassTableDelete(vm->anonClassLoader, J9UTF8_DATA(className), J9UTF8_LENGTH(className)); #if JAVA_SPEC_VERSION >= 22 hashClassTablePackageDelete(vmThread, j9clazz->classLoader, j9clazz->romClass); #endif /* JAVA_SPEC_VERSION >= 22 */