Path: blob/master/runtime/jcl/common/java_dyn_methodhandle.c
6000 views
/*******************************************************************************1* Copyright (c) 2001, 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 <string.h>23#include <stdlib.h>2425#include "j9.h"26#include "jcl.h"27#include "j9consts.h"28#include "jni.h"29#include "j9protos.h"30#include "jcl_internal.h"31#include "jclprots.h"32#include "ut_j9jcl.h"33#include "VM_MethodHandleKinds.h"3435#include "rommeth.h"36#include "j9vmnls.h"37#include "j9vmconstantpool.h"38#include "j9jclnls.h"39#include "cfreader.h"4041/*42* Note that the following native methods are implemented in sun_reflect_ConstantPool.c because43* they effectively extend the ConstantPool API and require functionality from that module:44* Java_java_lang_invoke_MethodHandleResolver_getCPTypeAt45* Java_java_lang_invoke_MethodHandleResolver_getCPMethodTypeAt46* Java_java_lang_invoke_MethodHandleResolver_getCPMethodHandleAt47* Java_java_lang_invoke_MethodHandleResolver_getCPConstantDynamicAt48*/4950static VMINLINE UDATA lookupImpl(J9VMThread *currentThread, J9Class *lookupClass, J9UTF8 *name, J9UTF8 *signature, J9Class *senderClass, UDATA options, BOOLEAN *foundDefaultConflicts);51static void registerVMNativesIfNoJIT(JNIEnv *env, jclass nativeClass, JNINativeMethod *natives, jint numNatives);52static jlong JNICALL vmInitialInvokeExactThunk(JNIEnv *env, jclass ignored);53static jlong JNICALL vmConvertITableIndexToVTableIndex(JNIEnv *env, jclass InterfaceMethodHandle, jlong interfaceArg, jint itableIndex, jlong receiverClassArg);54static void JNICALL vmFinalizeImpl(JNIEnv *env, jclass methodHandleClass, jlong thunkAddress);55static void JNICALL vmInvalidate(JNIEnv *env, jclass mutableCallSiteClass, jlongArray cookies);56static BOOLEAN accessCheckMethodSignature(J9VMThread *currentThread, J9Method *method, j9object_t methodType, J9UTF8 *lookupSig);57static BOOLEAN accessCheckFieldSignature(J9VMThread *currentThread, J9Class* lookupClass, UDATA romField, j9object_t methodType, J9UTF8 *lookupSig);58static char * expandNLSTemplate(J9VMThread *vmThread, const char *nlsTemplate, ...);5960/**61* Lookup static method name of type signature on lookupClass class.62*63* @param currentThread The thread used in the lookup.64* @param lookupClass The class to do the lookup on65* @param name The method name to lookup. Assumed to be verified.66* @param signature A valid method signature (JVM spec 4.4.3).67*68* @return a J9Method pointer or NULL on error.69*/70static UDATA71lookupStaticMethod(J9VMThread *currentThread, J9Class *lookupClass, J9UTF8 *name, J9UTF8 *signature)72{73return lookupImpl(currentThread, lookupClass, name, signature, NULL, J9_LOOK_STATIC, NULL);74}7576static UDATA77lookupInterfaceMethod(J9VMThread *currentThread, J9Class *lookupClass, J9UTF8 *name, J9UTF8 *signature, UDATA *methodIndex)78{79J9Method *method;8081if (methodIndex == NULL) {82return (UDATA) NULL;83}84*methodIndex = -1;8586/* Lookup the Interface method find its itable slot */87method = (J9Method *) lookupImpl(currentThread, lookupClass, name, signature, NULL, J9_LOOK_INTERFACE, NULL);88if (method != NULL) {89J9InternalVMFunctions *vmFuncs = currentThread->javaVM->internalVMFunctions;9091Assert_JCL_true(!J9_ARE_ANY_BITS_SET(J9_ROM_METHOD_FROM_RAM_METHOD(method)->modifiers, J9AccStatic));9293/* Starting Java 11 Nestmates, invokeInterface is allowed to target private interface methods */94if ((J2SE_VERSION(currentThread->javaVM) < J2SE_V11) && J9_ARE_ANY_BITS_SET(J9_ROM_METHOD_FROM_RAM_METHOD(method)->modifiers, J9AccPrivate)) {95/* [PR 67082] private interface methods require invokespecial, not invokeinterface.*/96vmFuncs->setCurrentExceptionNLS(currentThread, J9VMCONSTANTPOOL_JAVALANGINCOMPATIBLECLASSCHANGEERROR, J9NLS_JCL_PRIVATE_INTERFACE_REQUIRES_INVOKESPECIAL);97method = NULL;98} else {99if (J9_ARE_ANY_BITS_SET(J9_CLASS_FROM_METHOD(method)->romClass->modifiers, J9AccInterface)) {100if (J9ROMMETHOD_IN_ITABLE(J9_ROM_METHOD_FROM_RAM_METHOD(method))) {101*methodIndex = getITableIndexForMethod(method, lookupClass);102} else {103PORT_ACCESS_FROM_VMC(currentThread);104J9Class *clazz = J9_CLASS_FROM_METHOD(method);105J9UTF8 *className = J9ROMCLASS_CLASSNAME(clazz->romClass);106J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);107J9UTF8 *methodName = J9ROMMETHOD_NAME(romMethod);108J9UTF8 *sig = J9ROMMETHOD_SIGNATURE(romMethod);109size_t nameAndSigLength = J9UTF8_LENGTH(className)110+ J9UTF8_LENGTH(methodName) + J9UTF8_LENGTH(sig)111+ 4 /* period, parentheses, and terminating null */;112char *msg = j9mem_allocate_memory(nameAndSigLength, OMRMEM_CATEGORY_VM);113if (NULL != msg) {114j9str_printf(PORTLIB, msg, nameAndSigLength, "%.*s.%.*s(%.*s)",115J9UTF8_LENGTH(className), J9UTF8_DATA(className),116J9UTF8_LENGTH(methodName), J9UTF8_DATA(methodName),117J9UTF8_LENGTH(sig), J9UTF8_DATA(sig));118vmFuncs->setCurrentExceptionUTF(currentThread,119J9VMCONSTANTPOOL_JAVALANGNOSUCHMETHODERROR, msg);120j9mem_free_memory(msg);121} else {122vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);123}124method = NULL;125}126}127}128}129130return (UDATA) method;131}132133/*134* See resolvesupport.c: resolveSpecialMethodRefInto135*/136static UDATA137lookupSpecialMethod(J9VMThread *currentThread, J9Class *lookupClass, J9UTF8 *name, J9UTF8 *signature, J9Class *specialCaller, BOOLEAN isForVirtualLookup)138{139J9Method *method = NULL;140BOOLEAN foundDefaultConflicts = FALSE;141142/* REASON FOR THE J9_LOOK_HANDLE_DEFAULT_METHOD_CONFLICTS:143* Virtual invocation modes may still find a method in the receiver's vtable that resolves the default method conflict.144* If not, the method in the vtable will be a special method for throwing the exception.145*146* Special invocations (defender supersends) will not look at the receiver's vtable, but instead invoke the result of javaLookupMethod.147* Default method conflicts must therefore be handled by the lookup code.148*/149UDATA lookupOptions = J9_LOOK_VIRTUAL | J9_LOOK_HANDLE_DEFAULT_METHOD_CONFLICTS;150151method = (J9Method*)lookupImpl(currentThread, lookupClass, name, signature, specialCaller, lookupOptions, &foundDefaultConflicts);152153if (foundDefaultConflicts) {154J9InternalVMFunctions *vmFuncs = currentThread->javaVM->internalVMFunctions;155/* Don't need to clear the current exception here - it will be cleared when setting the exception. */156vmFuncs->setCurrentExceptionWithCause(currentThread, J9VMCONSTANTPOOL_JAVALANGINVOKEDEFAULTMETHODCONFLICTEXCEPTION, NULL, currentThread->currentException);157} else if (NULL != method) {158J9Class *resolvedClass = J9_CLASS_FROM_METHOD(method);159if (isForVirtualLookup || isDirectSuperInterface(currentThread, resolvedClass, specialCaller)) {160/* CMVC 197763 seq#4: Use the method's class, not the lookupClass, as the resolvedClass arg. LookupClass may be unrelated */161method = getMethodForSpecialSend(currentThread, specialCaller, resolvedClass, method, J9_LOOK_VIRTUAL | J9_LOOK_NO_VISIBILITY_CHECK | J9_LOOK_IGNORE_INCOMPATIBLE_METHODS);162Assert_JCL_notNull(method);163} else {164setIncompatibleClassChangeErrorInvalidDefenderSupersend(currentThread, resolvedClass, specialCaller);165method = NULL;166}167}168169return (UDATA)method;170}171172173/**174* Wrapper around javalookupMethod - packs the name and signature into a J9ROMNameAndSignature struct and calls175* javaLookupMethod.176*177* Returns a J9Method* or NULL.178*/179static UDATA180lookupImpl(J9VMThread *currentThread, J9Class *lookupClass, J9UTF8 *name, J9UTF8 *signature, J9Class *senderClass, UDATA options, BOOLEAN *foundDefaultConflicts)181{182J9Method *method;183J9NameAndSignature nameAndSig;184J9JavaVM * vm = currentThread->javaVM;185186Assert_JCL_notNull(lookupClass);187Assert_JCL_notNull(name);188Assert_JCL_notNull(signature);189190nameAndSig.name = name;191nameAndSig.signature = signature;192method = (J9Method *) vm->internalVMFunctions->javaLookupMethodImpl(currentThread, lookupClass, (J9ROMNameAndSignature *)&nameAndSig, senderClass, options /* | J9_LOOK_NO_THROW | J9_LOOK_CLCONSTRAINTS */ | J9_LOOK_DIRECT_NAS, foundDefaultConflicts);193194return (UDATA) method;195}196197void JNICALL198Java_java_lang_invoke_MethodHandle_requestCustomThunkFromJit(JNIEnv* env, jobject handle, jobject thunk)199{200J9VMThread *vmThread = ((J9VMThread *) env);201J9JavaVM *vm = vmThread->javaVM;202J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;203204vmFuncs->internalEnterVMFromJNI(vmThread);205vm->jitConfig->translateMethodHandle(206vmThread,207J9_JNI_UNWRAP_REFERENCE(handle),208J9_JNI_UNWRAP_REFERENCE(thunk),209J9_METHOD_HANDLE_COMPILE_CUSTOM);210vmFuncs->internalExitVMToJNI(vmThread);211}212213jclass JNICALL214Java_java_lang_invoke_PrimitiveHandle_lookupMethod(JNIEnv *env, jobject handle, jclass lookupClass, jstring name, jstring signature, jbyte kind, jclass specialCaller)215{216J9VMThread *vmThread = ((J9VMThread *) env);217J9JavaVM *vm = vmThread->javaVM;218J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;219J9UTF8 *nameUTF8 = NULL;220char nameUTF8Buffer[256];221J9UTF8 *signatureUTF8 = NULL;222char signatureUTF8Buffer[256];223UDATA method;224J9Class *j9LookupClass;225J9Class *j9SpecialCaller = NULL;226UDATA vmSlotValue = (UDATA)-1; /* Set to invalid value so easy to find.*/227jclass result = NULL;228BOOLEAN isForVirtualLookup = FALSE;229PORT_ACCESS_FROM_ENV(env);230231vmFuncs->internalEnterVMFromJNI(vmThread);232233nameUTF8 = vmFuncs->copyStringToJ9UTF8WithMemAlloc(vmThread, J9_JNI_UNWRAP_REFERENCE(name), J9_STR_NONE, "", 0, nameUTF8Buffer, sizeof(nameUTF8Buffer));234235if (nameUTF8 == NULL) {236vmFuncs->setNativeOutOfMemoryError(vmThread, 0, 0);237goto _cleanup;238}239240signatureUTF8 = vmFuncs->copyStringToJ9UTF8WithMemAlloc(vmThread, J9_JNI_UNWRAP_REFERENCE(signature), J9_STR_NONE, "", 0, signatureUTF8Buffer, sizeof(signatureUTF8Buffer));241242if (signatureUTF8 == NULL) {243vmFuncs->setNativeOutOfMemoryError(vmThread, 0, 0);244goto _cleanup;245}246247j9LookupClass = J9VM_J9CLASS_FROM_JCLASS(vmThread, lookupClass);248Assert_JCL_notNull(j9LookupClass);249250switch(kind){251case J9_METHOD_HANDLE_KIND_STATIC:252method = lookupStaticMethod(vmThread, j9LookupClass, nameUTF8, signatureUTF8);253vmSlotValue = method;254255if (NULL != (J9Method*)method) {256J9Class *methodClass = J9_CLASS_FROM_METHOD((J9Method *)method);257258if (methodClass != j9LookupClass) {259if (J9AccInterface == (j9LookupClass->romClass->modifiers & J9AccInterface)) {260/* Throws NoSuchMethodError (an IncompatibleClassChangeError subclass).261* This will be converted to NoSuchMethodException262* by the finishMethodInitialization() call in DirectHandle constructor.263*/264vmFuncs->setCurrentException(vmThread, J9VMCONSTANTPOOL_JAVALANGNOSUCHMETHODERROR, NULL);265goto _cleanup;266}267}268}269270break;271case J9_METHOD_HANDLE_KIND_INTERFACE:272method = lookupInterfaceMethod(vmThread, j9LookupClass, nameUTF8, signatureUTF8, &vmSlotValue);273break;274case J9_METHOD_HANDLE_KIND_VIRTUAL:275/* Instead of looking up the VirtualHandle directly, we look up the equivalent DirectHandle(KIND_SPECIAL)276* and then convert it into a VirtualHandle using setVMSlotAndRawModifiersFromSpecialHandle(). This is necessary277* as not every method invokeable by invokevirtual is in the vtable (ie: final methods in Object).278* The reason why we can't go directly to the KIND_SPECIAL case is because we need to allow lookup of VirtualHandle279* for methods in indirect super interfaces. DirectHandle(KIND_SPECIAL) can NOT be used for methods in indirect280* super interfaces.281*/282isForVirtualLookup = TRUE;283kind = J9_METHOD_HANDLE_KIND_SPECIAL;284J9VMJAVALANGINVOKEMETHODHANDLE_SET_KIND(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), J9_METHOD_HANDLE_KIND_SPECIAL);285/* In order to allow lookup of virtual methods in indirect super interfaces, we need to be able to differentiate286* between KIND_VIRTUAL and KIND_SPECIAL below.287*/288/* Fall through */289case J9_METHOD_HANDLE_KIND_CONSTRUCTOR:290/* Fall through - <init> gets invoked by invokespecial so this should be able to find it */291case J9_METHOD_HANDLE_KIND_SPECIAL:292Assert_JCL_notNull(specialCaller);293j9SpecialCaller = J9VM_J9CLASS_FROM_JCLASS(vmThread, specialCaller);294method = lookupSpecialMethod(vmThread, j9LookupClass, nameUTF8, signatureUTF8, j9SpecialCaller, isForVirtualLookup);295vmSlotValue = method;296break;297default:298/* Assert here - illegal should never be called with something that doesn't directly map to kind */299Assert_JCL_unreachable();300goto _cleanup;301}302303if (method != (UDATA) NULL) {304/* Check signature for classloader visibility */305if (!accessCheckMethodSignature(vmThread, (J9Method*)method, J9VMJAVALANGINVOKEMETHODHANDLE_TYPE(vmThread, J9_JNI_UNWRAP_REFERENCE(handle)), signatureUTF8)) {306J9Class *methodClass = J9_CLASS_FROM_METHOD((J9Method*)method);307setClassLoadingConstraintLinkageError(vmThread, methodClass, signatureUTF8);308goto _cleanup;309}310311J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_VMSLOT(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), vmSlotValue);312J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_RAWMODIFIERS(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), J9_ROM_METHOD_FROM_RAM_METHOD(method)->modifiers);313result = vmFuncs->j9jni_createLocalRef(env, J9VM_J9CLASS_TO_HEAPCLASS(J9_CLASS_FROM_METHOD((J9Method*)method)));314}315316_cleanup:317vmFuncs->internalExitVMToJNI(vmThread);318319if (signatureUTF8 != (J9UTF8*)signatureUTF8Buffer) {320j9mem_free_memory(signatureUTF8);321}322323if (nameUTF8 != (J9UTF8*)nameUTF8Buffer) {324j9mem_free_memory(nameUTF8);325}326327return result;328}329330static BOOLEAN331accessCheckFieldSignature(J9VMThread *currentThread, J9Class* lookupClass, UDATA romField, j9object_t methodType, J9UTF8 *lookupSig)332{333334J9JavaVM *vm = currentThread->javaVM;335J9BytecodeVerificationData *verifyData = vm->bytecodeVerificationData;336BOOLEAN result = TRUE;337338/* If the verifier isn't enabled, accept the access check unconditionally */339if (NULL != verifyData) {340U_8 *lookupSigData = J9UTF8_DATA(lookupSig);341U_32 sigOffset = 0;342343while ('[' == lookupSigData[sigOffset]) {344sigOffset += 1;345}346347if ('L' == lookupSigData[sigOffset]) {348BOOLEAN isVirtual = (0 == (((J9ROMFieldShape*)romField)->modifiers & J9AccStatic));349j9object_t argsArray = J9VMJAVALANGINVOKEMETHODTYPE_PTYPES(currentThread, methodType);350U_32 numParameters = J9INDEXABLEOBJECT_SIZE(currentThread, argsArray);351j9object_t clazz = NULL;352J9Class *ramClass = NULL;353J9ClassLoader *targetClassloader = lookupClass->classLoader;354355/* Move past the L in the Lfoo; signature */356sigOffset += 1;357358/* '()X' or '(Receiver)X' are both getters. All others are setters */359if (((0 == numParameters) && !isVirtual) || ((1 == numParameters) && isVirtual)) {360clazz = J9VMJAVALANGINVOKEMETHODTYPE_RTYPE(currentThread, methodType);361} else {362U_32 argumentIndex = 0;363364if (isVirtual) {365argumentIndex = 1;366}367368clazz = J9JAVAARRAYOFOBJECT_LOAD(currentThread, argsArray, argumentIndex);369}370371ramClass = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, clazz);372if (ramClass->classLoader != targetClassloader) {373/* -1 on the length to remove the ; and the end of the signature */374U_32 sigLength = J9UTF8_LENGTH(lookupSig) - sigOffset - 1;375376omrthread_monitor_enter(vm->classTableMutex);377if(verifyData->checkClassLoadingConstraintForNameFunction(currentThread, targetClassloader, ramClass->classLoader, &lookupSigData[sigOffset], &lookupSigData[sigOffset], sigLength, TRUE) != 0) {378result = FALSE;379}380omrthread_monitor_exit(vm->classTableMutex);381}382}383}384return result;385}386387static BOOLEAN388accessCheckMethodSignature(J9VMThread *currentThread, J9Method *method, j9object_t methodType, J9UTF8 *lookupSig)389{390J9JavaVM *vm = currentThread->javaVM;391J9BytecodeVerificationData *verifyData = vm->bytecodeVerificationData;392BOOLEAN result = TRUE;393394/* If the verifier isn't enabled, accept the check unconditionally */395if (NULL != verifyData) {396U_8 *lookupSigData = J9UTF8_DATA(lookupSig);397/* Grab the args array and length from MethodType.arguments */398j9object_t argsArray = J9VMJAVALANGINVOKEMETHODTYPE_PTYPES(currentThread, methodType);399j9object_t clazz = NULL;400J9Class *methodRamClass = J9_CLASS_FROM_METHOD(method);401J9ClassLoader *targetClassloader = methodRamClass->classLoader;402J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);403J9UTF8 *targetSig = J9ROMMETHOD_SIGNATURE(romMethod);404U_32 numParameters = J9INDEXABLEOBJECT_SIZE(currentThread, argsArray);405U_32 i = 0;406U_32 index = 0;407U_32 endIndex = 0;408U_32 start = 0;409410/* For virtual methods we need to skip the first parameter in the MethodType parameter array */411if (0 == (romMethod->modifiers & J9AccStatic)) {412J9UTF8 *targetName = J9ROMMETHOD_NAME(romMethod);413if ('<' != J9UTF8_DATA(targetName)[0]) {414/* ensure the method is not a constructor which has a name <init> */415start = 1;416}417}418419/* checkClassLoadingConstraintForNameFunction requires this mutex to be locked */420omrthread_monitor_enter(vm->classTableMutex);421for (i = start; i < numParameters; i++) {422J9Class *argumentRamClass = NULL;423424/* Advance the text pointer to the next argument */425index += 1;426427/* If this entry is an array, index forward */428while ('[' == lookupSigData[index]) {429index += 1;430}431432endIndex = index;433434/* If this entry is a class type, we need to do a classloader check on it */435if ('L' == lookupSigData[index]) {436index += 1;437438clazz = J9JAVAARRAYOFOBJECT_LOAD(currentThread, argsArray, i);439argumentRamClass = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, clazz);440441while (';' != lookupSigData[endIndex]) {442endIndex += 1;443}444445/* Check if we really need to check this classloader constraint */446if (argumentRamClass->classLoader != targetClassloader) {447if(verifyData->checkClassLoadingConstraintForNameFunction(currentThread, targetClassloader, argumentRamClass->classLoader, &J9UTF8_DATA(targetSig)[index], &lookupSigData[index], endIndex - index, TRUE) != 0) {448result = FALSE;449goto releaseMutexAndReturn;450}451}452453index = endIndex;454}455}456457/* Skip past the ) at the end of the signature, plus 1 to get to the next entry */458index += 2;459460/* Check the return type. If it's an array, get to the actual type */461while ('[' == lookupSigData[index]) {462index += 1;463}464if('L' == lookupSigData[index]) {465J9Class *returnRamClass = NULL;466/* Grab the MethodType returnType */467clazz = J9VMJAVALANGINVOKEMETHODTYPE_RTYPE(currentThread, methodType);468returnRamClass = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, clazz);469470/* Check if we really need to check this classloader constraint */471if (targetClassloader != returnRamClass->classLoader) {472endIndex = index;473index++;474475while (';' != lookupSigData[endIndex]) {476endIndex++;477}478479if(verifyData->checkClassLoadingConstraintForNameFunction(currentThread, targetClassloader, returnRamClass->classLoader, &J9UTF8_DATA(targetSig)[index], &lookupSigData[index], endIndex - index, TRUE) != 0) {480result = FALSE;481goto releaseMutexAndReturn;482}483}484}485486releaseMutexAndReturn:487omrthread_monitor_exit(vm->classTableMutex);488}489490return result;491}492493/* Should already have VMAccess */494UDATA495lookupField(JNIEnv *env, jboolean isStatic, J9Class *j9LookupClass, jstring name, J9UTF8 *sigUTF, J9Class **definingClass, UDATA *romField, jclass accessClass)496{497J9UTF8 *nameUTF8 = NULL;498char nameUTF8Buffer[256];499J9Class *j9AccessClass = NULL; /* J9Class for java.lang.Class accessClass */500UDATA field = 0;501J9VMThread *vmThread = (J9VMThread *) env;502J9JavaVM *vm = vmThread->javaVM;503J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;504PORT_ACCESS_FROM_VMC(vmThread);505506nameUTF8 = vmFuncs->copyStringToJ9UTF8WithMemAlloc(vmThread, J9_JNI_UNWRAP_REFERENCE(name), J9_STR_NONE, "", 0, nameUTF8Buffer, sizeof(nameUTF8Buffer));507508if (NULL == nameUTF8) {509vmFuncs->setNativeOutOfMemoryError(vmThread, 0, 0);510Assert_JCL_notNull(vmThread->currentException);511goto _cleanup;512}513514if (NULL != accessClass) {515j9AccessClass = J9VM_J9CLASS_FROM_JCLASS(vmThread, accessClass);516}517518if (JNI_TRUE == isStatic) {519field = (UDATA) vmFuncs->staticFieldAddress(vmThread, j9LookupClass, J9UTF8_DATA(nameUTF8), J9UTF8_LENGTH(nameUTF8), J9UTF8_DATA(sigUTF), J9UTF8_LENGTH(sigUTF), definingClass, romField, 0, j9AccessClass);520if (0 == field) {521/* IllegalAccessError / IncompatibleClassChangeError / NoSuchFieldError will be pending */522Assert_JCL_notNull(vmThread->currentException);523goto _cleanup;524}525/* Turn field into an offset that is usable by Unsafe to support526* the JIT implementation of static Field handles527*/528field = (UDATA) field - (UDATA) (*definingClass)->ramStatics;529field += J9_SUN_STATIC_FIELD_OFFSET_TAG;530} else {531field = (UDATA) vmFuncs->instanceFieldOffset(vmThread, j9LookupClass, J9UTF8_DATA(nameUTF8), J9UTF8_LENGTH(nameUTF8), J9UTF8_DATA(sigUTF), J9UTF8_LENGTH(sigUTF), definingClass, romField, 0);532if (-1 == field) {533/* IllegalAccessError / IncompatibleClassChangeError / NoSuchFieldError will be pending */534Assert_JCL_notNull(vmThread->currentException);535goto _cleanup;536}537}538539/* definingClass & romField cannot be null here. The field lookup would have failed if they were null and540* would have done a goto _cleanup.541*/542Assert_JCL_notNull(*definingClass);543Assert_JCL_notNull((J9ROMFieldShape *)(*romField));544545_cleanup:546547if (nameUTF8 != (J9UTF8*)nameUTF8Buffer) {548j9mem_free_memory(nameUTF8);549}550551return field;552}553554jclass JNICALL555Java_java_lang_invoke_PrimitiveHandle_lookupField(JNIEnv *env, jobject handle, jclass lookupClass, jstring name, jstring signature, jboolean isStatic, jclass accessClass)556{557J9UTF8 *signatureUTF8 = NULL;558char signatureUTF8Buffer[256];559J9Class *j9LookupClass = NULL; /* J9Class for java.lang.Class lookupClass */560J9Class *definingClass = NULL; /* Returned by calls to find field */561UDATA field = 0;562jclass result = NULL;563UDATA romField = 0;564J9VMThread *vmThread = (J9VMThread *) env;565J9JavaVM *vm = vmThread->javaVM;566J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;567PORT_ACCESS_FROM_ENV(env);568569vmFuncs->internalEnterVMFromJNI(vmThread);570571signatureUTF8 = vmFuncs->copyStringToJ9UTF8WithMemAlloc(vmThread, J9_JNI_UNWRAP_REFERENCE(signature), J9_STR_NONE, "", 0, signatureUTF8Buffer, sizeof(signatureUTF8Buffer));572573if (signatureUTF8 == NULL) {574vmFuncs->setNativeOutOfMemoryError(vmThread, 0, 0);575Assert_JCL_notNull(vmThread->currentException);576goto _cleanup;577}578579j9LookupClass = J9VM_J9CLASS_FROM_JCLASS(vmThread, lookupClass);580581field = lookupField(env, isStatic, j9LookupClass, name, signatureUTF8, &definingClass, &romField, accessClass);582583if (NULL != vmThread->currentException) {584goto _cleanup;585}586587/* Check signature for classloader visibility */588if (!accessCheckFieldSignature(vmThread, j9LookupClass, romField, J9VMJAVALANGINVOKEMETHODHANDLE_TYPE(vmThread, J9_JNI_UNWRAP_REFERENCE(handle)), signatureUTF8)) {589setClassLoadingConstraintLinkageError(vmThread, definingClass, signatureUTF8);590goto _cleanup;591}592if (NULL != accessClass) {593J9Class *j9AccessClass = J9VM_J9CLASS_FROM_JCLASS(vmThread, accessClass);594if ((j9AccessClass->classLoader != j9LookupClass->classLoader)595&& !accessCheckFieldSignature(vmThread, j9AccessClass, romField, J9VMJAVALANGINVOKEMETHODHANDLE_TYPE(vmThread, J9_JNI_UNWRAP_REFERENCE(handle)), signatureUTF8)596) {597setClassLoadingConstraintLinkageError(vmThread, j9AccessClass, signatureUTF8);598goto _cleanup;599}600}601602J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_VMSLOT(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), field);603J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_RAWMODIFIERS(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), ((J9ROMFieldShape*) romField)->modifiers);604result = vmFuncs->j9jni_createLocalRef(env, J9VM_J9CLASS_TO_HEAPCLASS(definingClass));605606_cleanup:607vmFuncs->internalExitVMToJNI(vmThread);608609if (signatureUTF8 != (J9UTF8*)signatureUTF8Buffer) {610j9mem_free_memory(signatureUTF8);611}612613return result;614}615616617jboolean JNICALL618Java_java_lang_invoke_PrimitiveHandle_setVMSlotAndRawModifiersFromField(JNIEnv *env, jclass clazz, jobject handle, jobject reflectField)619{620J9VMThread *vmThread = (J9VMThread *) env;621J9JavaVM *vm = vmThread->javaVM;622J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;623J9ReflectFunctionTable *reflectFunctions = &(vm->reflectFunctions);624J9JNIFieldID *fieldID;625jboolean result = JNI_FALSE;626j9object_t fieldObject;627UDATA fieldOffset;628629vmFuncs->internalEnterVMFromJNI(vmThread);630/* Can't fail as we know the field is not null */631fieldObject = J9_JNI_UNWRAP_REFERENCE(reflectField);632fieldID = reflectFunctions->idFromFieldObject(vmThread, NULL, fieldObject);633634fieldOffset = fieldID->offset;635if (J9AccStatic == (fieldID->field->modifiers & J9AccStatic)) {636/* ensure this is correctly tagged so that the JIT targets using Unsafe will correctly detect this is static */637fieldOffset |= J9_SUN_STATIC_FIELD_OFFSET_TAG;638}639640641J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_VMSLOT(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), fieldOffset);642J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_RAWMODIFIERS(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), fieldID->field->modifiers);643result = JNI_TRUE;644645vmFuncs->internalExitVMToJNI(vmThread);646return result;647}648649650jboolean JNICALL651Java_java_lang_invoke_PrimitiveHandle_setVMSlotAndRawModifiersFromMethod(JNIEnv *env, jclass clazz, jobject handle, jclass unused, jobject method, jbyte kind, jclass specialToken)652{653J9VMThread *vmThread = (J9VMThread *) env;654J9JavaVM *vm = vmThread->javaVM;655J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;656J9ReflectFunctionTable *reflectFunctions = &(vm->reflectFunctions);657J9JNIMethodID *methodID;658J9Class *j9SpecialToken = NULL;659jboolean result = JNI_FALSE;660UDATA vmSlotValue;661j9object_t methodObject;662U_32 modifiers;663664vmFuncs->internalEnterVMFromJNI(vmThread);665if (specialToken != NULL) {666j9SpecialToken = J9VM_J9CLASS_FROM_JCLASS(vmThread, specialToken);667}668/* Can't fail as we know the method is not null */669methodObject = J9_JNI_UNWRAP_REFERENCE(method);670methodID = reflectFunctions->idFromMethodObject(vmThread, methodObject);671modifiers = J9_ROM_METHOD_FROM_RAM_METHOD(methodID->method)->modifiers;672673switch(kind){674case J9_METHOD_HANDLE_KIND_STATIC:675vmSlotValue = (UDATA) methodID->method;676break;677case J9_METHOD_HANDLE_KIND_VIRTUAL:678vmSlotValue = methodID->vTableIndex;679break;680case J9_METHOD_HANDLE_KIND_INTERFACE:681Assert_JCL_true(J9_ARE_ANY_BITS_SET(methodID->vTableIndex, J9_JNI_MID_INTERFACE));682vmSlotValue = methodID->vTableIndex & ~J9_JNI_MID_INTERFACE;683break;684case J9_METHOD_HANDLE_KIND_SPECIAL:685if (specialToken == NULL) {686goto _cleanup;687}688if ((J9AccMethodVTable != (modifiers & J9AccMethodVTable))) {689/* Handle methods which aren't in the VTable, such as private methods and Object.getClass */690vmSlotValue = (UDATA) methodID->method;691} else {692vmSlotValue = (UDATA)getMethodForSpecialSend(vmThread, j9SpecialToken, J9_CLASS_FROM_METHOD(methodID->method), methodID->method, J9_LOOK_VIRTUAL | J9_LOOK_NO_VISIBILITY_CHECK | J9_LOOK_IGNORE_INCOMPATIBLE_METHODS);693Assert_JCL_true(0 != vmSlotValue);694}695break;696default:697/* Assert here - illegal should never be called with something that doesn't directly map to kind */698Assert_JCL_unreachable();699goto _cleanup;700}701702J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_VMSLOT(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), vmSlotValue);703J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_RAWMODIFIERS(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), modifiers);704705result = JNI_TRUE;706707_cleanup:708vmFuncs->internalExitVMToJNI(vmThread);709710return result;711}712713jboolean JNICALL714Java_java_lang_invoke_PrimitiveHandle_setVMSlotAndRawModifiersFromConstructor(JNIEnv *env, jclass clazz, jobject handle, jobject ctor)715{716J9VMThread *vmThread = (J9VMThread *) env;717J9JavaVM *vm = vmThread->javaVM;718J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;719J9ReflectFunctionTable *reflectFunctions = &(vm->reflectFunctions);720J9JNIMethodID *methodID;721jboolean result = JNI_FALSE;722j9object_t methodObject;723724vmFuncs->internalEnterVMFromJNI(vmThread);725/* Can't fail as we know the method is not null */726methodObject = J9_JNI_UNWRAP_REFERENCE(ctor);727methodID = reflectFunctions->idFromConstructorObject(vmThread, methodObject);728729J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_VMSLOT(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), (UDATA)methodID->method);730J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_RAWMODIFIERS(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), J9_ROM_METHOD_FROM_RAM_METHOD(methodID->method)->modifiers);731732result = JNI_TRUE;733734vmFuncs->internalExitVMToJNI(vmThread);735return result;736}737738/**739* Assign the vmSlot for a VirtualHandle when given a DirectHandle that is of KIND_SPECIAL.740* This method does no access checking as the access checks should have occurred when creating741* the SpecialHandle.742*/743jboolean JNICALL744Java_java_lang_invoke_PrimitiveHandle_setVMSlotAndRawModifiersFromSpecialHandle(JNIEnv *env, jclass clazz, jobject handle, jobject specialHandle)745{746J9VMThread *vmThread = (J9VMThread *) env;747J9JavaVM *vm = vmThread->javaVM;748J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;749jboolean result = JNI_FALSE;750UDATA vtableOffset;751j9object_t specialHandleObject;752J9Method *method;753j9object_t classObject;754J9Class *j9class;755756vmFuncs->internalEnterVMFromJNI(vmThread);757specialHandleObject = J9_JNI_UNWRAP_REFERENCE(specialHandle);758759method = (J9Method *)(UDATA) J9VMJAVALANGINVOKEPRIMITIVEHANDLE_VMSLOT(vmThread, specialHandleObject);760classObject = (j9object_t) J9VMJAVALANGINVOKEPRIMITIVEHANDLE_REFERENCECLASS(vmThread, specialHandleObject);761if ((method == NULL) || (classObject == NULL)) {762goto _done;763}764j9class = J9VM_J9CLASS_FROM_HEAPCLASS(vmThread, classObject);765if (j9class == NULL) {766goto _done;767}768vtableOffset = vmFuncs->getVTableOffsetForMethod(method, j9class, vmThread);769if (vtableOffset != 0) {770J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_VMSLOT(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), vtableOffset);771J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_RAWMODIFIERS(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), J9_ROM_METHOD_FROM_RAM_METHOD(method)->modifiers);772result = JNI_TRUE;773}774775_done:776vmFuncs->internalExitVMToJNI(vmThread);777return result;778}779780/* Return the field offset of the 'vmRef' field in j.l.Class.781* Needed by the JIT in MethodHandle's static initializer before Unsafe782* can be loaded. The 'ignored' parameter is to work around a javac bug.783*/784jint JNICALL785Java_java_lang_invoke_MethodHandle_vmRefFieldOffset(JNIEnv *env, jclass clazz, jclass ignored)786{787return (jint) J9VMJAVALANGCLASS_VMREF_OFFSET(((J9VMThread *) env));788}789790#ifdef J9VM_OPT_PANAMA791jlong JNICALL792Java_java_lang_invoke_MethodHandles_findNativeAddress(JNIEnv *env, jclass jlClass, jstring methodName)793{794const char *nativeMethodName = NULL;795UDATA handle = 0;796jlong func = 0;797PORT_ACCESS_FROM_ENV(env);798799nativeMethodName = (*env)->GetStringUTFChars(env, methodName, NULL);800801if(0 == j9sl_open_shared_library(NULL, &handle, FALSE)) {802if(0 != j9sl_lookup_name(handle, (char *)nativeMethodName, (UDATA *)&func, "")){803func = 0;804}805}806807return func;808}809#endif810811void JNICALL812Java_java_lang_invoke_MutableCallSite_freeGlobalRef(JNIEnv *env, jclass mutableCallSite, jlong bypassOffset)813{814if (0 != bypassOffset) {815J9VMThread *vmThread = (J9VMThread *) env;816J9JavaVM *vm = vmThread->javaVM;817J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;818jobject globalRef = NULL;819820vmFuncs->internalEnterVMFromJNI(vmThread);821globalRef = (jobject)((UDATA)J9VM_J9CLASS_FROM_HEAPCLASS(vmThread, J9_JNI_UNWRAP_REFERENCE(mutableCallSite))->ramStatics + ((UDATA)bypassOffset & ~(UDATA)J9_SUN_FIELD_OFFSET_MASK));822vmFuncs->j9jni_deleteGlobalRef(env, globalRef, FALSE);823vmFuncs->internalExitVMToJNI(vmThread);824}825return;826}827828void JNICALL829Java_java_lang_invoke_ThunkTuple_registerNatives(JNIEnv *env, jclass nativeClass)830{831JNINativeMethod natives[] = {832{833"initialInvokeExactThunk",834"()J",835(void *)&vmInitialInvokeExactThunk836}837};838JNINativeMethod finalizeNative[] = {839{840"finalizeImpl",841"(J)V",842(void *)&vmFinalizeImpl843}844};845846registerVMNativesIfNoJIT(env, nativeClass, natives, 1);847848/* Always register this native - JIT may provide an implementation later.849* This is just a hook that will allow them to override the native if850* the code cache leaking is an issue.851*/852(*env)->RegisterNatives(env, nativeClass, finalizeNative, 1);853#if defined(J9VM_OPT_JAVA_OFFLOAD_SUPPORT)854/* Jazz 99339: Given that the non-zAAP eligible bit is set in RegisterNatives(),855* we need to clear the bit here for JCL natives to allow them to run on zAAP.856*/857clearNonZAAPEligibleBit(env, nativeClass, finalizeNative, 1);858#endif /* J9VM_OPT_JAVA_OFFLOAD_SUPPORT */859860return;861}862863864void JNICALL865Java_java_lang_invoke_MutableCallSite_registerNatives(JNIEnv *env, jclass nativeClass)866{867JNINativeMethod natives[] = {868{869"invalidate",870"([J)V",871(void *)&vmInvalidate872}873};874registerVMNativesIfNoJIT(env, nativeClass, natives, 1);875return;876}877878879void JNICALL880Java_java_lang_invoke_InterfaceHandle_registerNatives(JNIEnv *env, jclass nativeClass)881{882JNINativeMethod natives[] = {883{884"convertITableIndexToVTableIndex",885"(JIJ)I",886(void *)&vmConvertITableIndexToVTableIndex887}888};889registerVMNativesIfNoJIT(env, nativeClass, natives, 1);890return;891}892893/*894* Helper function to register vm versions of native methods if the jitconfig is null.895*/896static void897registerVMNativesIfNoJIT(JNIEnv *env, jclass nativeClass, JNINativeMethod *natives, jint numNatives)898{899J9VMThread *vmThread = (J9VMThread *) env;900901if (NULL == vmThread->javaVM->jitConfig) {902(*env)->RegisterNatives(env, nativeClass, natives, numNatives);903#if defined(J9VM_OPT_JAVA_OFFLOAD_SUPPORT)904/* Jazz 99339: Given that the non-zAAP eligible bit is set in RegisterNatives(),905* we need to clear the bit here for JCL natives to allow them to run on zAAP.906*/907clearNonZAAPEligibleBit(env, nativeClass, natives, numNatives);908#endif /* J9VM_OPT_JAVA_OFFLOAD_SUPPORT */909}910911return;912}913914static void JNICALL915vmInvalidate(JNIEnv *env, jclass mutableCallSiteClass, jlongArray cookies)916{917/* No op - this native is supplied by the JIT dll when the jit is enabled.918* This is just a dummy native to prevent LinkageErrors when running Xint.919*/920return;921}922923static jlong JNICALL924vmInitialInvokeExactThunk(JNIEnv *env, jclass ignored)925{926return 0;927}928929static jlong JNICALL930vmConvertITableIndexToVTableIndex(JNIEnv *env, jclass InterfaceMethodHandle, jlong interfaceArg, jint itableIndex, jlong receiverClassArg)931{932return 0;933}934935static void JNICALL936vmFinalizeImpl(JNIEnv *env, jclass methodHandleClass, jlong thunkAddress)937{938return;939}940941/**942* Fill in a parameterized NLS message.943*944* Does not require VM access.945*946* @param[in] vmThread The current VM thread.947* @param[in] nlsTemplate A parameterized NLS message, as returned from j9nls_lookup_message().948* @return An allocated buffer containing the expanded NLS message. Caller must free this949* buffer using j9mem_free_memory().950*/951static char *952expandNLSTemplate(J9VMThread *vmThread, const char *nlsTemplate, ...)953{954PORT_ACCESS_FROM_VMC(vmThread);955char *msg = NULL;956957if (NULL != nlsTemplate) {958UDATA msgLen = 0;959va_list args;960961va_start(args, nlsTemplate);962msgLen = j9str_vprintf(NULL, 0, nlsTemplate, args);963va_end(args);964965msg = (char *)j9mem_allocate_memory(msgLen, OMRMEM_CATEGORY_VM);966if (NULL != msg) {967va_start(args, nlsTemplate);968j9str_vprintf(msg, msgLen, nlsTemplate, args);969va_end(args);970}971}972return msg;973}974975/**976* Set a LinkageError to indicate a class loading constraint violation between977* the MT and the looked up method or field.978*979* @param[in] vmThread The current J9VMThread *980* @param[in] methodOrFieldClass The defining class of the looked up field or method981* @param[in] signatureUTF8 The signature of the MethodType982*/983void984setClassLoadingConstraintLinkageError(J9VMThread *vmThread, J9Class *methodOrFieldClass, J9UTF8 *signatureUTF8)985{986J9JavaVM *vm = vmThread->javaVM;987J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;988PORT_ACCESS_FROM_VMC(vmThread);989J9UTF8 *className = J9ROMCLASS_CLASSNAME(methodOrFieldClass->romClass);990const char *nlsTemplate = j9nls_lookup_message(991J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE,992J9NLS_JCL_METHODTYPE_CLASS_LOADING_CONSTRAINT,993"loading constraint violation: %.*s not visible from %.*s");994char * msg = expandNLSTemplate(995vmThread,996nlsTemplate,997J9UTF8_LENGTH(signatureUTF8), J9UTF8_DATA(signatureUTF8),998J9UTF8_LENGTH(className), J9UTF8_DATA(className));999vmFuncs->setCurrentExceptionUTF(vmThread, J9VMCONSTANTPOOL_JAVALANGLINKAGEERROR, msg);1000j9mem_free_memory(msg);1001}10021003#if defined(J9VM_OPT_JAVA_OFFLOAD_SUPPORT)1004/**1005* Clear the non-ZAAP eligible bit for JCL natives to allow them to run on zAAP.1006*1007* @param[in] env The JNI interface pointer1008* @param[in] nativeClass The class containing the native method1009* @param[in] nativeMethods The JNI native method pointer1010* @param[in] nativeMethodCount The count of native methods1011*/1012void1013clearNonZAAPEligibleBit(JNIEnv *env, jclass nativeClass, const JNINativeMethod *nativeMethods, jint nativeMethodCount)1014{1015J9VMThread *vmThread = (J9VMThread *) env;1016J9JavaVM *vm = vmThread->javaVM;1017J9InternalVMFunctions* vmFuncs = vm->internalVMFunctions;1018const JNINativeMethod *nativeMethod = nativeMethods;1019jint count = nativeMethodCount;1020J9Class *j9clazz = NULL;10211022vmFuncs->internalEnterVMFromJNI(vmThread);1023j9clazz = J9VM_J9CLASS_FROM_HEAPCLASS(vmThread, J9_JNI_UNWRAP_REFERENCE(nativeClass));10241025while (0 < count) {1026J9Method *jniMethod = vmFuncs->findJNIMethod(vmThread, j9clazz, nativeMethod->name, nativeMethod->signature);1027vmFuncs->atomicAndIntoConstantPool(vm, jniMethod, ~(UDATA)J9_STARTPC_NATIVE_REQUIRES_SWITCHING);1028count -= 1;1029nativeMethod +=1;1030}1031vmFuncs->internalExitVMToJNI(vmThread);1032}1033#endif /* J9VM_OPT_JAVA_OFFLOAD_SUPPORT */10341035#if JAVA_SPEC_VERSION >= 151036void JNICALL1037Java_java_lang_invoke_MethodHandleNatives_checkClassBytes(JNIEnv *env, jclass jlClass, jbyteArray classRep)1038{1039J9VMThread *currentThread = (J9VMThread *)env;1040J9JavaVM *vm = currentThread->javaVM;1041J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;1042jsize length = 0;1043U_8* classBytes = NULL;1044I_32 rc = 0;1045U_8* segment = NULL;1046U_32 segmentLength = 0;1047PORT_ACCESS_FROM_JAVAVM(vm);10481049if (NULL == classRep) {1050throwNewNullPointerException(env, NULL);1051goto done;1052}1053length = (*env)->GetArrayLength(env, classRep);1054if (0 == length) {1055goto done;1056}10571058segmentLength = ESTIMATE_SIZE(length);1059segment = (U_8*)j9mem_allocate_memory(segmentLength, J9MEM_CATEGORY_VM_JCL);1060if (NULL == segment) {1061vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);1062goto done;1063}1064memset(segment, 0, segmentLength);1065classBytes = (*env)->GetPrimitiveArrayCritical(env, classRep, NULL);10661067rc = vmFuncs->checkClassBytes(currentThread, classBytes, length, segment, segmentLength);1068(*env)->ReleasePrimitiveArrayCritical(env, classRep, classBytes, 0);1069if (0 != rc) {1070J9CfrError *cfrError = (J9CfrError *)segment;1071const char* errorMsg = OMRPORT_FROM_J9PORT(PORTLIB)->nls_lookup_message(OMRPORT_FROM_J9PORT(PORTLIB), J9NLS_DO_NOT_APPEND_NEWLINE, cfrError->errorCatalog, cfrError->errorCode, NULL);1072vmFuncs->internalEnterVMFromJNI(currentThread);1073vmFuncs->setCurrentExceptionUTF(currentThread, cfrError->errorAction, errorMsg);1074vmFuncs->internalExitVMToJNI(currentThread);1075}1076j9mem_free_memory(segment);1077done:1078return;1079}1080#endif /* JAVA_SPEC_VERSION >= 15 */108110821083