Path: blob/master/runtime/jcl/common/java_lang_Class.cpp
6000 views
/*******************************************************************************1* Copyright (c) 1998, 2021 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122#include "jni.h"23#include "jcl.h"24#include "jclglob.h"25#include "jclprots.h"26#include "jcl_internal.h"27#include "objhelp.h"28#include "rommeth.h"29#include "vmaccess.h"30#include "java_lang_Class.h"31#include "ArrayCopyHelpers.hpp"32#include "j9jclnls.h"333435#include "VMHelpers.hpp"3637extern "C" {3839typedef enum {40STATE_INITIAL = -2,41STATE_ERROR = -1,42STATE_STOP = 0,43STATE_IMPLIED = 144} StackWalkingStates;4546typedef enum {47OBJS_ARRAY_IDX_ACC = 0,48OBJS_ARRAY_IDX_PDS = 1,49OBJS_ARRAY_IDX_PERMS_OR_CACHECHECKED = 2,50OBJS_ARRAY_SIZE = 351} ObjsArraySizeNindex;5253#define STACK_WALK_STATE_MAGIC (void *)154#define STACK_WALK_STATE_LIMITED_DOPRIVILEGED (void *)255#define STACK_WALK_STATE_FULL_DOPRIVILEGED (void *)35657static UDATA isPrivilegedFrameIterator(J9VMThread * currentThread, J9StackWalkState * walkState);58static UDATA isPrivilegedFrameIteratorGetAccSnapshot(J9VMThread * currentThread, J9StackWalkState * walkState);59static UDATA frameIteratorGetAccSnapshotHelper(J9VMThread * currentThread, J9StackWalkState * walkState, j9object_t acc, j9object_t perm);60static j9object_t storePDobjectsHelper(J9VMThread* vmThread, J9Class* arrayClass, J9StackWalkState* walkState, j9object_t contextObject, U_32 arraySize, UDATA framesWalked, I_32 startPos, BOOLEAN dupCallerPD);61static BOOLEAN checkInnerClassHelper(J9Class* declaringClass, J9Class* declaredClass);6263jobject JNICALL64Java_java_lang_Class_getDeclaredAnnotationsData(JNIEnv *env, jobject jlClass)65{66jobject result = NULL;67j9object_t clazz = NULL;68J9VMThread *vmThread = (J9VMThread *) env;6970enterVMFromJNI(vmThread);71clazz = J9_JNI_UNWRAP_REFERENCE(jlClass);72if (NULL != clazz) {73j9object_t annotationsData = getClassAnnotationData(vmThread, J9VM_J9CLASS_FROM_HEAPCLASS(vmThread, clazz));74if (NULL != annotationsData) {75result = vmThread->javaVM->internalVMFunctions->j9jni_createLocalRef(env, annotationsData);76}77}78exitVMToJNI(vmThread);79return result;80}8182static UDATA83isPrivilegedFrameIterator(J9VMThread * currentThread, J9StackWalkState * walkState)84{85J9JavaVM *vm = currentThread->javaVM;86J9JNIMethodID *doPrivilegedMethodID1 = (J9JNIMethodID *) vm->doPrivilegedMethodID1;87J9JNIMethodID *doPrivilegedMethodID2 = (J9JNIMethodID *) vm->doPrivilegedMethodID2;88J9JNIMethodID *doPrivilegedWithContextMethodID1 = (J9JNIMethodID *) vm->doPrivilegedWithContextMethodID1;89J9JNIMethodID *doPrivilegedWithContextMethodID2 = (J9JNIMethodID *) vm->doPrivilegedWithContextMethodID2;90J9Method *currentMethod = walkState->method;9192if (J9_ARE_ALL_BITS_SET(J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod)->modifiers, J9AccMethodFrameIteratorSkip)) {93/* Skip methods with java.lang.invoke.FrameIteratorSkip / jdk.internal.vm.annotation.Hidden / java.lang.invoke.LambdaForm$Hidden annotation */94return J9_STACKWALK_KEEP_ITERATING;95}9697if (NULL == walkState->userData2) {98J9Class * currentClass = J9_CLASS_FROM_CP(walkState->constantPool);99if ((walkState->method == vm->jlrMethodInvoke)100#if JAVA_SPEC_VERSION >= 18101|| (walkState->method == vm->jlrMethodInvokeMH)102#endif /* JAVA_SPEC_VERSION >= 18 */103|| (walkState->method == vm->jliMethodHandleInvokeWithArgs)104|| (walkState->method == vm->jliMethodHandleInvokeWithArgsList)105|| (vm->srMethodAccessor && VM_VMHelpers::isSameOrSuperclass(J9VM_J9CLASS_FROM_JCLASS(currentThread, vm->srMethodAccessor), currentClass))106) {107/* skip reflection/MethodHandleInvoke frames */108} else {109return J9_STACKWALK_STOP_ITERATING;110}111}112113if ( ((doPrivilegedMethodID1 != NULL) && (currentMethod == doPrivilegedMethodID1->method)) ||114((doPrivilegedMethodID2 != NULL) && (currentMethod == doPrivilegedMethodID2->method))115) {116/* Context is NULL */117walkState->userData1 = NULL;118walkState->userData2 = NULL;119}120121if ( ((doPrivilegedWithContextMethodID1 != NULL) && (currentMethod == doPrivilegedWithContextMethodID1->method)) ||122((doPrivilegedWithContextMethodID2 != NULL) && (currentMethod == doPrivilegedWithContextMethodID2->method))123) {124/* Grab the Context from the arguments: ultra-scary: fetch arg2 from the doPrivileged() method */125walkState->userData1 = (void *)walkState->arg0EA[-1];126walkState->userData2 = NULL;127}128129return J9_STACKWALK_KEEP_ITERATING;130}131132jobject JNICALL133Java_java_lang_Class_getStackClasses(JNIEnv *env, jclass jlHeapClass, jint maxDepth, jboolean stopAtPrivileged)134{135J9VMThread *vmThread = (J9VMThread *) env;136J9JavaVM *vm = vmThread->javaVM;137J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;138J9StackWalkState walkState = {0};139J9Class *jlClass = NULL;140J9Class *arrayClass = NULL;141UDATA walkFlags = J9_STACKWALK_CACHE_METHODS | J9_STACKWALK_COUNT_SPECIFIED | J9_STACKWALK_VISIBLE_ONLY | J9_STACKWALK_INCLUDE_NATIVES;142UDATA framesWalked = 0;143UDATA *cacheContents = NULL;144UDATA i = 0;145j9object_t arrayObject = NULL;146jobject result = NULL;147148vmFuncs->internalEnterVMFromJNI(vmThread);149150/* Fetch the Class[] class before doing the stack walk. */151jlClass = J9VMJAVALANGCLASS(vm);152153arrayClass = fetchArrayClass(vmThread, jlClass);154if (NULL != vmThread->currentException) {155goto _throwException;156}157158/* Walk the stack, caching the constant pools of the frames. If we're stopping at159* privileged frames, specify a frame walk function.160*/161walkState.skipCount = 2; /*skip this JNI frame and the local caller */162walkState.userData1 = STACK_WALK_STATE_MAGIC; /* value which will not be written into userData1 by the frame walk function (which writes only null or an object pointer) */163walkState.userData2 = STACK_WALK_STATE_MAGIC; /* value which will not be written into userData2 by the frame walk function (which writes only null) */164walkState.maxFrames = maxDepth;165walkState.walkThread = vmThread;166167if (stopAtPrivileged) {168walkFlags |= J9_STACKWALK_ITERATE_FRAMES;169walkState.frameWalkFunction = isPrivilegedFrameIterator;170}171walkState.flags = walkFlags;172173if (vm->walkStackFrames(vmThread, &walkState) != J9_STACKWALK_RC_NONE) {174vmFuncs->setNativeOutOfMemoryError(vmThread, 0, 0);175goto _throwException;176}177178/* If a privileged frame caused us to stop walking, do not include that179* frame (the last one walked) in the array.180*/181framesWalked = walkState.framesWalked;182if (STACK_WALK_STATE_MAGIC != walkState.userData1) {183framesWalked -= 1;184}185186/* Translate cached CPs into J9Class * and nil any entries that are for reflect frames. */187cacheContents = walkState.cache;188189for (i = framesWalked; i > 0; i--) {190J9Method *currentMethod = (J9Method *)*cacheContents;191J9Class *currentClass = J9_CLASS_FROM_METHOD(currentMethod);192193if ( J9_ARE_ALL_BITS_SET(J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod)->modifiers, J9AccMethodFrameIteratorSkip) ||194(vm->jliArgumentHelper && instanceOfOrCheckCast(currentClass, J9VM_J9CLASS_FROM_JCLASS(vmThread, vm->jliArgumentHelper))) ||195(vm->srMethodAccessor && vmFuncs->instanceOfOrCheckCast(currentClass, J9VM_J9CLASS_FROM_HEAPCLASS(vmThread, *((j9object_t*) vm->srMethodAccessor)))) ||196(vm->srConstructorAccessor && vmFuncs->instanceOfOrCheckCast(currentClass, J9VM_J9CLASS_FROM_HEAPCLASS(vmThread, *((j9object_t*) vm->srConstructorAccessor))))197) {198currentClass = NULL;199framesWalked--;200}201*cacheContents++ = (UDATA) currentClass;202}203204/* Allocate the result array. */205arrayObject = vm->memoryManagerFunctions->J9AllocateIndexableObject(vmThread, arrayClass, (U_32)framesWalked, J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);206if (NULL == arrayObject) {207vmFuncs->freeStackWalkCaches(vmThread, &walkState);208vmFuncs->setHeapOutOfMemoryError(vmThread);209goto _throwException;210}211212/* Fill in the array. */213if (framesWalked != 0) {214I_32 resultIndex = 0;215216cacheContents = walkState.cache;217218for (i = framesWalked; i > 0; i--) {219J9Class *clazz = (J9Class *)(*cacheContents++);220/* Ignore zero entries (removed reflect frames). */221while (NULL == clazz) {222clazz = (J9Class *)(*cacheContents++);223}224J9JAVAARRAYOFOBJECT_STORE(vmThread, arrayObject, resultIndex, J9VM_J9CLASS_TO_HEAPCLASS(clazz));225resultIndex++;226}227}228229vmFuncs->freeStackWalkCaches(vmThread, &walkState);230result = vmFuncs->j9jni_createLocalRef(env, arrayObject);231232_throwException:233vmFuncs->internalExitVMToJNI(vmThread);234235return result;236}237238jboolean JNICALL239Java_java_lang_Class_isClassADeclaredClass(JNIEnv *env, jobject jlClass, jobject aClass)240{241J9VMThread *vmThread = (J9VMThread *) env;242J9Class *declaringClass = NULL;243J9Class *declaredClass = NULL;244jboolean result = JNI_FALSE;245246enterVMFromJNI(vmThread);247248declaringClass = J9VM_J9CLASS_FROM_HEAPCLASS(vmThread, J9_JNI_UNWRAP_REFERENCE(jlClass));249declaredClass = J9VM_J9CLASS_FROM_HEAPCLASS(vmThread, J9_JNI_UNWRAP_REFERENCE(aClass));250251if (checkInnerClassHelper(declaringClass, declaredClass)) {252result = JNI_TRUE;253}254255exitVMToJNI(vmThread);256return result;257}258259jboolean JNICALL260Java_java_lang_Class_isClassAnEnclosedClass(JNIEnv *env, jobject jlClass, jobject aClass)261{262J9VMThread *vmThread = (J9VMThread *) env;263J9Class *enclosingClass = NULL;264U_32 enclosedInnerClassCount = 0;265J9Class *enclosedClass = NULL;266J9UTF8 *enclosedClassName = NULL;267J9SRP *srpCursor = NULL;268jboolean result = JNI_FALSE;269U_32 i = 0;270271enterVMFromJNI(vmThread);272273enclosingClass = J9VM_J9CLASS_FROM_HEAPCLASS(vmThread, J9_JNI_UNWRAP_REFERENCE(jlClass));274enclosedInnerClassCount = enclosingClass->romClass->enclosedInnerClassCount;275enclosedClass = J9VM_J9CLASS_FROM_HEAPCLASS(vmThread, J9_JNI_UNWRAP_REFERENCE(aClass));276enclosedClassName = J9ROMCLASS_CLASSNAME(enclosedClass->romClass);277278if (checkInnerClassHelper(enclosingClass, enclosedClass)) {279result = JNI_TRUE;280} else {281srpCursor = J9ROMCLASS_ENCLOSEDINNERCLASSES(enclosingClass->romClass);282for (i = 0; i < enclosedInnerClassCount; i++) {283J9UTF8 *enclosedInnerClassName = SRP_PTR_GET(srpCursor, J9UTF8 *);284if (0 == compareUTF8Length(J9UTF8_DATA(enclosedClassName), J9UTF8_LENGTH(enclosedClassName),285J9UTF8_DATA(enclosedInnerClassName), J9UTF8_LENGTH(enclosedInnerClassName))) {286/* aClass' class name matches one of the enclosed inner classes of 'this',287* therefore aClass is one of this' enclosed classes */288result = JNI_TRUE;289break;290}291srpCursor++;292}293}294295exitVMToJNI(vmThread);296return result;297}298299static BOOLEAN300checkInnerClassHelper(J9Class* declaringClass, J9Class* declaredClass)301{302U_32 innerClassCount = declaringClass->romClass->innerClassCount;303J9SRP *srpCursor = J9ROMCLASS_INNERCLASSES(declaringClass->romClass);304J9UTF8* declaredClassName = J9ROMCLASS_CLASSNAME(declaredClass->romClass);305U_32 i = 0;306307for (i = 0; i < innerClassCount; i++) {308J9UTF8 *innerClassName = SRP_PTR_GET(srpCursor, J9UTF8 *);309if (0 == compareUTF8Length(J9UTF8_DATA(declaredClassName), J9UTF8_LENGTH(declaredClassName),310J9UTF8_DATA(innerClassName), J9UTF8_LENGTH(innerClassName))) {311/* aClass' class name matches one of the inner classes of 'this',312* therefore aClass is one of this' declared classes */313return TRUE;314}315srpCursor++;316}317return FALSE;318}319320jboolean JNICALL321Java_java_lang_Class_isCircularDeclaringClass(JNIEnv *env, jobject recv)322{323J9VMThread *currentThread = (J9VMThread*)env;324J9JavaVM *vm = currentThread->javaVM;325J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;326jboolean result = JNI_FALSE;327328vmFuncs->internalEnterVMFromJNI(currentThread);329330J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(recv));331J9Class *currentClazz = clazz;332J9UTF8 *outerClassName = J9ROMCLASS_OUTERCLASSNAME(currentClazz->romClass);333while (NULL != outerClassName) {334J9Class *outerClass = vmFuncs->internalFindClassUTF8(currentThread, J9UTF8_DATA(outerClassName),335J9UTF8_LENGTH(outerClassName), currentClazz->classLoader, 0);336if (NULL == outerClass) {337break;338} else if (clazz == outerClass) {339result = JNI_TRUE;340break;341}342currentClazz = outerClass;343outerClassName = J9ROMCLASS_OUTERCLASSNAME(currentClazz->romClass);344}345346vmFuncs->internalExitVMToJNI(currentThread);347return result;348}349350jobject JNICALL351Java_com_ibm_oti_vm_VM_getClassNameImpl(JNIEnv *env, jclass recv, jclass jlClass, jboolean internAndAssign)352{353J9VMThread *currentThread = (J9VMThread *) env;354J9JavaVM *vm = currentThread->javaVM;355J9InternalVMFunctions const * const vmFuncs = vm->internalVMFunctions;356jobject classNameRef = NULL;357358vmFuncs->internalEnterVMFromJNI(currentThread);359360j9object_t classNameObject = VM_VMHelpers::getClassNameString(currentThread, J9_JNI_UNWRAP_REFERENCE(jlClass), JNI_FALSE != internAndAssign);361if (NULL != classNameObject) {362classNameRef = vmFuncs->j9jni_createLocalRef(env, classNameObject);363if (NULL == classNameRef) {364vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);365}366}367368vmFuncs->internalExitVMToJNI(currentThread);369return classNameRef;370}371372jarray JNICALL373Java_java_lang_Class_getDeclaredFieldsImpl(JNIEnv *env, jobject recv)374{375return getDeclaredFieldsHelper(env, recv);376}377378jobject JNICALL379Java_java_lang_Class_getGenericSignature(JNIEnv *env, jobject recv)380{381J9VMThread *currentThread = (J9VMThread*)env;382J9JavaVM *vm = currentThread->javaVM;383J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;384jobject result = NULL;385j9object_t classObject = NULL;386J9Class *clazz = NULL;387J9ROMClass *romClass = NULL;388J9UTF8 *signature = NULL;389390vmFuncs->internalEnterVMFromJNI(currentThread);391classObject = J9_JNI_UNWRAP_REFERENCE(recv);392clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, classObject);393romClass = clazz->romClass;394signature = getGenericSignatureForROMClass(vm, clazz->classLoader, romClass);395if (NULL != signature) {396j9object_t stringObject = vm->memoryManagerFunctions->j9gc_createJavaLangString(currentThread, J9UTF8_DATA(signature), J9UTF8_LENGTH(signature), 0);397result = vmFuncs->j9jni_createLocalRef(env, stringObject);398releaseOptInfoBuffer(vm, romClass);399}400vmFuncs->internalExitVMToJNI(currentThread);401return result;402}403404/**405* Determines if a method is a normal method (not <clinit> or <init>).406*407* @param romMethod[in] the ROM method408*409* @returns true if the method is <init> or <clinit>, false if not410*/411static VMINLINE bool412isSpecialMethod(J9ROMMethod *romMethod)413{414return '<' == (char)*J9UTF8_DATA(J9ROMMETHOD_NAME(romMethod));415}416417/**418* Determines if a method is <init>.419*420* @param romMethod[in] the ROM method421*422* @returns true if this is <init>, false if not423*/424static VMINLINE bool425isConstructor(J9ROMMethod *romMethod)426{427return (J9_ARE_NO_BITS_SET(romMethod->modifiers, J9AccStatic)) && isSpecialMethod(romMethod);428}429430/**431* Determines if a method is a static method which should be reported.432*433* @param romMethod[in] the ROM method434*435* @returns true if this is public, static and not <clinit>, false if not436*/437static VMINLINE bool438isNormalStaticMethod(J9ROMMethod *romMethod)439{440return J9_ARE_ALL_BITS_SET(romMethod->modifiers, J9AccPublic | J9AccStatic) && !isSpecialMethod(romMethod);441}442443/**444* Get the constructors for a Class.445*446* @param env[in] the JNIEnv447* @param recv[in] the receiver448* @param mustBePublic[in] true if only public methods are to be returned, false if not449*450* @returns true if this is <init>, false if not451*/452static jobject453getConstructorsHelper(JNIEnv *env, jobject recv, bool mustBePublic)454{455J9VMThread *currentThread = (J9VMThread*)env;456J9JavaVM *vm = currentThread->javaVM;457J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;458J9MemoryManagerFunctions *mmFuncs = vm->memoryManagerFunctions;459j9object_t resultObject = NULL;460vmFuncs->internalEnterVMFromJNI(currentThread);461462J9Class *arrayClass = fetchArrayClass(currentThread, J9VMJAVALANGREFLECTCONSTRUCTOR_OR_NULL(vm));463464retry:465J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(recv));466J9ROMClass *romClass = clazz->romClass;467U_32 size = 0;468UDATA preCount = vm->hotSwapCount;469470/* primitives/arrays don't have local methods */471if (!J9ROMCLASS_IS_PRIMITIVE_OR_ARRAY(romClass)) {472J9Method *currentMethod = clazz->ramMethods;473J9Method *endOfMethods = currentMethod + romClass->romMethodCount;474while (currentMethod != endOfMethods) {475J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod);476if (isConstructor(romMethod) && (!mustBePublic || J9_ARE_ANY_BITS_SET(romMethod->modifiers, J9AccPublic))) {477size += 1;478}479currentMethod += 1;480}481}482483if (NULL != arrayClass) {484resultObject = mmFuncs->J9AllocateIndexableObject(currentThread, arrayClass, size, J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);485if (vm->hotSwapCount != preCount) {486goto retry;487} else if (NULL == resultObject) {488vmFuncs->setHeapOutOfMemoryError(currentThread);489} else {490J9Method *currentMethod = clazz->ramMethods;491U_32 index = 0;492J9Method *endOfMethods = currentMethod + romClass->romMethodCount;493while (currentMethod != endOfMethods) {494J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod);495if (isConstructor(romMethod) && (!mustBePublic || J9_ARE_ANY_BITS_SET(romMethod->modifiers, J9AccPublic))) {496PUSH_OBJECT_IN_SPECIAL_FRAME(currentThread, resultObject);497j9object_t element = vm->reflectFunctions.createConstructorObject(currentMethod, clazz, NULL, currentThread);498resultObject = POP_OBJECT_IN_SPECIAL_FRAME(currentThread);499if (vm->hotSwapCount != preCount) {500goto retry;501} else if (NULL == element) {502break;503}504J9JAVAARRAYOFOBJECT_STORE(currentThread, resultObject, index, element);505index += 1;506}507currentMethod += 1;508}509}510}511jobject result = vmFuncs->j9jni_createLocalRef(env, resultObject);512vmFuncs->internalExitVMToJNI(currentThread);513return result;514}515516/**517* Get a particular constructor for a Class.518*519* @param env[in] the JNIEnv520* @param recv[in] the receiver521* @param parameterTypes[in] the parameter types array522* @param signature[in] the signature523* @param mustBePublic[in] true if only public methods are to be returned, false if not524*525* @returns true if this is <init>, false if not526*/527static jobject528getConstructorHelper(JNIEnv *env, jobject recv, jobject parameterTypes, jobject signature, bool mustBePublic)529{530J9VMThread *currentThread = (J9VMThread*)env;531J9JavaVM *vm = currentThread->javaVM;532J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;533j9object_t resultObject = NULL;534vmFuncs->internalEnterVMFromJNI(currentThread);535536retry:537J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(recv));538if (NULL == signature) {539vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, NULL);540} else {541J9ROMClass *romClass = clazz->romClass;542/* primitives/arrays don't have local methods */543if (!J9ROMCLASS_IS_PRIMITIVE_OR_ARRAY(romClass)) {544j9object_t signatureObject = J9_JNI_UNWRAP_REFERENCE(signature);545J9Method *currentMethod = clazz->ramMethods;546J9Method *endOfMethods = currentMethod + romClass->romMethodCount;547UDATA preCount = vm->hotSwapCount;548while (currentMethod != endOfMethods) {549J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod);550if (isConstructor(romMethod) && (!mustBePublic || J9_ARE_ANY_BITS_SET(romMethod->modifiers, J9AccPublic))) {551J9UTF8 *signatureUTF = J9ROMMETHOD_SIGNATURE(romMethod);552if (0 != vmFuncs->compareStringToUTF8(currentThread, signatureObject, TRUE, J9UTF8_DATA(signatureUTF), J9UTF8_LENGTH(signatureUTF))) {553j9object_t parameterTypesObject = NULL;554if (NULL != parameterTypes) {555parameterTypesObject = J9_JNI_UNWRAP_REFERENCE(parameterTypes);556}557resultObject = vm->reflectFunctions.createConstructorObject(currentMethod, clazz, (j9array_t)parameterTypesObject, currentThread);558if (vm->hotSwapCount != preCount) {559goto retry;560}561break;562}563}564currentMethod += 1;565}566}567}568jobject result = vmFuncs->j9jni_createLocalRef(env, resultObject);569vmFuncs->internalExitVMToJNI(currentThread);570return result;571}572573jobject JNICALL574Java_java_lang_Class_allocateAndFillArray(JNIEnv *env, jobject recv, jint size)575{576J9VMThread *currentThread = (J9VMThread*)env;577J9JavaVM *vm = currentThread->javaVM;578J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;579J9MemoryManagerFunctions *mmFuncs = vm->memoryManagerFunctions;580j9object_t resultObject = NULL;581vmFuncs->internalEnterVMFromJNI(currentThread);582J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(recv));583J9Class *arrayClass = fetchArrayClass(currentThread, clazz);584if (NULL != arrayClass) {585resultObject = mmFuncs->J9AllocateIndexableObject(currentThread, arrayClass, (U_32)size, J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);586if (NULL == resultObject) {587oom:588vmFuncs->setHeapOutOfMemoryError(currentThread);589} else {590for (U_32 i = 0; i < (U_32)size; ++i) {591PUSH_OBJECT_IN_SPECIAL_FRAME(currentThread, resultObject);592j9object_t element = mmFuncs->J9AllocateObject(currentThread, clazz, J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);593resultObject = POP_OBJECT_IN_SPECIAL_FRAME(currentThread);594if (NULL == element) {595goto oom;596}597J9JAVAARRAYOFOBJECT_STORE(currentThread, resultObject, i, element);598}599}600}601jobject result = vmFuncs->j9jni_createLocalRef(env, resultObject);602vmFuncs->internalExitVMToJNI(currentThread);603return result;604}605606jobject JNICALL607Java_java_lang_Class_getConstructorImpl(JNIEnv *env, jobject recv, jobject parameterTypes, jobject signature)608{609return getConstructorHelper(env, recv, parameterTypes, signature, true);610}611612jobject JNICALL613Java_java_lang_Class_getConstructorsImpl(JNIEnv *env, jobject recv)614{615return getConstructorsHelper(env, recv, true);616}617618jobject JNICALL619Java_java_lang_Class_getDeclaredClassesImpl(JNIEnv *env, jobject recv)620{621J9VMThread *currentThread = (J9VMThread*)env;622J9JavaVM *vm = currentThread->javaVM;623J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;624J9MemoryManagerFunctions *mmFuncs = vm->memoryManagerFunctions;625j9object_t resultObject = NULL;626vmFuncs->internalEnterVMFromJNI(currentThread);627J9Class *arrayClass = fetchArrayClass(currentThread, J9VMJAVALANGCLASS_OR_NULL(vm));628629retry:630J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(recv));631J9ROMClass *romClass = clazz->romClass;632U_32 size = romClass->innerClassCount;633UDATA preCount = vm->hotSwapCount;634635if (NULL != arrayClass) {636resultObject = mmFuncs->J9AllocateIndexableObject(currentThread, arrayClass, size, J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);637if (vm->hotSwapCount != preCount) {638goto retry;639} else if (NULL == resultObject) {640vmFuncs->setHeapOutOfMemoryError(currentThread);641} else {642J9ClassLoader *classLoader = clazz->classLoader;643J9SRP *innerClasses = J9ROMCLASS_INNERCLASSES(romClass);644645for (U_32 i = 0; i < size; ++i) {646J9UTF8 *className = NNSRP_PTR_GET(innerClasses, J9UTF8*);647PUSH_OBJECT_IN_SPECIAL_FRAME(currentThread, resultObject);648J9Class *innerClazz = vmFuncs->internalFindClassUTF8(currentThread, J9UTF8_DATA(className), J9UTF8_LENGTH(className), classLoader, J9_FINDCLASS_FLAG_THROW_ON_FAIL);649resultObject = POP_OBJECT_IN_SPECIAL_FRAME(currentThread);650if (vm->hotSwapCount != preCount) {651goto retry;652}653if (NULL == innerClazz) {654break;655}656J9JAVAARRAYOFOBJECT_STORE(currentThread, resultObject, i, J9VM_J9CLASS_TO_HEAPCLASS(innerClazz));657innerClasses += 1;658}659}660}661jobject result = vmFuncs->j9jni_createLocalRef(env, resultObject);662vmFuncs->internalExitVMToJNI(currentThread);663return result;664}665666jobject JNICALL667Java_java_lang_Class_getDeclaredConstructorImpl(JNIEnv *env, jobject recv, jobject parameterTypes, jobject signature)668{669return getConstructorHelper(env, recv, parameterTypes, signature, false);670}671672jobject JNICALL673Java_java_lang_Class_getDeclaredConstructorsImpl(JNIEnv *env, jobject recv)674{675return getConstructorsHelper(env, recv, false);676}677678jobject JNICALL679Java_java_lang_Class_getDeclaredMethodImpl(JNIEnv *env, jobject recv, jobject name, jobject parameterTypes, jobject partialSignature, jobject startingPoint)680{681J9VMThread *currentThread = (J9VMThread*)env;682J9JavaVM *vm = currentThread->javaVM;683J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;684j9object_t resultObject = NULL;685vmFuncs->internalEnterVMFromJNI(currentThread);686687retry:688J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(recv));689if ((NULL == name) || (NULL == partialSignature)) {690vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, NULL);691} else {692J9ROMClass *romClass = clazz->romClass;693UDATA preCount = vm->hotSwapCount;694695/* primitives/arrays don't have local methods */696if (!J9ROMCLASS_IS_PRIMITIVE_OR_ARRAY(romClass)) {697j9object_t nameObject = J9_JNI_UNWRAP_REFERENCE(name);698j9object_t signatureObject = J9_JNI_UNWRAP_REFERENCE(partialSignature);699J9Method *currentMethod = clazz->ramMethods;700J9Method *endOfMethods = currentMethod + romClass->romMethodCount;701if (NULL != startingPoint) {702j9object_t methodObject = J9_JNI_UNWRAP_REFERENCE(startingPoint);703J9JNIMethodID *id = vm->reflectFunctions.idFromMethodObject(currentThread, methodObject);704currentMethod = id->method + 1;705}706while (currentMethod != endOfMethods) {707J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod);708if (!isSpecialMethod(romMethod)) {709J9UTF8 *nameUTF = J9ROMMETHOD_NAME(romMethod);710J9UTF8 *signatureUTF = J9ROMMETHOD_SIGNATURE(romMethod);711if (0 != vmFuncs->compareStringToUTF8(currentThread, nameObject, FALSE, J9UTF8_DATA(nameUTF), J9UTF8_LENGTH(nameUTF))) {712if (0 != compareJavaStringToPartialUTF8(currentThread, signatureObject, J9UTF8_DATA(signatureUTF), J9UTF8_LENGTH(signatureUTF))) {713j9object_t parameterTypesObject = NULL;714if (NULL != parameterTypes) {715parameterTypesObject = J9_JNI_UNWRAP_REFERENCE(parameterTypes);716}717resultObject = vm->reflectFunctions.createDeclaredMethodObject(currentMethod, clazz, (j9array_t)parameterTypesObject, currentThread);718if (vm->hotSwapCount != preCount) {719goto retry;720}721break;722}723}724}725currentMethod += 1;726}727}728}729jobject result = vmFuncs->j9jni_createLocalRef(env, resultObject);730vmFuncs->internalExitVMToJNI(currentThread);731return result;732}733734jobject JNICALL735Java_java_lang_Class_getDeclaredMethodsImpl(JNIEnv *env, jobject recv)736{737J9VMThread *currentThread = (J9VMThread*)env;738J9JavaVM *vm = currentThread->javaVM;739J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;740J9MemoryManagerFunctions *mmFuncs = vm->memoryManagerFunctions;741j9object_t resultObject = NULL;742vmFuncs->internalEnterVMFromJNI(currentThread);743J9Class *arrayClass = fetchArrayClass(currentThread, J9VMJAVALANGREFLECTMETHOD_OR_NULL(vm));744745retry:746J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(recv));747J9ROMClass *romClass = clazz->romClass;748U_32 size = 0;749UDATA preCount = vm->hotSwapCount;750751/* primitives/arrays don't have local methods */752if (!J9ROMCLASS_IS_PRIMITIVE_OR_ARRAY(romClass)) {753J9Method *currentMethod = clazz->ramMethods;754J9Method *endOfMethods = currentMethod + romClass->romMethodCount;755while (currentMethod != endOfMethods) {756J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod);757if (!isSpecialMethod(romMethod)) {758size += 1;759}760currentMethod += 1;761}762}763764if (NULL != arrayClass) {765resultObject = mmFuncs->J9AllocateIndexableObject(currentThread, arrayClass, size, J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);766if (vm->hotSwapCount != preCount) {767goto retry;768} else if (NULL == resultObject) {769vmFuncs->setHeapOutOfMemoryError(currentThread);770} else {771J9Method *currentMethod = clazz->ramMethods;772U_32 index = 0;773J9Method *endOfMethods = currentMethod + romClass->romMethodCount;774while (currentMethod != endOfMethods) {775J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod);776if (!isSpecialMethod(romMethod)) {777PUSH_OBJECT_IN_SPECIAL_FRAME(currentThread, resultObject);778j9object_t element = vm->reflectFunctions.createDeclaredMethodObject(currentMethod, clazz, NULL, currentThread);779resultObject = POP_OBJECT_IN_SPECIAL_FRAME(currentThread);780if (vm->hotSwapCount != preCount) {781goto retry;782}783if (NULL == element) {784break;785}786J9JAVAARRAYOFOBJECT_STORE(currentThread, resultObject, index, element);787index += 1;788}789currentMethod += 1;790}791}792}793jobject result = vmFuncs->j9jni_createLocalRef(env, resultObject);794vmFuncs->internalExitVMToJNI(currentThread);795return result;796}797798jobject JNICALL799Java_java_lang_Class_getDeclaringClassImpl(JNIEnv *env, jobject recv)800{801J9VMThread *currentThread = (J9VMThread*)env;802J9JavaVM *vm = currentThread->javaVM;803J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;804j9object_t resultObject = NULL;805vmFuncs->internalEnterVMFromJNI(currentThread);806J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(recv));807J9ROMClass *romClass = clazz->romClass;808J9UTF8 *outerClassName = J9ROMCLASS_OUTERCLASSNAME(romClass);809if (NULL != outerClassName) {810J9Class *outerClass = vmFuncs->internalFindClassUTF8(currentThread, J9UTF8_DATA(outerClassName), J9UTF8_LENGTH(outerClassName), clazz->classLoader, J9_FINDCLASS_FLAG_THROW_ON_FAIL);811resultObject = J9VM_J9CLASS_TO_HEAPCLASS(outerClass);812}813jobject result = vmFuncs->j9jni_createLocalRef(env, resultObject);814vmFuncs->internalExitVMToJNI(currentThread);815return result;816}817818jobject JNICALL819Java_java_lang_Class_getEnclosingObject(JNIEnv *env, jobject recv)820{821J9VMThread *currentThread = (J9VMThread*)env;822J9JavaVM *vm = currentThread->javaVM;823J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;824j9object_t resultObject = NULL;825vmFuncs->internalEnterVMFromJNI(currentThread);826J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(recv));827J9ROMClass *romClass = clazz->romClass;828/* primitives/arrays don't have enclosing objects */829if (!J9ROMCLASS_IS_PRIMITIVE_OR_ARRAY(romClass)) {830J9EnclosingObject *methodRef = getEnclosingMethodForROMClass(vm, clazz->classLoader, romClass);831if (NULL != methodRef) {832J9ROMNameAndSignature *nas = J9ENCLOSINGOBJECT_NAMEANDSIGNATURE(methodRef);833if (NULL != nas) {834J9Class *resolvedClass = vmFuncs->resolveClassRef(currentThread, J9_CP_FROM_CLASS(clazz), methodRef->classRefCPIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE);835if (NULL != resolvedClass) {836J9UTF8 *enclosingMethodNameUTF = J9ROMNAMEANDSIGNATURE_NAME(nas);837J9UTF8 *enclosingMethodSigUTF = J9ROMNAMEANDSIGNATURE_SIGNATURE(nas);838J9Method *method = vmFuncs->searchClassForMethod(resolvedClass, J9UTF8_DATA(enclosingMethodNameUTF), J9UTF8_LENGTH(enclosingMethodNameUTF), J9UTF8_DATA(enclosingMethodSigUTF), J9UTF8_LENGTH(enclosingMethodSigUTF));839if (NULL != method) {840J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);841if (!isSpecialMethod(romMethod)) {842resultObject = vm->reflectFunctions.createDeclaredMethodObject(method, resolvedClass, NULL, currentThread);843} else if (isConstructor(romMethod)) {844resultObject = vm->reflectFunctions.createDeclaredConstructorObject(method, resolvedClass, NULL, currentThread);845}846}847}848}849releaseOptInfoBuffer(vm, romClass);850}851}852jobject result = vmFuncs->j9jni_createLocalRef(env, resultObject);853vmFuncs->internalExitVMToJNI(currentThread);854return result;855}856857jobject JNICALL858Java_java_lang_Class_getEnclosingObjectClass(JNIEnv *env, jobject recv)859{860J9VMThread *currentThread = (J9VMThread*)env;861J9JavaVM *vm = currentThread->javaVM;862J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;863j9object_t resultObject = NULL;864vmFuncs->internalEnterVMFromJNI(currentThread);865J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(recv));866J9ROMClass *romClass = clazz->romClass;867/* primitives/arrays don't have enclosing objects */868if (!J9ROMCLASS_IS_PRIMITIVE_OR_ARRAY(romClass)) {869J9EnclosingObject *methodRef = getEnclosingMethodForROMClass(vm, clazz->classLoader, romClass);870if (NULL != methodRef) {871J9Class *resolvedClass = vmFuncs->resolveClassRef(currentThread, J9_CP_FROM_CLASS(clazz), methodRef->classRefCPIndex, J9_RESOLVE_FLAG_RUNTIME_RESOLVE);872resultObject = J9VM_J9CLASS_TO_HEAPCLASS(resolvedClass);873releaseOptInfoBuffer(vm, romClass);874}875}876jobject result = vmFuncs->j9jni_createLocalRef(env, resultObject);877vmFuncs->internalExitVMToJNI(currentThread);878return result;879}880881jobject JNICALL882Java_java_lang_Class_getFieldImpl(JNIEnv *env, jobject recv, jstring name)883{884return getFieldHelper(env, recv, name);885}886887jobject JNICALL888Java_java_lang_Class_getDeclaredFieldImpl(JNIEnv *env, jobject recv, jstring name)889{890return getDeclaredFieldHelper(env, recv, name);891}892893jarray JNICALL894Java_java_lang_Class_getFieldsImpl(JNIEnv *env, jobject recv)895{896return getFieldsHelper(env, recv);897}898899jobject JNICALL900Java_java_lang_Class_getMethodImpl(JNIEnv *env, jobject recv, jobject name, jobject parameterTypes, jobject partialSignature)901{902J9VMThread *currentThread = (J9VMThread*)env;903J9JavaVM *vm = currentThread->javaVM;904J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;905j9object_t resultObject = NULL;906vmFuncs->internalEnterVMFromJNI(currentThread);907908PORT_ACCESS_FROM_VMC(currentThread);909if ((NULL == name) || (NULL == partialSignature)) {910vmFuncs->setCurrentExceptionUTF(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, NULL);911} else {912J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(recv));913J9ROMClass *romClass = clazz->romClass;914915/* primitives doesn't have local methods */916if (!J9ROMCLASS_IS_PRIMITIVE_TYPE(romClass)) {917J9Method *currentMethod = NULL;918j9object_t nameObject = J9_JNI_UNWRAP_REFERENCE(name);919j9object_t signatureObject = J9_JNI_UNWRAP_REFERENCE(partialSignature);920UDATA lookupFLags = J9_LOOK_JNI | J9_LOOK_NO_THROW | J9_LOOK_PARTIAL_SIGNATURE | (J9ROMCLASS_IS_INTERFACE(romClass) ? (J9_LOOK_INTERFACE | J9_LOOK_NO_JLOBJECT) : 0);921922J9JNINameAndSignature nameAndSig;923char nameBuffer[J9VM_PACKAGE_NAME_BUFFER_LENGTH];924UDATA nameBufferLength = 0;925char signatureBuffer[J9VM_PACKAGE_NAME_BUFFER_LENGTH];926UDATA signatureLength = 0;927nameAndSig.name = nameBuffer;928nameAndSig.nameLength = 0;929nameAndSig.signature = signatureBuffer;930nameAndSig.signatureLength = 0;931932nameAndSig.name = vmFuncs->copyStringToUTF8WithMemAlloc(933currentThread, nameObject, J9_STR_NULL_TERMINATE_RESULT, "", 0, nameBuffer, J9VM_PACKAGE_NAME_BUFFER_LENGTH, &nameBufferLength);934if (NULL == nameAndSig.name) {935goto _done;936}937nameAndSig.nameLength = (U_32)nameBufferLength;938939nameAndSig.signature = vmFuncs->copyStringToUTF8WithMemAlloc(940currentThread, signatureObject, J9_STR_NULL_TERMINATE_RESULT | J9_STR_XLAT, "", 0, signatureBuffer, J9VM_PACKAGE_NAME_BUFFER_LENGTH, &signatureLength);941if (NULL == nameAndSig.signature) {942goto _done;943}944nameAndSig.signatureLength = (U_32)signatureLength;945946currentMethod = (J9Method *) vmFuncs->javaLookupMethodImpl(currentThread, clazz, ((J9ROMNameAndSignature *) &nameAndSig), NULL, lookupFLags, NULL);947if (NULL == currentMethod) { /* by default we look for virtual methods. Try static methods. */948lookupFLags |= J9_LOOK_STATIC;949currentMethod = (J9Method *) vmFuncs->javaLookupMethodImpl(currentThread, clazz, ((J9ROMNameAndSignature *) &nameAndSig), NULL, lookupFLags, NULL);950}951952953Trc_JCL_getMethodImpl_result(currentThread, nameAndSig.nameLength, nameAndSig.name, nameAndSig.signatureLength, nameAndSig.signature, currentMethod);954_done:955if (nameAndSig.name != nameBuffer) {956j9mem_free_memory((void *)nameAndSig.name);957}958if (nameAndSig.signature != signatureBuffer) {959j9mem_free_memory((void *)nameAndSig.signature);960}961962if (NULL != currentMethod) {963J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod);964if (J9_ARE_ALL_BITS_SET(romMethod->modifiers, J9AccPublic) && !isSpecialMethod(romMethod)) {965j9object_t parameterTypesObject = NULL;966if (NULL != parameterTypes) {967parameterTypesObject = J9_JNI_UNWRAP_REFERENCE(parameterTypes);968}969resultObject = vm->reflectFunctions.createMethodObject(currentMethod, clazz, (j9array_t)parameterTypesObject, currentThread);970}971}972}973}974jobject result = vmFuncs->j9jni_createLocalRef(env, resultObject);975vmFuncs->internalExitVMToJNI(currentThread);976return result;977}978979jint JNICALL980Java_java_lang_Class_getStaticMethodCountImpl(JNIEnv *env, jobject recv)981{982J9VMThread *currentThread = (J9VMThread*)env;983J9JavaVM *vm = currentThread->javaVM;984J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;985jint result = 0;986vmFuncs->internalEnterVMFromJNI(currentThread);987J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(recv));988do {989J9ROMClass *romClass = clazz->romClass;990J9Method *currentMethod = clazz->ramMethods;991J9Method *endOfMethods = currentMethod + romClass->romMethodCount;992while (currentMethod != endOfMethods) {993J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod);994if (isNormalStaticMethod(romMethod)) {995result += 1;996}997currentMethod += 1;998}999clazz = VM_VMHelpers::getSuperclass(clazz);1000} while (NULL != clazz);1001vmFuncs->internalExitVMToJNI(currentThread);1002return result;1003}10041005jboolean JNICALL1006Java_java_lang_Class_getStaticMethodsImpl(JNIEnv *env, jobject recv, jobject array, jint start, jint count)1007{1008J9VMThread *currentThread = (J9VMThread*)env;1009J9JavaVM *vm = currentThread->javaVM;1010J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;1011vmFuncs->internalEnterVMFromJNI(currentThread);10121013jboolean result = JNI_TRUE;1014J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(recv));1015U_32 index = (U_32)start;1016jint numMethodFound = 0;1017UDATA preCount = vm->hotSwapCount;10181019do {1020J9ROMClass *romClass = clazz->romClass;1021J9Method *currentMethod = clazz->ramMethods;1022J9Method *endOfMethods = currentMethod + romClass->romMethodCount;10231024while ((currentMethod != endOfMethods) && (numMethodFound < count)) {1025J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod);1026if (isNormalStaticMethod(romMethod)) {1027J9JNIMethodID *methodID = vmFuncs->getJNIMethodID(currentThread, currentMethod);1028j9object_t resultObject = J9_JNI_UNWRAP_REFERENCE(array);1029j9object_t methodObject = J9JAVAARRAYOFOBJECT_LOAD(currentThread, resultObject, index);1030vm->reflectFunctions.fillInReflectMethod(methodObject, clazz, (jmethodID)methodID, currentThread);1031if (VM_VMHelpers::exceptionPending(currentThread)) {1032goto done;1033}1034index += 1;1035numMethodFound += 1;1036}1037currentMethod += 1;1038if (vm->hotSwapCount != preCount) {1039result = JNI_FALSE;1040goto done;1041}1042}1043clazz = VM_VMHelpers::getSuperclass(clazz);1044} while (NULL != clazz);10451046if (numMethodFound != count) {1047result = JNI_FALSE;1048}1049done:1050vmFuncs->internalExitVMToJNI(currentThread);1051return result;1052}10531054jint JNICALL1055Java_java_lang_Class_getVirtualMethodCountImpl(JNIEnv *env, jobject recv)1056{1057J9VMThread *currentThread = (J9VMThread*)env;1058J9JavaVM *vm = currentThread->javaVM;1059J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;1060vmFuncs->internalEnterVMFromJNI(currentThread);1061J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(recv));10621063J9VTableHeader *vTableHeader = J9VTABLE_HEADER_FROM_RAM_CLASS(clazz);1064UDATA count = vTableHeader->size;1065J9Method **vTableMethods = J9VTABLE_FROM_HEADER(vTableHeader);1066/* assuming constant number of public final methods in java.lang.Object */1067jint result = 6;1068for (UDATA index = 0; index < count; ++index) {1069J9Method *currentMethod = vTableMethods[index];1070J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod);1071if (J9_ARE_ANY_BITS_SET(romMethod->modifiers, J9AccPublic)) {1072if (VM_VMHelpers::hasDefaultConflictSendTarget(currentMethod)) {1073/*1074* PR 104809: getMethods() does not report multiple default implementations of the same method.1075* The method pointer has a link to the actual conflicting method. Return the method that's actually in the VTable.1076* Class.getMethods() will pick up the alternate implementation when it scans the class's interfaces.1077*/1078currentMethod = (J9Method *) (((UDATA)currentMethod->extra) & ~J9_STARTPC_NOT_TRANSLATED);1079}1080/* found a candidate, now reverse scan for a duplicate */1081for (UDATA scan = 0; scan < index; ++scan) {1082if (currentMethod == vTableMethods[scan]) {1083goto skip;1084}1085}1086result += 1;1087}1088skip: ;1089}1090vmFuncs->internalExitVMToJNI(currentThread);1091return result;1092}10931094jboolean JNICALL1095Java_java_lang_Class_getVirtualMethodsImpl(JNIEnv *env, jobject recv, jobject array, jint start, jint count)1096{1097J9VMThread *currentThread = (J9VMThread*)env;1098J9JavaVM *vm = currentThread->javaVM;1099J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;1100vmFuncs->internalEnterVMFromJNI(currentThread);1101J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(recv));1102U_32 index = (U_32)start;1103jint numMethodFound = 0;1104jboolean result = JNI_TRUE;1105UDATA preCount = vm->hotSwapCount;11061107/* First walk the vTable */1108{1109J9VTableHeader *vTableHeader = J9VTABLE_HEADER_FROM_RAM_CLASS(clazz);1110UDATA vTableSize = vTableHeader->size;1111J9Method **vTableMethods = J9VTABLE_FROM_HEADER(vTableHeader);1112for (UDATA progress = 0; ((progress < vTableSize) && (numMethodFound < count)); ++progress) {1113J9Method *currentMethod = vTableMethods[progress];1114J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod);1115if (J9_ARE_ANY_BITS_SET(romMethod->modifiers, J9AccPublic)) {1116if (VM_VMHelpers::hasDefaultConflictSendTarget(currentMethod)) {1117/*1118* PR 104809: getMethods() does not report multiple default implementations of the same method.1119* Does this affect Class.getMethods()?1120*/1121currentMethod = (J9Method *) (((UDATA)currentMethod->extra) & ~J9_STARTPC_NOT_TRANSLATED);1122}1123/* found a candidate, now reverse scan for a duplicate */1124for (UDATA scan = 0; scan < progress; ++scan) {1125if (currentMethod == vTableMethods[scan]) {1126goto skip;1127}1128}1129J9Class *declaringClass = J9_CLASS_FROM_METHOD(currentMethod);1130J9JNIMethodID *methodID = vmFuncs->getJNIMethodID(currentThread, currentMethod);1131j9object_t resultObject = J9_JNI_UNWRAP_REFERENCE(array);1132j9object_t methodObject = J9JAVAARRAYOFOBJECT_LOAD(currentThread, resultObject, index);1133vm->reflectFunctions.fillInReflectMethod(methodObject, declaringClass, (jmethodID)methodID, currentThread);1134if (VM_VMHelpers::exceptionPending(currentThread)) {1135goto done;1136}1137index += 1;1138numMethodFound += 1;1139}11401141if (vm->hotSwapCount != preCount) {1142result = JNI_FALSE;1143goto done;1144}1145skip: ;1146}1147}1148/* Now add the public final methods from Object */1149{1150J9Class *objectClass = J9VMJAVALANGOBJECT_OR_NULL(vm);1151J9ROMClass *romClass = objectClass->romClass;1152J9Method *currentMethod = objectClass->ramMethods;1153J9Method *endOfMethods = currentMethod + romClass->romMethodCount;1154while ((currentMethod != endOfMethods) && (numMethodFound < count)) {1155J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod);1156if (J9_ARE_ALL_BITS_SET(romMethod->modifiers, J9AccPublic | J9AccFinal)) {1157J9JNIMethodID *methodID = vmFuncs->getJNIMethodID(currentThread, currentMethod);1158j9object_t resultObject = J9_JNI_UNWRAP_REFERENCE(array);1159j9object_t methodObject = J9JAVAARRAYOFOBJECT_LOAD(currentThread, resultObject, index);1160vm->reflectFunctions.fillInReflectMethod(methodObject, objectClass, (jmethodID)methodID, currentThread);1161if (VM_VMHelpers::exceptionPending(currentThread)) {1162goto done;1163}1164index += 1;1165numMethodFound += 1;1166}11671168if (vm->hotSwapCount != preCount) {1169result = JNI_FALSE;1170goto done;1171}11721173currentMethod += 1;1174}11751176if (numMethodFound != count) {1177result = JNI_FALSE;1178goto done;1179}1180}1181done:1182vmFuncs->internalExitVMToJNI(currentThread);1183return result;1184}11851186#if JAVA_SPEC_VERSION >= 141187jarray JNICALL1188Java_java_lang_Class_getRecordComponentsImpl(JNIEnv *env, jobject cls)1189{1190return getRecordComponentsHelper(env, cls);1191}1192#endif /* JAVA_SPEC_VERSION >= 14 */11931194jarray JNICALL1195Java_java_lang_Class_permittedSubclassesImpl(JNIEnv *env, jobject cls)1196{1197return permittedSubclassesHelper(env, cls);1198}11991200static UDATA1201frameIteratorGetAccSnapshotHelper(J9VMThread * currentThread, J9StackWalkState * walkState, j9object_t acc, j9object_t perm)1202{1203PORT_ACCESS_FROM_VMC(currentThread);12041205DoPrivilegedMethodArgs* doPrivilegedMethodsArgs = (DoPrivilegedMethodArgs*)walkState->userData2;1206DoPrivilegedMethodArgs* doPrivilegedMethodsArgsTmp = (DoPrivilegedMethodArgs*)j9mem_allocate_memory(sizeof(DoPrivilegedMethodArgs), J9MEM_CATEGORY_VM_JCL);1207if (NULL == doPrivilegedMethodsArgsTmp) {1208currentThread->javaVM->internalVMFunctions->setNativeOutOfMemoryError(currentThread, 0, 0);1209return J9_STACKWALK_STOP_ITERATING;1210}1211memset(doPrivilegedMethodsArgsTmp, 0, sizeof(DoPrivilegedMethodArgs));12121213doPrivilegedMethodsArgsTmp->accControlContext = acc;1214doPrivilegedMethodsArgsTmp->permissions = perm;1215while (NULL != doPrivilegedMethodsArgs->next) {1216doPrivilegedMethodsArgs = doPrivilegedMethodsArgs->next;1217}1218doPrivilegedMethodsArgs->next = doPrivilegedMethodsArgsTmp;1219return J9_STACKWALK_KEEP_ITERATING;1220}12211222/**1223* PrivilegedFrameIterator method to perform stack walking for doPrivileged & doPrivilegedWithCombiner methods1224* For doPrivileged methods, this finds the callers of each doPrivileged method and the AccessControlContext discovered during stack walking,1225* either from a privilege frame or the contextObject from current thread1226* For doPrivilegedWithCombiner, this finds the caller of doPrivilegedWithCombiner method, and the AccessControlContext1227* discovered during stack walking, either from a privilege frame or the contextObject from current thread1228*1229* Notes:1230* walkState.userData11231* initial value is STACK_WALK_STATE_MAGIC((void*)1), set to NULL when a limited doPrivileged frame is discovered1232* walkState.userData21233* initial value is contextObject from current thread, set to DoPrivilegedMethodArgs* when a limited doPrivileged frame is discovered1234* walkState.userData31235* initial value is STACK_WALK_STATE_MAGIC((void*)1),1236* set to STACK_WALK_STATE_LIMITED_DOPRIVILEGED((void*)2) for searching the caller of a limited doPrivileged method,1237* and reset to STACK_WALK_STATE_MAGIC after identified the caller of that limited doPrivileged method1238* set to STACK_WALK_STATE_FULL_DOPRIVILEGED ((void*)3) for searching the caller of a full privileged doPrivileged method,1239* there is no need for resetting cause PrivilegedFrameIterator method exits with J9_STACKWALK_STOP_ITERATING1240* walkState.userData4 (only for doPrivilegedWithCombiner)1241* initial value is NULL, set to walkState->framesWalked when found the non reflection/MethodHandleInvoke frame caller of doPrivilegedWithCombiner1242*1243* @param currentThread the VM Thread1244* @param walkState the stack walk state1245*1246* @return J9_STACKWALK_STOP_ITERATING, J9_STACKWALK_KEEP_ITERATING1247*/1248static UDATA1249isPrivilegedFrameIteratorGetAccSnapshot(J9VMThread * currentThread, J9StackWalkState * walkState)1250{1251J9JavaVM *vm = currentThread->javaVM;1252PORT_ACCESS_FROM_JAVAVM(vm);1253J9JNIMethodID *doPrivilegedMethodID1 = (J9JNIMethodID *) vm->doPrivilegedMethodID1;1254J9JNIMethodID *doPrivilegedMethodID2 = (J9JNIMethodID *) vm->doPrivilegedMethodID2;1255J9JNIMethodID *doPrivilegedWithContextMethodID1 = (J9JNIMethodID *) vm->doPrivilegedWithContextMethodID1;1256J9JNIMethodID *doPrivilegedWithContextMethodID2 = (J9JNIMethodID *) vm->doPrivilegedWithContextMethodID2;1257J9JNIMethodID *doPrivilegedWithContextPermissionMethodID1 = (J9JNIMethodID *) vm->doPrivilegedWithContextPermissionMethodID1;1258J9JNIMethodID *doPrivilegedWithContextPermissionMethodID2 = (J9JNIMethodID *) vm->doPrivilegedWithContextPermissionMethodID2;1259J9Method *currentMethod = walkState->method;12601261if (J9_ARE_ALL_BITS_SET(J9_ROM_METHOD_FROM_RAM_METHOD(currentMethod)->modifiers, J9AccMethodFrameIteratorSkip)) {1262/* Skip methods with java.lang.invoke.FrameIteratorSkip / jdk.internal.vm.annotation.Hidden / java.lang.invoke.LambdaForm$Hidden annotation */1263return J9_STACKWALK_KEEP_ITERATING;1264}12651266if ((NULL == walkState->userData4)1267|| (STACK_WALK_STATE_LIMITED_DOPRIVILEGED == walkState->userData3)1268|| (STACK_WALK_STATE_FULL_DOPRIVILEGED == walkState->userData3)1269) {1270/* find the callers of each doPrivileged method */1271J9Class * currentClass = J9_CLASS_FROM_CP(walkState->constantPool);1272if ((walkState->method == vm->jlrMethodInvoke)1273#if JAVA_SPEC_VERSION >= 181274|| (walkState->method == vm->jlrMethodInvokeMH)1275#endif /* JAVA_SPEC_VERSION >= 18 */1276|| (walkState->method == vm->jliMethodHandleInvokeWithArgs)1277|| (walkState->method == vm->jliMethodHandleInvokeWithArgsList)1278|| (vm->srMethodAccessor && VM_VMHelpers::isSameOrSuperclass(J9VM_J9CLASS_FROM_JCLASS(currentThread, vm->srMethodAccessor), currentClass))1279) {1280/* skip reflection/MethodHandleInvoke frames */1281return J9_STACKWALK_KEEP_ITERATING;1282} else {1283if (NULL == walkState->userData4) {1284/* find the caller of doPrivilegedWithCombiner */1285walkState->userData4 = (void*)walkState->framesWalked;1286} else {1287if (STACK_WALK_STATE_FULL_DOPRIVILEGED == walkState->userData3) {1288/* find the caller of full doPrivileged method */1289return J9_STACKWALK_STOP_ITERATING;1290}1291/* find the caller of limited doPrivileged method */1292Assert_JCL_notNull(walkState->userData2);1293DoPrivilegedMethodArgs* doPrivilegedMethodsArgs = (DoPrivilegedMethodArgs*)walkState->userData2;1294while (NULL != doPrivilegedMethodsArgs->next) {1295doPrivilegedMethodsArgs = doPrivilegedMethodsArgs->next;1296}1297doPrivilegedMethodsArgs->frameCounter = walkState->framesWalked;1298/* reset to magic value to finish the search for the caller of current limited doPrivileged method */1299walkState->userData3 = STACK_WALK_STATE_MAGIC;1300}1301}1302}13031304if ( ((doPrivilegedMethodID1 != NULL) && (currentMethod == doPrivilegedMethodID1->method))1305|| ((doPrivilegedMethodID2 != NULL) && (currentMethod == doPrivilegedMethodID2->method))1306) {1307/* Context is NULL */1308walkState->userData3 = STACK_WALK_STATE_FULL_DOPRIVILEGED;1309if (NULL == walkState->userData1) { /* a limited doPrivileged frame was discovered */1310return frameIteratorGetAccSnapshotHelper(currentThread, walkState, NULL, NULL);1311} else {1312walkState->userData2 = NULL; /* set NULL context */1313}1314}13151316if ( ((doPrivilegedWithContextMethodID1 != NULL) && (currentMethod == doPrivilegedWithContextMethodID1->method)) ||1317((doPrivilegedWithContextMethodID2 != NULL) && (currentMethod == doPrivilegedWithContextMethodID2->method))1318) {1319/* Grab the Context from the arguments: ultra-scary: fetch arg2 from the doPrivileged() method */1320walkState->userData3 = STACK_WALK_STATE_FULL_DOPRIVILEGED;1321if (NULL == walkState->userData1) { /* a limited doPrivileged frame was discovered */1322return frameIteratorGetAccSnapshotHelper(currentThread, walkState, (j9object_t)walkState->arg0EA[-1], NULL);1323} else {1324walkState->userData2 = (void *)walkState->arg0EA[-1]; /* grab context from doPrivileged frame */1325}1326}13271328if ( ((doPrivilegedWithContextPermissionMethodID1 != NULL) && (currentMethod == doPrivilegedWithContextPermissionMethodID1->method))1329|| ((doPrivilegedWithContextPermissionMethodID2 != NULL) && (currentMethod == doPrivilegedWithContextPermissionMethodID2->method))1330) {1331walkState->userData3 = STACK_WALK_STATE_LIMITED_DOPRIVILEGED;1332if (NULL != walkState->userData1) {1333DoPrivilegedMethodArgs* doPrivilegedMethodsArgsTmp = (DoPrivilegedMethodArgs*)j9mem_allocate_memory(sizeof(DoPrivilegedMethodArgs), J9MEM_CATEGORY_VM_JCL);1334walkState->userData1 = NULL; /* set to NULL when a limited doPrivileged frame is discovered */1335if (NULL == doPrivilegedMethodsArgsTmp) {1336currentThread->javaVM->internalVMFunctions->setNativeOutOfMemoryError(currentThread, 0, 0);1337return J9_STACKWALK_STOP_ITERATING;1338}1339memset(doPrivilegedMethodsArgsTmp, 0, sizeof(DoPrivilegedMethodArgs));1340doPrivilegedMethodsArgsTmp->accControlContext = (j9object_t)walkState->arg0EA[-1];1341doPrivilegedMethodsArgsTmp->permissions = (j9object_t)walkState->arg0EA[-2];13421343walkState->userData2 = doPrivilegedMethodsArgsTmp;1344} else {1345return frameIteratorGetAccSnapshotHelper(currentThread, walkState, (j9object_t)walkState->arg0EA[-1], (j9object_t)walkState->arg0EA[-2]);1346}1347}13481349return J9_STACKWALK_KEEP_ITERATING;1350}13511352/**1353* The object array returned has following format:1354*1355* Pre-JEP140 format: AccessControlContext/ProtectionDomain..., and the length of the object array is NOT divisible by OBJS_ARRAY_SIZE1356* First element is an AccessControlContext object which might be null, either from a full permission privileged frame or from current thread if there is no such privileged frames1357* ProtectionDomain elements after AccessControlContext object could be in one of following two formats:1358* For doPrivileged methods - flag forDoPrivilegedWithCombiner is false:1359* the ProtectionDomain element might be null, first ProtectionDomain element is a duplicate of the ProtectionDomain of the caller of doPrivileged1360* rest of ProtectionDomain elements are from the callers discovered during stack walking1361* the start index of the actual ProtectionDomain element is 2 of the object array returned1362* For doPrivilegedWithCombiner methods - flag forDoPrivilegedWithCombiner is true:1363* there are only two ProtectionDomain elements, first one is the ProtectionDomain of the caller of doPrivileged1364* and the other is the ProtectionDomain of the caller of doPrivilegedWithCombiner1365* the fourth element of the object array is NULL for padding to ensure that the length of the object array is NOT divisible by OBJS_ARRAY_SIZE either1366*1367* JEP 140 format: AccessControlContext/ProtectionDomain[]/Permission[]1368* The length of the object array is always divisible by OBJS_ARRAY_SIZE.1369* Depends on number of limited permission privileged frames, the result are in following format:1370* First element is an AccessControlContext object1371* Second element could be in one of following two formats:1372* For doPrivileged methods - flag forDoPrivilegedWithCombiner is false:1373* an array of ProtectionDomain objects in which first ProtectionDomain element is a duplicate of the ProtectionDomain of the caller of doPrivileged1374* the start index of the actual ProtectionDomain element is 1 of this ProtectionDomain objects array1375* For doPrivilegedWithCombiner methods - flag forDoPrivilegedWithCombiner is true:1376* an array of ProtectionDomain objects with only two elements1377* first one is the ProtectionDomain of the caller of doPrivileged1378* and the other is the ProtectionDomain of the caller of doPrivilegedWithCombiner1379* Third element is an array of Limited Permission objects1380* Repeating this format:1381* AccessControlContext object,1382* ProtectionDomain objects array with same format above when flag forDoPrivilegedWithCombiner is false1383* or just the ProtectionDomain of the caller of doPrivileged in case of flag forDoPrivilegedWithCombiner is true1384* Permission object array1385* Until a full permission privileged frame or the end of the stack reached.1386*1387* Note: 1. The reason to have Pre-JEP140 and JEP 140 format is to keep similar format and processing logic1388* when there is no limited doPrivileged method (JEP 140 implementation) involved.1389* This helped to address performance issue raised by JAZZ 66091: Perf work for LIR 28261 (Limited doPrivileged / JEP 140)1390* 2. The reason to duplicate the ProtectionDomain object of the caller of doPrivileged is to avoid creating a new object array1391* without NULL and duplicate ProtectionDomain objects discovered during stack walking while still keeping same order of1392* those objects.1393*1394* @param env The current thread.1395* @param jsAccessController The receiver class1396* @param startingFrame The frame to start stack walking1397* @param forDoPrivilegedWithCombiner the flag to indicate if it is for doPrivilegedWithCombiner method1398*1399* @return an array of objects as per comment above1400*/1401jobject JNICALL1402Java_java_security_AccessController_getAccSnapshot(JNIEnv* env, jclass jsAccessController, jint startingFrame, jboolean forDoPrivilegedWithCombiner)1403{1404J9VMThread *vmThread = (J9VMThread *) env;1405J9JavaVM *vm = vmThread->javaVM;1406J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;1407J9StackWalkState walkState = {0};1408J9Class *arrayClass = NULL;1409UDATA i = 0;1410j9object_t contextObject = NULL;1411j9object_t arrayObject = NULL;1412jobject result = NULL;14131414/* Trc_JCL_java_security_AccessController_getAccSnapshot_Entry(vmThread, startingFrame); */1415vmFuncs->internalEnterVMFromJNI(vmThread);14161417/* Fetch the Object[] class before doing the stack walk. */1418arrayClass = fetchArrayClass(vmThread, J9VMJAVALANGOBJECT(vm));1419if (NULL != vmThread->currentException) {1420goto _walkStateUninitialized;1421}1422/* AccessControlContext is allocated in the same space as the thread, so no exception can occur */1423contextObject = vmThread->threadObject;1424if (NULL != contextObject) {1425contextObject = J9VMJAVALANGTHREAD_INHERITEDACCESSCONTROLCONTEXT(vmThread, contextObject);1426}1427/* Walk the stack, caching the constant pools of the frames. */1428walkState.skipCount = startingFrame + 1; /* skip this JNI frame as well */1429walkState.userData1 = STACK_WALK_STATE_MAGIC; /* set to NULL when a limited doPrivileged frame is discovered */1430walkState.userData2 = contextObject; /* initially set to contextObject, set to DoPrivilegedMethodArgs* when a limited doPrivileged frame is discovered */1431walkState.userData3 = STACK_WALK_STATE_MAGIC; /* set to NULL when to find the caller of a limited doPrivileged method */1432walkState.userData4 = NULL; /* when forDoPrivilegedWithCombiner is true, set to walkState->framesWalked of non reflection/MethodHandleInvoke frame caller of doPrivilegedWithCombiner */1433walkState.frameWalkFunction = isPrivilegedFrameIteratorGetAccSnapshot;1434walkState.flags = J9_STACKWALK_CACHE_CPS | J9_STACKWALK_VISIBLE_ONLY | J9_STACKWALK_INCLUDE_NATIVES | J9_STACKWALK_ITERATE_FRAMES;1435walkState.walkThread = vmThread;14361437if (vm->walkStackFrames(vmThread, &walkState) != J9_STACKWALK_RC_NONE) {1438vmFuncs->setNativeOutOfMemoryError(vmThread, 0, 0);1439goto _throwException;1440}1441if (STACK_WALK_STATE_MAGIC == walkState.userData1) {1442/* No limited doPrivileged or no doPrivileged frame discovered */1443if (forDoPrivilegedWithCombiner) {1444/* for doPrivilegedWithCombiner methods1445* first slot: contextObject1446* second slot: the caller of the ProtectionDomain of the caller of doPrivileged1447* third slot: the ProtectionDomain of the caller of doPrivilegedWithCombiner1448* fourth slot: NULL to ensure the total length of object array is not divisible by OBJS_ARRAY_SIZE1449* */1450UDATA *cachePtr = NULL;1451UDATA framesWalked = (UDATA)walkState.userData4;1452Assert_JCL_true(framesWalked > 0);1453contextObject = (j9object_t)walkState.userData2;1454PUSH_OBJECT_IN_SPECIAL_FRAME(vmThread, contextObject);1455arrayObject = vmThread->javaVM->memoryManagerFunctions->J9AllocateIndexableObject(vmThread, arrayClass, 4, J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);1456contextObject = POP_OBJECT_IN_SPECIAL_FRAME(vmThread);1457if (NULL == arrayObject) {1458vmThread->javaVM->internalVMFunctions->setHeapOutOfMemoryError(vmThread);1459goto _throwException;1460}1461J9JAVAARRAYOFOBJECT_STORE(vmThread, arrayObject, 0, contextObject);1462cachePtr = walkState.cache + (walkState.framesWalked - 1);1463J9JAVAARRAYOFOBJECT_STORE(vmThread, arrayObject, 1, J9VMJAVALANGCLASS_PROTECTIONDOMAIN(vmThread, J9VM_J9CLASS_TO_HEAPCLASS(J9_CLASS_FROM_CP(*cachePtr))));1464cachePtr = walkState.cache + (framesWalked - 1);1465J9JAVAARRAYOFOBJECT_STORE(vmThread, arrayObject, 2, J9VMJAVALANGCLASS_PROTECTIONDOMAIN(vmThread, J9VM_J9CLASS_TO_HEAPCLASS(J9_CLASS_FROM_CP(*cachePtr))));1466} else {1467/* contextObject in first slot, duplicate of the ProtectionDomain of the caller of doPrivileged in second slot (add 2 to size before allocation). */1468U_32 arraySize = (U_32)(walkState.framesWalked + 2);1469if (0 == (arraySize % OBJS_ARRAY_SIZE)) {1470arraySize++; /* increase one more slot to make sure the size of arrayObject is NOT divisible by OBJS_ARRAY_SIZE */1471}1472arrayObject = storePDobjectsHelper(vmThread, arrayClass, &walkState, (j9object_t)walkState.userData2, arraySize, walkState.framesWalked, 2, TRUE);1473if (NULL == arrayObject) {1474goto _throwException;1475}1476}1477result = vmFuncs->j9jni_createLocalRef(env, arrayObject);1478} else {1479/* at least a limited doPrivileged frame discovered */1480IDATA signedCounter = 0;1481UDATA nbrPDblockToBuild = 1; /* the number of ProtectionDomain block walked, minimum 1 when no target method walked, i.e., walked whole stack */1482UDATA counter = 0;1483DoPrivilegedMethodArgs* dpMethodsArgs = NULL; /* args found within target methods */1484DoPrivilegedMethodArgs* dpMethodsArgsTmp = NULL;14851486PORT_ACCESS_FROM_JAVAVM(vm);14871488dpMethodsArgs = (DoPrivilegedMethodArgs*)walkState.userData2;1489if (NULL == dpMethodsArgs) {1490goto _clearAllocation;1491}1492/* Array structure: AccessControlContext (could be null), ProtectionDomain object array, Permission object array (null means a normal method) */1493dpMethodsArgsTmp = dpMethodsArgs;1494if (NULL != dpMethodsArgsTmp->next) {1495/* look for top doPrivileged frame */1496do {1497nbrPDblockToBuild++;1498dpMethodsArgsTmp = dpMethodsArgsTmp->next;1499} while (NULL != dpMethodsArgsTmp->next);1500} else {1501/* only one frame */1502}1503if (NULL != dpMethodsArgsTmp->permissions) {1504/* top frame is a limited doPrivilege frame */1505DoPrivilegedMethodArgs* doPrivilegedMethodsArgsTmp2 = (DoPrivilegedMethodArgs*)j9mem_allocate_memory(sizeof(DoPrivilegedMethodArgs), J9MEM_CATEGORY_VM_JCL);1506if (NULL == doPrivilegedMethodsArgsTmp2) {1507vmFuncs->setNativeOutOfMemoryError(vmThread, 0, 0);1508goto _clearAllocation;1509}1510memset(doPrivilegedMethodsArgsTmp2, 0, sizeof(DoPrivilegedMethodArgs));1511doPrivilegedMethodsArgsTmp2->accControlContext = contextObject;1512doPrivilegedMethodsArgsTmp2->frameCounter = walkState.framesWalked;1513dpMethodsArgsTmp->next = doPrivilegedMethodsArgsTmp2;15141515nbrPDblockToBuild++;1516} else {1517dpMethodsArgsTmp->frameCounter = walkState.framesWalked;1518}15191520dpMethodsArgsTmp = dpMethodsArgs;1521counter = 0;1522do {1523PUSH_OBJECT_IN_SPECIAL_FRAME(vmThread, (j9object_t)dpMethodsArgsTmp->accControlContext);1524PUSH_OBJECT_IN_SPECIAL_FRAME(vmThread, (j9object_t)dpMethodsArgsTmp->permissions);1525dpMethodsArgsTmp = dpMethodsArgsTmp->next;1526counter++;1527} while (NULL != dpMethodsArgsTmp);1528arrayObject = vm->memoryManagerFunctions->J9AllocateIndexableObject(vmThread, arrayClass, (U_32)nbrPDblockToBuild*OBJS_ARRAY_SIZE, J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);1529if (NULL == arrayObject) {1530for (signedCounter = (counter - 1); signedCounter >= 0; signedCounter--) {1531DROP_OBJECT_IN_SPECIAL_FRAME(vmThread);1532DROP_OBJECT_IN_SPECIAL_FRAME(vmThread);1533}1534vmFuncs->setHeapOutOfMemoryError(vmThread);1535goto _clearAllocation;1536}1537for (signedCounter = (counter - 1); signedCounter >= 0; signedCounter--) {1538j9object_t permissions = POP_OBJECT_IN_SPECIAL_FRAME(vmThread);1539j9object_t accControlContext = POP_OBJECT_IN_SPECIAL_FRAME(vmThread);1540/* store accControlContext at index OBJS_ARRAY_IDX_ACC(0) */1541J9JAVAARRAYOFOBJECT_STORE(vmThread, arrayObject, signedCounter*OBJS_ARRAY_SIZE, accControlContext);1542/* store permissions at index OBJS_ARRAY_IDX_PERMS_OR_CACHECHECKED(2) */1543J9JAVAARRAYOFOBJECT_STORE(vmThread, arrayObject, (signedCounter*OBJS_ARRAY_SIZE + OBJS_ARRAY_IDX_PERMS_OR_CACHECHECKED), permissions);1544}15451546if (forDoPrivilegedWithCombiner) {1547/* for doPrivilegedWithCombiner methods1548* first arrayObject[signedCounter*OBJS_ARRAY_SIZE + OBJS_ARRAY_IDX_PDS] is an object array with length 21549* in which first element is the ProtectionDomain of the caller of doPrivileged1550* second slot: the ProtectionDomain of the caller of doPrivilegedWithCombiner1551* rest of arrayObject[signedCounter*OBJS_ARRAY_SIZE + OBJS_ARRAY_IDX_PDS] are a single ProtectionDomain object of the callers of each limited/full doPrivileged methods1552* */1553signedCounter = 0;1554dpMethodsArgsTmp = dpMethodsArgs;1555do {1556UDATA *cachePtr = NULL;1557if (0 == signedCounter) {1558/* this is first frame */1559UDATA framesWalked = (UDATA)walkState.userData4;1560j9object_t pdArrayTmp = NULL;1561Assert_JCL_true(framesWalked > 0);15621563PUSH_OBJECT_IN_SPECIAL_FRAME(vmThread, (j9object_t)arrayObject);1564pdArrayTmp = vm->memoryManagerFunctions->J9AllocateIndexableObject(vmThread, arrayClass, 2, J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);1565arrayObject = POP_OBJECT_IN_SPECIAL_FRAME(vmThread);1566if (NULL == pdArrayTmp) {1567vmFuncs->setHeapOutOfMemoryError(vmThread);1568goto _clearAllocation;1569}1570cachePtr = walkState.cache + (dpMethodsArgsTmp->frameCounter - 1);1571J9JAVAARRAYOFOBJECT_STORE(vmThread, pdArrayTmp, 0, J9VMJAVALANGCLASS_PROTECTIONDOMAIN(vmThread, J9VM_J9CLASS_TO_HEAPCLASS(J9_CLASS_FROM_CP(*cachePtr))));1572cachePtr = walkState.cache + (framesWalked - 1);1573J9JAVAARRAYOFOBJECT_STORE(vmThread, pdArrayTmp, 1, J9VMJAVALANGCLASS_PROTECTIONDOMAIN(vmThread, J9VM_J9CLASS_TO_HEAPCLASS(J9_CLASS_FROM_CP(*cachePtr))));1574J9JAVAARRAYOFOBJECT_STORE(vmThread, arrayObject, (signedCounter*OBJS_ARRAY_SIZE + OBJS_ARRAY_IDX_PDS), pdArrayTmp);1575} else {1576cachePtr = walkState.cache + (dpMethodsArgsTmp->frameCounter - 1);1577J9JAVAARRAYOFOBJECT_STORE(vmThread, arrayObject, (signedCounter*OBJS_ARRAY_SIZE + OBJS_ARRAY_IDX_PDS), J9VMJAVALANGCLASS_PROTECTIONDOMAIN(vmThread, J9VM_J9CLASS_TO_HEAPCLASS(J9_CLASS_FROM_CP(*cachePtr))));1578}1579signedCounter++;1580dpMethodsArgsTmp = dpMethodsArgsTmp->next;1581} while (NULL != dpMethodsArgsTmp);1582} else {1583UDATA *cachePtr = walkState.cache;1584j9object_t lastPD = NULL;1585j9object_t pdArrayTmp = NULL;1586UDATA lastFrameCounter = 0;1587signedCounter = 0;1588i = 0;15891590dpMethodsArgsTmp = dpMethodsArgs;1591do {1592j9object_t pd = NULL;1593I_32 resultIndex = 1;15941595/* The layout of ProtectionDomain object array is changed to following format:1596* first element: the ProtectionDomain of the caller of doPrivileged1597* rest elements: the ProtectionDomains of the callers discovered during stack walking including the caller of doPrivileged1598* The reason to duplicate the ProtectionDomain of the caller of doPrivileged is to keep current structure and performance1599* */1600PUSH_OBJECT_IN_SPECIAL_FRAME(vmThread, (j9object_t)arrayObject);1601pdArrayTmp = vm->memoryManagerFunctions->J9AllocateIndexableObject(vmThread, arrayClass, (U_32)(dpMethodsArgsTmp->frameCounter - lastFrameCounter + 1), J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);1602arrayObject = POP_OBJECT_IN_SPECIAL_FRAME(vmThread);1603if (NULL == pdArrayTmp) {1604vmFuncs->setHeapOutOfMemoryError(vmThread);1605goto _clearAllocation;1606}1607lastFrameCounter = dpMethodsArgsTmp->frameCounter;1608do {1609pd = J9VMJAVALANGCLASS_PROTECTIONDOMAIN(vmThread, J9VM_J9CLASS_TO_HEAPCLASS(J9_CLASS_FROM_CP(*cachePtr)));1610cachePtr += 1;1611if ((NULL != pd) && (pd != lastPD)) {1612BOOLEAN duplicate = FALSE;1613IDATA sc = 0;16141615while (sc < signedCounter) {1616/* Scanning over object array already in previous limited doPrivileged frames */1617UDATA j = 0;1618j9object_t pdTmp = J9JAVAARRAYOFOBJECT_LOAD(vmThread, arrayObject, (sc*OBJS_ARRAY_SIZE + OBJS_ARRAY_IDX_PDS));1619for (j = 1; j < J9INDEXABLEOBJECT_SIZE(vmThread, pdTmp); j++) {1620if (pd == J9JAVAARRAYOFOBJECT_LOAD(vmThread, pdTmp, j)) {1621duplicate = TRUE;1622break;1623}1624}1625if (TRUE == duplicate) {1626break;1627}1628sc++;1629}1630if (!duplicate) {1631I_32 scanIndex = 1;1632while (scanIndex < resultIndex) {1633/* Scanning over objects just saved in this doPrivileged frame */1634if (pd == J9JAVAARRAYOFOBJECT_LOAD(vmThread, pdArrayTmp, scanIndex)) {1635duplicate = TRUE;1636break;1637}1638scanIndex++;1639}1640if (!duplicate) {1641J9JAVAARRAYOFOBJECT_STORE(vmThread, pdArrayTmp, resultIndex, pd);1642resultIndex++;1643}1644}1645lastPD = pd;1646}1647i++;1648} while (i < dpMethodsArgsTmp->frameCounter);1649/* save the PD of the caller of doPrivileged at first element */1650if (NULL != pd) {1651J9JAVAARRAYOFOBJECT_STORE(vmThread, pdArrayTmp, 0, pd);1652}1653J9JAVAARRAYOFOBJECT_STORE(vmThread, arrayObject, (signedCounter*OBJS_ARRAY_SIZE + OBJS_ARRAY_IDX_PDS), pdArrayTmp);1654signedCounter++;1655dpMethodsArgsTmp = dpMethodsArgsTmp->next;1656} while (i < walkState.framesWalked);1657}1658result = vmFuncs->j9jni_createLocalRef(env, arrayObject);16591660_clearAllocation:1661if (NULL != dpMethodsArgs) {1662do {1663dpMethodsArgsTmp = dpMethodsArgs->next;1664j9mem_free_memory(dpMethodsArgs);1665dpMethodsArgs = dpMethodsArgsTmp;1666} while (NULL != dpMethodsArgsTmp);1667}1668}16691670_throwException:1671vmFuncs->freeStackWalkCaches(vmThread, &walkState);1672_walkStateUninitialized:1673vmFuncs->internalExitVMToJNI(vmThread);1674/* Trc_JCL_java_security_AccessController_getAccSnapshot_Exit(vmThread, result); */1675return result;1676}16771678/**1679* PrivilegedFrameIterator method to perform stack walking and find the caller specified by startingFrame1680*1681* @param currentThread the VM Thread1682* @param walkState the stack walk state1683*1684* @return J9_STACKWALK_STOP_ITERATING, J9_STACKWALK_KEEP_ITERATING1685*/1686static UDATA1687isPrivilegedFrameIteratorGetCallerPD(J9VMThread * currentThread, J9StackWalkState * walkState)1688{1689if (J9_ARE_ALL_BITS_SET(J9_ROM_METHOD_FROM_RAM_METHOD(walkState->method)->modifiers, J9AccMethodFrameIteratorSkip)) {1690/* Skip methods with java.lang.invoke.FrameIteratorSkip / jdk.internal.vm.annotation.Hidden / java.lang.invoke.LambdaForm$Hidden annotation */1691return J9_STACKWALK_KEEP_ITERATING;1692}16931694J9JavaVM *vm = currentThread->javaVM;1695J9Class * currentClass = J9_CLASS_FROM_CP(walkState->constantPool);1696if ((walkState->method == vm->jlrMethodInvoke)1697#if JAVA_SPEC_VERSION >= 181698|| (walkState->method == vm->jlrMethodInvokeMH)1699#endif /* JAVA_SPEC_VERSION >= 18 */1700|| (walkState->method == vm->jliMethodHandleInvokeWithArgs)1701|| (walkState->method == vm->jliMethodHandleInvokeWithArgsList)1702|| (vm->srMethodAccessor && VM_VMHelpers::isSameOrSuperclass(J9VM_J9CLASS_FROM_JCLASS(currentThread, vm->srMethodAccessor), currentClass))1703/* there is no need to check srConstructorAccessor because doPrivilegedXX are method calls and not affected by Constructor reflection */1704) {1705/* skip reflection/MethodHandleInvoke frames */1706return J9_STACKWALK_KEEP_ITERATING;1707} else {1708/* find the caller */1709return J9_STACKWALK_STOP_ITERATING;1710}1711}17121713/**1714* This native retrieves the ProtectionDomain object of the non-reflection/MethodHandleInvoke caller as per the startingFrame specified.17151716* @param env The current thread.1717* @param jsAccessController The receiver class1718* @param startingFrame The frame to start stack walking1719*1720* @return a ProtectionDomain object as per description above1721*/1722jobject JNICALL1723Java_java_security_AccessController_getCallerPD(JNIEnv* env, jclass jsAccessController, jint startingFrame)1724{1725J9VMThread *vmThread = (J9VMThread *) env;1726J9JavaVM *vm = vmThread->javaVM;1727J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;1728J9StackWalkState walkState = {0};1729j9object_t pd = NULL;1730jobject result = NULL;1731UDATA *cachePtr = NULL;17321733vmFuncs->internalEnterVMFromJNI(vmThread);17341735walkState.skipCount = startingFrame + 1; /* skip this JNI frame as well */1736walkState.frameWalkFunction = isPrivilegedFrameIteratorGetCallerPD;1737walkState.flags = J9_STACKWALK_CACHE_CPS | J9_STACKWALK_VISIBLE_ONLY | J9_STACKWALK_INCLUDE_NATIVES | J9_STACKWALK_ITERATE_FRAMES;1738walkState.walkThread = vmThread;1739if (vm->walkStackFrames(vmThread, &walkState) != J9_STACKWALK_RC_NONE) {1740vmFuncs->setNativeOutOfMemoryError(vmThread, 0, 0);1741goto _throwException;1742}1743Assert_JCL_true(walkState.framesWalked > 0);1744cachePtr = walkState.cache + (walkState.framesWalked - 1);1745pd = J9VMJAVALANGCLASS_PROTECTIONDOMAIN(vmThread, J9VM_J9CLASS_TO_HEAPCLASS(J9_CLASS_FROM_CP(*cachePtr)));1746if (NULL != pd) {1747result = vmFuncs->j9jni_createLocalRef(env, pd);1748}17491750_throwException:1751vmFuncs->freeStackWalkCaches(vmThread, &walkState);1752vmFuncs->internalExitVMToJNI(vmThread);17531754return result;1755}17561757/**1758* Helper method to store PD object discovered during stack walking1759*1760* @param vmThread[in] the current J9VMThread1761* @param arrayClass[in] the Object[] class1762* @param walkState[in] the stack walk state1763* @param contextObject[in] the AccessControlContext object1764* @param arraySize[in] the size of array object to be allocated1765* @param framesWalked[in] the frames walked1766* @param startPos[in] the start index of the actual ProtectionDomain object excluding acc & dup1767* @param dupCallerPD[in] the flag to indicate if the caller ProtectionDomain object is to be duplicated at index 11768*1769* @returns an object array with AccessControlContext object at index 0 followed by ProtectionDomain objects1770*/1771static j9object_t1772storePDobjectsHelper(J9VMThread* vmThread, J9Class* arrayClass, J9StackWalkState* walkState, j9object_t contextObject, U_32 arraySize, UDATA framesWalked, I_32 startPos, BOOLEAN dupCallerPD)1773{1774j9object_t arrayObject = NULL;17751776PUSH_OBJECT_IN_SPECIAL_FRAME(vmThread, contextObject);1777arrayObject = vmThread->javaVM->memoryManagerFunctions->J9AllocateIndexableObject(vmThread, arrayClass, arraySize, J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);1778contextObject = POP_OBJECT_IN_SPECIAL_FRAME(vmThread);1779if (NULL == arrayObject) {1780vmThread->javaVM->internalVMFunctions->setHeapOutOfMemoryError(vmThread);1781return NULL;1782}1783J9JAVAARRAYOFOBJECT_STORE(vmThread, arrayObject, 0, contextObject);1784/* Fill in the array. */1785if (0 < framesWalked) {1786UDATA i = 0;1787j9object_t lastPD = NULL;1788I_32 resultIndex = startPos;1789UDATA *cachePtr = walkState->cache;1790j9object_t pd = NULL;1791for (i = framesWalked; i > 0; i--) {1792pd = J9VMJAVALANGCLASS_PROTECTIONDOMAIN(vmThread, J9VM_J9CLASS_TO_HEAPCLASS(J9_CLASS_FROM_CP(*cachePtr)));1793cachePtr += 1;1794if ((NULL != pd) && (pd != lastPD)) {1795I_32 scanIndex = startPos;1796BOOLEAN duplicate = FALSE;1797while (scanIndex < resultIndex) {1798/* Scanning over objects that were already read in this function, so no exception can occur */1799if (pd == J9JAVAARRAYOFOBJECT_LOAD(vmThread, arrayObject, scanIndex)) {1800duplicate = TRUE;1801break;1802}1803scanIndex++;1804}1805if (!duplicate) {1806J9JAVAARRAYOFOBJECT_STORE(vmThread, arrayObject, resultIndex, pd);1807resultIndex++;1808}1809lastPD = pd;1810}1811}1812if (dupCallerPD && NULL != pd) {1813J9JAVAARRAYOFOBJECT_STORE(vmThread, arrayObject, 1, pd);1814}1815}1816return arrayObject;1817}181818191820jobject JNICALL1821Java_java_lang_Class_getNestHostImpl(JNIEnv *env, jobject recv)1822{1823#if JAVA_SPEC_VERSION >= 111824J9VMThread *currentThread = (J9VMThread*)env;1825J9InternalVMFunctions *vmFuncs = currentThread->javaVM->internalVMFunctions;1826vmFuncs->internalEnterVMFromJNI(currentThread);18271828J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(recv));1829J9Class *nestHost = clazz->nestHost;18301831if (NULL == nestHost) {1832if (J9_VISIBILITY_ALLOWED == vmFuncs->loadAndVerifyNestHost(currentThread, clazz, J9_LOOK_NO_THROW)) {1833nestHost = clazz->nestHost;1834} else {1835/* If there is a failure loading or accessing the nest host, or if this class or interface does1836* not specify a nest, then it is considered to belong to its own nest and this is returned as1837* the host */1838nestHost = clazz;1839}1840}1841j9object_t resultObject = J9VM_J9CLASS_TO_HEAPCLASS(nestHost);1842jobject result = vmFuncs->j9jni_createLocalRef(env, resultObject);18431844if (NULL == result) {1845vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);1846}18471848vmFuncs->internalExitVMToJNI(currentThread);1849return result;1850#else /* JAVA_SPEC_VERSION >= 11 */1851Assert_JCL_unimplemented();1852return NULL;1853#endif /* JAVA_SPEC_VERSION >= 11 */1854}18551856jobject JNICALL1857Java_java_lang_Class_getNestMembersImpl(JNIEnv *env, jobject recv)1858{1859#if JAVA_SPEC_VERSION >= 111860J9VMThread *currentThread = (J9VMThread*)env;1861J9JavaVM *vm = currentThread->javaVM;1862J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;1863J9MemoryManagerFunctions *mmFuncs = vm->memoryManagerFunctions;18641865j9object_t resultObject = NULL;1866jobject result = NULL;1867J9ROMClass *romHostClass = NULL;1868U_16 nestMemberCount = 0;1869J9Class *jlClass = NULL;1870J9Class *arrayClass = NULL;18711872vmFuncs->internalEnterVMFromJNI(currentThread);18731874J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(recv));1875J9Class *nestHost = clazz->nestHost;18761877if (NULL == nestHost) {1878if (J9_VISIBILITY_ALLOWED != vmFuncs->loadAndVerifyNestHost(currentThread, clazz, 0)) {1879goto _done;1880}1881nestHost = clazz->nestHost;1882}1883romHostClass = nestHost->romClass;1884nestMemberCount = romHostClass->nestMemberCount;18851886/* Grab java.lang.Class class for result object size */1887jlClass = J9VMJAVALANGCLASS_OR_NULL(vm);1888Assert_JCL_notNull(jlClass);1889arrayClass = fetchArrayClass(currentThread, jlClass);1890if (NULL != currentThread->currentException) {1891goto _done;1892}18931894resultObject = mmFuncs->J9AllocateIndexableObject(currentThread, arrayClass, 1 + nestMemberCount, J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE);1895if (NULL == resultObject) {1896vmFuncs->setHeapOutOfMemoryError(currentThread);1897goto _done;1898}18991900/* Host class is always in zeroeth index */1901J9JAVAARRAYOFOBJECT_STORE(currentThread, resultObject, 0, J9VM_J9CLASS_TO_HEAPCLASS(nestHost));19021903/* If host class claims nest members, they should be placed in second index onwards */1904if (0 != nestMemberCount) {1905J9SRP *nestMembers = J9ROMCLASS_NESTMEMBERS(romHostClass);1906U_16 i = 0;1907/* Classes in nest are in same runtime package & therefore have same classloader */1908J9ClassLoader *classLoader = clazz->classLoader;19091910for (i = 0; i < nestMemberCount; i++) {1911J9UTF8 *nestMemberName = NNSRP_GET(nestMembers[i], J9UTF8 *);19121913PUSH_OBJECT_IN_SPECIAL_FRAME(currentThread, resultObject);1914J9Class *nestMember = vmFuncs->internalFindClassUTF8(currentThread, J9UTF8_DATA(nestMemberName), J9UTF8_LENGTH(nestMemberName), classLoader, J9_FINDCLASS_FLAG_THROW_ON_FAIL);1915resultObject = POP_OBJECT_IN_SPECIAL_FRAME(currentThread);19161917if (NULL == nestMember) {1918/* If internalFindClassUTF8 fails to find the nest member, it sets1919* a NoClassDefFoundError1920*/1921goto _done;1922} else if (NULL == nestMember->nestHost) {1923if (J9_VISIBILITY_ALLOWED != vmFuncs->loadAndVerifyNestHost(currentThread, nestMember, 0)) {1924goto _done;1925}1926}1927if (nestMember->nestHost != nestHost) {1928vmFuncs->setNestmatesError(currentThread, nestMember, nestHost, J9_VISIBILITY_NEST_MEMBER_NOT_CLAIMED_ERROR);1929goto _done;1930}1931J9JAVAARRAYOFOBJECT_STORE(currentThread, resultObject, i + 1, J9VM_J9CLASS_TO_HEAPCLASS(nestMember));1932}1933}19341935result = vmFuncs->j9jni_createLocalRef(env, resultObject);19361937_done:1938vmFuncs->internalExitVMToJNI(currentThread);1939return result;1940#else /* JAVA_SPEC_VERSION >= 11 */1941Assert_JCL_unimplemented();1942return NULL;1943#endif /* JAVA_SPEC_VERSION >= 11 */1944}19451946jboolean JNICALL1947Java_java_lang_Class_isHiddenImpl(JNIEnv *env, jobject recv)1948{1949#if JAVA_SPEC_VERSION >= 151950jboolean result = JNI_FALSE;1951J9VMThread *currentThread = (J9VMThread*)env;1952J9InternalVMFunctions *vmFuncs = currentThread->javaVM->internalVMFunctions;1953vmFuncs->internalEnterVMFromJNI(currentThread);1954J9Class *clazz = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, J9_JNI_UNWRAP_REFERENCE(recv));1955result = J9ROMCLASS_IS_HIDDEN(clazz->romClass);1956vmFuncs->internalExitVMToJNI(currentThread);1957return result;1958#else /* JAVA_SPEC_VERSION >= 15 */1959Assert_JCL_unimplemented();1960return JNI_FALSE;1961#endif /* JAVA_SPEC_VERSION >= 15 */1962}19631964} /* extern "C" */196519661967