Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/jcl/common/java_dyn_methodhandle.c
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2001, 2021 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* 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-exception
21
*******************************************************************************/
22
23
#include <string.h>
24
#include <stdlib.h>
25
26
#include "j9.h"
27
#include "jcl.h"
28
#include "j9consts.h"
29
#include "jni.h"
30
#include "j9protos.h"
31
#include "jcl_internal.h"
32
#include "jclprots.h"
33
#include "ut_j9jcl.h"
34
#include "VM_MethodHandleKinds.h"
35
36
#include "rommeth.h"
37
#include "j9vmnls.h"
38
#include "j9vmconstantpool.h"
39
#include "j9jclnls.h"
40
#include "cfreader.h"
41
42
/*
43
* Note that the following native methods are implemented in sun_reflect_ConstantPool.c because
44
* they effectively extend the ConstantPool API and require functionality from that module:
45
* Java_java_lang_invoke_MethodHandleResolver_getCPTypeAt
46
* Java_java_lang_invoke_MethodHandleResolver_getCPMethodTypeAt
47
* Java_java_lang_invoke_MethodHandleResolver_getCPMethodHandleAt
48
* Java_java_lang_invoke_MethodHandleResolver_getCPConstantDynamicAt
49
*/
50
51
static VMINLINE UDATA lookupImpl(J9VMThread *currentThread, J9Class *lookupClass, J9UTF8 *name, J9UTF8 *signature, J9Class *senderClass, UDATA options, BOOLEAN *foundDefaultConflicts);
52
static void registerVMNativesIfNoJIT(JNIEnv *env, jclass nativeClass, JNINativeMethod *natives, jint numNatives);
53
static jlong JNICALL vmInitialInvokeExactThunk(JNIEnv *env, jclass ignored);
54
static jlong JNICALL vmConvertITableIndexToVTableIndex(JNIEnv *env, jclass InterfaceMethodHandle, jlong interfaceArg, jint itableIndex, jlong receiverClassArg);
55
static void JNICALL vmFinalizeImpl(JNIEnv *env, jclass methodHandleClass, jlong thunkAddress);
56
static void JNICALL vmInvalidate(JNIEnv *env, jclass mutableCallSiteClass, jlongArray cookies);
57
static BOOLEAN accessCheckMethodSignature(J9VMThread *currentThread, J9Method *method, j9object_t methodType, J9UTF8 *lookupSig);
58
static BOOLEAN accessCheckFieldSignature(J9VMThread *currentThread, J9Class* lookupClass, UDATA romField, j9object_t methodType, J9UTF8 *lookupSig);
59
static char * expandNLSTemplate(J9VMThread *vmThread, const char *nlsTemplate, ...);
60
61
/**
62
* Lookup static method name of type signature on lookupClass class.
63
*
64
* @param currentThread The thread used in the lookup.
65
* @param lookupClass The class to do the lookup on
66
* @param name The method name to lookup. Assumed to be verified.
67
* @param signature A valid method signature (JVM spec 4.4.3).
68
*
69
* @return a J9Method pointer or NULL on error.
70
*/
71
static UDATA
72
lookupStaticMethod(J9VMThread *currentThread, J9Class *lookupClass, J9UTF8 *name, J9UTF8 *signature)
73
{
74
return lookupImpl(currentThread, lookupClass, name, signature, NULL, J9_LOOK_STATIC, NULL);
75
}
76
77
static UDATA
78
lookupInterfaceMethod(J9VMThread *currentThread, J9Class *lookupClass, J9UTF8 *name, J9UTF8 *signature, UDATA *methodIndex)
79
{
80
J9Method *method;
81
82
if (methodIndex == NULL) {
83
return (UDATA) NULL;
84
}
85
*methodIndex = -1;
86
87
/* Lookup the Interface method find its itable slot */
88
method = (J9Method *) lookupImpl(currentThread, lookupClass, name, signature, NULL, J9_LOOK_INTERFACE, NULL);
89
if (method != NULL) {
90
J9InternalVMFunctions *vmFuncs = currentThread->javaVM->internalVMFunctions;
91
92
Assert_JCL_true(!J9_ARE_ANY_BITS_SET(J9_ROM_METHOD_FROM_RAM_METHOD(method)->modifiers, J9AccStatic));
93
94
/* Starting Java 11 Nestmates, invokeInterface is allowed to target private interface methods */
95
if ((J2SE_VERSION(currentThread->javaVM) < J2SE_V11) && J9_ARE_ANY_BITS_SET(J9_ROM_METHOD_FROM_RAM_METHOD(method)->modifiers, J9AccPrivate)) {
96
/* [PR 67082] private interface methods require invokespecial, not invokeinterface.*/
97
vmFuncs->setCurrentExceptionNLS(currentThread, J9VMCONSTANTPOOL_JAVALANGINCOMPATIBLECLASSCHANGEERROR, J9NLS_JCL_PRIVATE_INTERFACE_REQUIRES_INVOKESPECIAL);
98
method = NULL;
99
} else {
100
if (J9_ARE_ANY_BITS_SET(J9_CLASS_FROM_METHOD(method)->romClass->modifiers, J9AccInterface)) {
101
if (J9ROMMETHOD_IN_ITABLE(J9_ROM_METHOD_FROM_RAM_METHOD(method))) {
102
*methodIndex = getITableIndexForMethod(method, lookupClass);
103
} else {
104
PORT_ACCESS_FROM_VMC(currentThread);
105
J9Class *clazz = J9_CLASS_FROM_METHOD(method);
106
J9UTF8 *className = J9ROMCLASS_CLASSNAME(clazz->romClass);
107
J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);
108
J9UTF8 *methodName = J9ROMMETHOD_NAME(romMethod);
109
J9UTF8 *sig = J9ROMMETHOD_SIGNATURE(romMethod);
110
size_t nameAndSigLength = J9UTF8_LENGTH(className)
111
+ J9UTF8_LENGTH(methodName) + J9UTF8_LENGTH(sig)
112
+ 4 /* period, parentheses, and terminating null */;
113
char *msg = j9mem_allocate_memory(nameAndSigLength, OMRMEM_CATEGORY_VM);
114
if (NULL != msg) {
115
j9str_printf(PORTLIB, msg, nameAndSigLength, "%.*s.%.*s(%.*s)",
116
J9UTF8_LENGTH(className), J9UTF8_DATA(className),
117
J9UTF8_LENGTH(methodName), J9UTF8_DATA(methodName),
118
J9UTF8_LENGTH(sig), J9UTF8_DATA(sig));
119
vmFuncs->setCurrentExceptionUTF(currentThread,
120
J9VMCONSTANTPOOL_JAVALANGNOSUCHMETHODERROR, msg);
121
j9mem_free_memory(msg);
122
} else {
123
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
124
}
125
method = NULL;
126
}
127
}
128
}
129
}
130
131
return (UDATA) method;
132
}
133
134
/*
135
* See resolvesupport.c: resolveSpecialMethodRefInto
136
*/
137
static UDATA
138
lookupSpecialMethod(J9VMThread *currentThread, J9Class *lookupClass, J9UTF8 *name, J9UTF8 *signature, J9Class *specialCaller, BOOLEAN isForVirtualLookup)
139
{
140
J9Method *method = NULL;
141
BOOLEAN foundDefaultConflicts = FALSE;
142
143
/* REASON FOR THE J9_LOOK_HANDLE_DEFAULT_METHOD_CONFLICTS:
144
* Virtual invocation modes may still find a method in the receiver's vtable that resolves the default method conflict.
145
* If not, the method in the vtable will be a special method for throwing the exception.
146
*
147
* Special invocations (defender supersends) will not look at the receiver's vtable, but instead invoke the result of javaLookupMethod.
148
* Default method conflicts must therefore be handled by the lookup code.
149
*/
150
UDATA lookupOptions = J9_LOOK_VIRTUAL | J9_LOOK_HANDLE_DEFAULT_METHOD_CONFLICTS;
151
152
method = (J9Method*)lookupImpl(currentThread, lookupClass, name, signature, specialCaller, lookupOptions, &foundDefaultConflicts);
153
154
if (foundDefaultConflicts) {
155
J9InternalVMFunctions *vmFuncs = currentThread->javaVM->internalVMFunctions;
156
/* Don't need to clear the current exception here - it will be cleared when setting the exception. */
157
vmFuncs->setCurrentExceptionWithCause(currentThread, J9VMCONSTANTPOOL_JAVALANGINVOKEDEFAULTMETHODCONFLICTEXCEPTION, NULL, currentThread->currentException);
158
} else if (NULL != method) {
159
J9Class *resolvedClass = J9_CLASS_FROM_METHOD(method);
160
if (isForVirtualLookup || isDirectSuperInterface(currentThread, resolvedClass, specialCaller)) {
161
/* CMVC 197763 seq#4: Use the method's class, not the lookupClass, as the resolvedClass arg. LookupClass may be unrelated */
162
method = getMethodForSpecialSend(currentThread, specialCaller, resolvedClass, method, J9_LOOK_VIRTUAL | J9_LOOK_NO_VISIBILITY_CHECK | J9_LOOK_IGNORE_INCOMPATIBLE_METHODS);
163
Assert_JCL_notNull(method);
164
} else {
165
setIncompatibleClassChangeErrorInvalidDefenderSupersend(currentThread, resolvedClass, specialCaller);
166
method = NULL;
167
}
168
}
169
170
return (UDATA)method;
171
}
172
173
174
/**
175
* Wrapper around javalookupMethod - packs the name and signature into a J9ROMNameAndSignature struct and calls
176
* javaLookupMethod.
177
*
178
* Returns a J9Method* or NULL.
179
*/
180
static UDATA
181
lookupImpl(J9VMThread *currentThread, J9Class *lookupClass, J9UTF8 *name, J9UTF8 *signature, J9Class *senderClass, UDATA options, BOOLEAN *foundDefaultConflicts)
182
{
183
J9Method *method;
184
J9NameAndSignature nameAndSig;
185
J9JavaVM * vm = currentThread->javaVM;
186
187
Assert_JCL_notNull(lookupClass);
188
Assert_JCL_notNull(name);
189
Assert_JCL_notNull(signature);
190
191
nameAndSig.name = name;
192
nameAndSig.signature = signature;
193
method = (J9Method *) vm->internalVMFunctions->javaLookupMethodImpl(currentThread, lookupClass, (J9ROMNameAndSignature *)&nameAndSig, senderClass, options /* | J9_LOOK_NO_THROW | J9_LOOK_CLCONSTRAINTS */ | J9_LOOK_DIRECT_NAS, foundDefaultConflicts);
194
195
return (UDATA) method;
196
}
197
198
void JNICALL
199
Java_java_lang_invoke_MethodHandle_requestCustomThunkFromJit(JNIEnv* env, jobject handle, jobject thunk)
200
{
201
J9VMThread *vmThread = ((J9VMThread *) env);
202
J9JavaVM *vm = vmThread->javaVM;
203
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
204
205
vmFuncs->internalEnterVMFromJNI(vmThread);
206
vm->jitConfig->translateMethodHandle(
207
vmThread,
208
J9_JNI_UNWRAP_REFERENCE(handle),
209
J9_JNI_UNWRAP_REFERENCE(thunk),
210
J9_METHOD_HANDLE_COMPILE_CUSTOM);
211
vmFuncs->internalExitVMToJNI(vmThread);
212
}
213
214
jclass JNICALL
215
Java_java_lang_invoke_PrimitiveHandle_lookupMethod(JNIEnv *env, jobject handle, jclass lookupClass, jstring name, jstring signature, jbyte kind, jclass specialCaller)
216
{
217
J9VMThread *vmThread = ((J9VMThread *) env);
218
J9JavaVM *vm = vmThread->javaVM;
219
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
220
J9UTF8 *nameUTF8 = NULL;
221
char nameUTF8Buffer[256];
222
J9UTF8 *signatureUTF8 = NULL;
223
char signatureUTF8Buffer[256];
224
UDATA method;
225
J9Class *j9LookupClass;
226
J9Class *j9SpecialCaller = NULL;
227
UDATA vmSlotValue = (UDATA)-1; /* Set to invalid value so easy to find.*/
228
jclass result = NULL;
229
BOOLEAN isForVirtualLookup = FALSE;
230
PORT_ACCESS_FROM_ENV(env);
231
232
vmFuncs->internalEnterVMFromJNI(vmThread);
233
234
nameUTF8 = vmFuncs->copyStringToJ9UTF8WithMemAlloc(vmThread, J9_JNI_UNWRAP_REFERENCE(name), J9_STR_NONE, "", 0, nameUTF8Buffer, sizeof(nameUTF8Buffer));
235
236
if (nameUTF8 == NULL) {
237
vmFuncs->setNativeOutOfMemoryError(vmThread, 0, 0);
238
goto _cleanup;
239
}
240
241
signatureUTF8 = vmFuncs->copyStringToJ9UTF8WithMemAlloc(vmThread, J9_JNI_UNWRAP_REFERENCE(signature), J9_STR_NONE, "", 0, signatureUTF8Buffer, sizeof(signatureUTF8Buffer));
242
243
if (signatureUTF8 == NULL) {
244
vmFuncs->setNativeOutOfMemoryError(vmThread, 0, 0);
245
goto _cleanup;
246
}
247
248
j9LookupClass = J9VM_J9CLASS_FROM_JCLASS(vmThread, lookupClass);
249
Assert_JCL_notNull(j9LookupClass);
250
251
switch(kind){
252
case J9_METHOD_HANDLE_KIND_STATIC:
253
method = lookupStaticMethod(vmThread, j9LookupClass, nameUTF8, signatureUTF8);
254
vmSlotValue = method;
255
256
if (NULL != (J9Method*)method) {
257
J9Class *methodClass = J9_CLASS_FROM_METHOD((J9Method *)method);
258
259
if (methodClass != j9LookupClass) {
260
if (J9AccInterface == (j9LookupClass->romClass->modifiers & J9AccInterface)) {
261
/* Throws NoSuchMethodError (an IncompatibleClassChangeError subclass).
262
* This will be converted to NoSuchMethodException
263
* by the finishMethodInitialization() call in DirectHandle constructor.
264
*/
265
vmFuncs->setCurrentException(vmThread, J9VMCONSTANTPOOL_JAVALANGNOSUCHMETHODERROR, NULL);
266
goto _cleanup;
267
}
268
}
269
}
270
271
break;
272
case J9_METHOD_HANDLE_KIND_INTERFACE:
273
method = lookupInterfaceMethod(vmThread, j9LookupClass, nameUTF8, signatureUTF8, &vmSlotValue);
274
break;
275
case J9_METHOD_HANDLE_KIND_VIRTUAL:
276
/* Instead of looking up the VirtualHandle directly, we look up the equivalent DirectHandle(KIND_SPECIAL)
277
* and then convert it into a VirtualHandle using setVMSlotAndRawModifiersFromSpecialHandle(). This is necessary
278
* as not every method invokeable by invokevirtual is in the vtable (ie: final methods in Object).
279
* The reason why we can't go directly to the KIND_SPECIAL case is because we need to allow lookup of VirtualHandle
280
* for methods in indirect super interfaces. DirectHandle(KIND_SPECIAL) can NOT be used for methods in indirect
281
* super interfaces.
282
*/
283
isForVirtualLookup = TRUE;
284
kind = J9_METHOD_HANDLE_KIND_SPECIAL;
285
J9VMJAVALANGINVOKEMETHODHANDLE_SET_KIND(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), J9_METHOD_HANDLE_KIND_SPECIAL);
286
/* In order to allow lookup of virtual methods in indirect super interfaces, we need to be able to differentiate
287
* between KIND_VIRTUAL and KIND_SPECIAL below.
288
*/
289
/* Fall through */
290
case J9_METHOD_HANDLE_KIND_CONSTRUCTOR:
291
/* Fall through - <init> gets invoked by invokespecial so this should be able to find it */
292
case J9_METHOD_HANDLE_KIND_SPECIAL:
293
Assert_JCL_notNull(specialCaller);
294
j9SpecialCaller = J9VM_J9CLASS_FROM_JCLASS(vmThread, specialCaller);
295
method = lookupSpecialMethod(vmThread, j9LookupClass, nameUTF8, signatureUTF8, j9SpecialCaller, isForVirtualLookup);
296
vmSlotValue = method;
297
break;
298
default:
299
/* Assert here - illegal should never be called with something that doesn't directly map to kind */
300
Assert_JCL_unreachable();
301
goto _cleanup;
302
}
303
304
if (method != (UDATA) NULL) {
305
/* Check signature for classloader visibility */
306
if (!accessCheckMethodSignature(vmThread, (J9Method*)method, J9VMJAVALANGINVOKEMETHODHANDLE_TYPE(vmThread, J9_JNI_UNWRAP_REFERENCE(handle)), signatureUTF8)) {
307
J9Class *methodClass = J9_CLASS_FROM_METHOD((J9Method*)method);
308
setClassLoadingConstraintLinkageError(vmThread, methodClass, signatureUTF8);
309
goto _cleanup;
310
}
311
312
J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_VMSLOT(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), vmSlotValue);
313
J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_RAWMODIFIERS(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), J9_ROM_METHOD_FROM_RAM_METHOD(method)->modifiers);
314
result = vmFuncs->j9jni_createLocalRef(env, J9VM_J9CLASS_TO_HEAPCLASS(J9_CLASS_FROM_METHOD((J9Method*)method)));
315
}
316
317
_cleanup:
318
vmFuncs->internalExitVMToJNI(vmThread);
319
320
if (signatureUTF8 != (J9UTF8*)signatureUTF8Buffer) {
321
j9mem_free_memory(signatureUTF8);
322
}
323
324
if (nameUTF8 != (J9UTF8*)nameUTF8Buffer) {
325
j9mem_free_memory(nameUTF8);
326
}
327
328
return result;
329
}
330
331
static BOOLEAN
332
accessCheckFieldSignature(J9VMThread *currentThread, J9Class* lookupClass, UDATA romField, j9object_t methodType, J9UTF8 *lookupSig)
333
{
334
335
J9JavaVM *vm = currentThread->javaVM;
336
J9BytecodeVerificationData *verifyData = vm->bytecodeVerificationData;
337
BOOLEAN result = TRUE;
338
339
/* If the verifier isn't enabled, accept the access check unconditionally */
340
if (NULL != verifyData) {
341
U_8 *lookupSigData = J9UTF8_DATA(lookupSig);
342
U_32 sigOffset = 0;
343
344
while ('[' == lookupSigData[sigOffset]) {
345
sigOffset += 1;
346
}
347
348
if ('L' == lookupSigData[sigOffset]) {
349
BOOLEAN isVirtual = (0 == (((J9ROMFieldShape*)romField)->modifiers & J9AccStatic));
350
j9object_t argsArray = J9VMJAVALANGINVOKEMETHODTYPE_PTYPES(currentThread, methodType);
351
U_32 numParameters = J9INDEXABLEOBJECT_SIZE(currentThread, argsArray);
352
j9object_t clazz = NULL;
353
J9Class *ramClass = NULL;
354
J9ClassLoader *targetClassloader = lookupClass->classLoader;
355
356
/* Move past the L in the Lfoo; signature */
357
sigOffset += 1;
358
359
/* '()X' or '(Receiver)X' are both getters. All others are setters */
360
if (((0 == numParameters) && !isVirtual) || ((1 == numParameters) && isVirtual)) {
361
clazz = J9VMJAVALANGINVOKEMETHODTYPE_RTYPE(currentThread, methodType);
362
} else {
363
U_32 argumentIndex = 0;
364
365
if (isVirtual) {
366
argumentIndex = 1;
367
}
368
369
clazz = J9JAVAARRAYOFOBJECT_LOAD(currentThread, argsArray, argumentIndex);
370
}
371
372
ramClass = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, clazz);
373
if (ramClass->classLoader != targetClassloader) {
374
/* -1 on the length to remove the ; and the end of the signature */
375
U_32 sigLength = J9UTF8_LENGTH(lookupSig) - sigOffset - 1;
376
377
omrthread_monitor_enter(vm->classTableMutex);
378
if(verifyData->checkClassLoadingConstraintForNameFunction(currentThread, targetClassloader, ramClass->classLoader, &lookupSigData[sigOffset], &lookupSigData[sigOffset], sigLength, TRUE) != 0) {
379
result = FALSE;
380
}
381
omrthread_monitor_exit(vm->classTableMutex);
382
}
383
}
384
}
385
return result;
386
}
387
388
static BOOLEAN
389
accessCheckMethodSignature(J9VMThread *currentThread, J9Method *method, j9object_t methodType, J9UTF8 *lookupSig)
390
{
391
J9JavaVM *vm = currentThread->javaVM;
392
J9BytecodeVerificationData *verifyData = vm->bytecodeVerificationData;
393
BOOLEAN result = TRUE;
394
395
/* If the verifier isn't enabled, accept the check unconditionally */
396
if (NULL != verifyData) {
397
U_8 *lookupSigData = J9UTF8_DATA(lookupSig);
398
/* Grab the args array and length from MethodType.arguments */
399
j9object_t argsArray = J9VMJAVALANGINVOKEMETHODTYPE_PTYPES(currentThread, methodType);
400
j9object_t clazz = NULL;
401
J9Class *methodRamClass = J9_CLASS_FROM_METHOD(method);
402
J9ClassLoader *targetClassloader = methodRamClass->classLoader;
403
J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);
404
J9UTF8 *targetSig = J9ROMMETHOD_SIGNATURE(romMethod);
405
U_32 numParameters = J9INDEXABLEOBJECT_SIZE(currentThread, argsArray);
406
U_32 i = 0;
407
U_32 index = 0;
408
U_32 endIndex = 0;
409
U_32 start = 0;
410
411
/* For virtual methods we need to skip the first parameter in the MethodType parameter array */
412
if (0 == (romMethod->modifiers & J9AccStatic)) {
413
J9UTF8 *targetName = J9ROMMETHOD_NAME(romMethod);
414
if ('<' != J9UTF8_DATA(targetName)[0]) {
415
/* ensure the method is not a constructor which has a name <init> */
416
start = 1;
417
}
418
}
419
420
/* checkClassLoadingConstraintForNameFunction requires this mutex to be locked */
421
omrthread_monitor_enter(vm->classTableMutex);
422
for (i = start; i < numParameters; i++) {
423
J9Class *argumentRamClass = NULL;
424
425
/* Advance the text pointer to the next argument */
426
index += 1;
427
428
/* If this entry is an array, index forward */
429
while ('[' == lookupSigData[index]) {
430
index += 1;
431
}
432
433
endIndex = index;
434
435
/* If this entry is a class type, we need to do a classloader check on it */
436
if ('L' == lookupSigData[index]) {
437
index += 1;
438
439
clazz = J9JAVAARRAYOFOBJECT_LOAD(currentThread, argsArray, i);
440
argumentRamClass = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, clazz);
441
442
while (';' != lookupSigData[endIndex]) {
443
endIndex += 1;
444
}
445
446
/* Check if we really need to check this classloader constraint */
447
if (argumentRamClass->classLoader != targetClassloader) {
448
if(verifyData->checkClassLoadingConstraintForNameFunction(currentThread, targetClassloader, argumentRamClass->classLoader, &J9UTF8_DATA(targetSig)[index], &lookupSigData[index], endIndex - index, TRUE) != 0) {
449
result = FALSE;
450
goto releaseMutexAndReturn;
451
}
452
}
453
454
index = endIndex;
455
}
456
}
457
458
/* Skip past the ) at the end of the signature, plus 1 to get to the next entry */
459
index += 2;
460
461
/* Check the return type. If it's an array, get to the actual type */
462
while ('[' == lookupSigData[index]) {
463
index += 1;
464
}
465
if('L' == lookupSigData[index]) {
466
J9Class *returnRamClass = NULL;
467
/* Grab the MethodType returnType */
468
clazz = J9VMJAVALANGINVOKEMETHODTYPE_RTYPE(currentThread, methodType);
469
returnRamClass = J9VM_J9CLASS_FROM_HEAPCLASS(currentThread, clazz);
470
471
/* Check if we really need to check this classloader constraint */
472
if (targetClassloader != returnRamClass->classLoader) {
473
endIndex = index;
474
index++;
475
476
while (';' != lookupSigData[endIndex]) {
477
endIndex++;
478
}
479
480
if(verifyData->checkClassLoadingConstraintForNameFunction(currentThread, targetClassloader, returnRamClass->classLoader, &J9UTF8_DATA(targetSig)[index], &lookupSigData[index], endIndex - index, TRUE) != 0) {
481
result = FALSE;
482
goto releaseMutexAndReturn;
483
}
484
}
485
}
486
487
releaseMutexAndReturn:
488
omrthread_monitor_exit(vm->classTableMutex);
489
}
490
491
return result;
492
}
493
494
/* Should already have VMAccess */
495
UDATA
496
lookupField(JNIEnv *env, jboolean isStatic, J9Class *j9LookupClass, jstring name, J9UTF8 *sigUTF, J9Class **definingClass, UDATA *romField, jclass accessClass)
497
{
498
J9UTF8 *nameUTF8 = NULL;
499
char nameUTF8Buffer[256];
500
J9Class *j9AccessClass = NULL; /* J9Class for java.lang.Class accessClass */
501
UDATA field = 0;
502
J9VMThread *vmThread = (J9VMThread *) env;
503
J9JavaVM *vm = vmThread->javaVM;
504
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
505
PORT_ACCESS_FROM_VMC(vmThread);
506
507
nameUTF8 = vmFuncs->copyStringToJ9UTF8WithMemAlloc(vmThread, J9_JNI_UNWRAP_REFERENCE(name), J9_STR_NONE, "", 0, nameUTF8Buffer, sizeof(nameUTF8Buffer));
508
509
if (NULL == nameUTF8) {
510
vmFuncs->setNativeOutOfMemoryError(vmThread, 0, 0);
511
Assert_JCL_notNull(vmThread->currentException);
512
goto _cleanup;
513
}
514
515
if (NULL != accessClass) {
516
j9AccessClass = J9VM_J9CLASS_FROM_JCLASS(vmThread, accessClass);
517
}
518
519
if (JNI_TRUE == isStatic) {
520
field = (UDATA) vmFuncs->staticFieldAddress(vmThread, j9LookupClass, J9UTF8_DATA(nameUTF8), J9UTF8_LENGTH(nameUTF8), J9UTF8_DATA(sigUTF), J9UTF8_LENGTH(sigUTF), definingClass, romField, 0, j9AccessClass);
521
if (0 == field) {
522
/* IllegalAccessError / IncompatibleClassChangeError / NoSuchFieldError will be pending */
523
Assert_JCL_notNull(vmThread->currentException);
524
goto _cleanup;
525
}
526
/* Turn field into an offset that is usable by Unsafe to support
527
* the JIT implementation of static Field handles
528
*/
529
field = (UDATA) field - (UDATA) (*definingClass)->ramStatics;
530
field += J9_SUN_STATIC_FIELD_OFFSET_TAG;
531
} else {
532
field = (UDATA) vmFuncs->instanceFieldOffset(vmThread, j9LookupClass, J9UTF8_DATA(nameUTF8), J9UTF8_LENGTH(nameUTF8), J9UTF8_DATA(sigUTF), J9UTF8_LENGTH(sigUTF), definingClass, romField, 0);
533
if (-1 == field) {
534
/* IllegalAccessError / IncompatibleClassChangeError / NoSuchFieldError will be pending */
535
Assert_JCL_notNull(vmThread->currentException);
536
goto _cleanup;
537
}
538
}
539
540
/* definingClass & romField cannot be null here. The field lookup would have failed if they were null and
541
* would have done a goto _cleanup.
542
*/
543
Assert_JCL_notNull(*definingClass);
544
Assert_JCL_notNull((J9ROMFieldShape *)(*romField));
545
546
_cleanup:
547
548
if (nameUTF8 != (J9UTF8*)nameUTF8Buffer) {
549
j9mem_free_memory(nameUTF8);
550
}
551
552
return field;
553
}
554
555
jclass JNICALL
556
Java_java_lang_invoke_PrimitiveHandle_lookupField(JNIEnv *env, jobject handle, jclass lookupClass, jstring name, jstring signature, jboolean isStatic, jclass accessClass)
557
{
558
J9UTF8 *signatureUTF8 = NULL;
559
char signatureUTF8Buffer[256];
560
J9Class *j9LookupClass = NULL; /* J9Class for java.lang.Class lookupClass */
561
J9Class *definingClass = NULL; /* Returned by calls to find field */
562
UDATA field = 0;
563
jclass result = NULL;
564
UDATA romField = 0;
565
J9VMThread *vmThread = (J9VMThread *) env;
566
J9JavaVM *vm = vmThread->javaVM;
567
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
568
PORT_ACCESS_FROM_ENV(env);
569
570
vmFuncs->internalEnterVMFromJNI(vmThread);
571
572
signatureUTF8 = vmFuncs->copyStringToJ9UTF8WithMemAlloc(vmThread, J9_JNI_UNWRAP_REFERENCE(signature), J9_STR_NONE, "", 0, signatureUTF8Buffer, sizeof(signatureUTF8Buffer));
573
574
if (signatureUTF8 == NULL) {
575
vmFuncs->setNativeOutOfMemoryError(vmThread, 0, 0);
576
Assert_JCL_notNull(vmThread->currentException);
577
goto _cleanup;
578
}
579
580
j9LookupClass = J9VM_J9CLASS_FROM_JCLASS(vmThread, lookupClass);
581
582
field = lookupField(env, isStatic, j9LookupClass, name, signatureUTF8, &definingClass, &romField, accessClass);
583
584
if (NULL != vmThread->currentException) {
585
goto _cleanup;
586
}
587
588
/* Check signature for classloader visibility */
589
if (!accessCheckFieldSignature(vmThread, j9LookupClass, romField, J9VMJAVALANGINVOKEMETHODHANDLE_TYPE(vmThread, J9_JNI_UNWRAP_REFERENCE(handle)), signatureUTF8)) {
590
setClassLoadingConstraintLinkageError(vmThread, definingClass, signatureUTF8);
591
goto _cleanup;
592
}
593
if (NULL != accessClass) {
594
J9Class *j9AccessClass = J9VM_J9CLASS_FROM_JCLASS(vmThread, accessClass);
595
if ((j9AccessClass->classLoader != j9LookupClass->classLoader)
596
&& !accessCheckFieldSignature(vmThread, j9AccessClass, romField, J9VMJAVALANGINVOKEMETHODHANDLE_TYPE(vmThread, J9_JNI_UNWRAP_REFERENCE(handle)), signatureUTF8)
597
) {
598
setClassLoadingConstraintLinkageError(vmThread, j9AccessClass, signatureUTF8);
599
goto _cleanup;
600
}
601
}
602
603
J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_VMSLOT(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), field);
604
J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_RAWMODIFIERS(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), ((J9ROMFieldShape*) romField)->modifiers);
605
result = vmFuncs->j9jni_createLocalRef(env, J9VM_J9CLASS_TO_HEAPCLASS(definingClass));
606
607
_cleanup:
608
vmFuncs->internalExitVMToJNI(vmThread);
609
610
if (signatureUTF8 != (J9UTF8*)signatureUTF8Buffer) {
611
j9mem_free_memory(signatureUTF8);
612
}
613
614
return result;
615
}
616
617
618
jboolean JNICALL
619
Java_java_lang_invoke_PrimitiveHandle_setVMSlotAndRawModifiersFromField(JNIEnv *env, jclass clazz, jobject handle, jobject reflectField)
620
{
621
J9VMThread *vmThread = (J9VMThread *) env;
622
J9JavaVM *vm = vmThread->javaVM;
623
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
624
J9ReflectFunctionTable *reflectFunctions = &(vm->reflectFunctions);
625
J9JNIFieldID *fieldID;
626
jboolean result = JNI_FALSE;
627
j9object_t fieldObject;
628
UDATA fieldOffset;
629
630
vmFuncs->internalEnterVMFromJNI(vmThread);
631
/* Can't fail as we know the field is not null */
632
fieldObject = J9_JNI_UNWRAP_REFERENCE(reflectField);
633
fieldID = reflectFunctions->idFromFieldObject(vmThread, NULL, fieldObject);
634
635
fieldOffset = fieldID->offset;
636
if (J9AccStatic == (fieldID->field->modifiers & J9AccStatic)) {
637
/* ensure this is correctly tagged so that the JIT targets using Unsafe will correctly detect this is static */
638
fieldOffset |= J9_SUN_STATIC_FIELD_OFFSET_TAG;
639
}
640
641
642
J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_VMSLOT(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), fieldOffset);
643
J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_RAWMODIFIERS(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), fieldID->field->modifiers);
644
result = JNI_TRUE;
645
646
vmFuncs->internalExitVMToJNI(vmThread);
647
return result;
648
}
649
650
651
jboolean JNICALL
652
Java_java_lang_invoke_PrimitiveHandle_setVMSlotAndRawModifiersFromMethod(JNIEnv *env, jclass clazz, jobject handle, jclass unused, jobject method, jbyte kind, jclass specialToken)
653
{
654
J9VMThread *vmThread = (J9VMThread *) env;
655
J9JavaVM *vm = vmThread->javaVM;
656
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
657
J9ReflectFunctionTable *reflectFunctions = &(vm->reflectFunctions);
658
J9JNIMethodID *methodID;
659
J9Class *j9SpecialToken = NULL;
660
jboolean result = JNI_FALSE;
661
UDATA vmSlotValue;
662
j9object_t methodObject;
663
U_32 modifiers;
664
665
vmFuncs->internalEnterVMFromJNI(vmThread);
666
if (specialToken != NULL) {
667
j9SpecialToken = J9VM_J9CLASS_FROM_JCLASS(vmThread, specialToken);
668
}
669
/* Can't fail as we know the method is not null */
670
methodObject = J9_JNI_UNWRAP_REFERENCE(method);
671
methodID = reflectFunctions->idFromMethodObject(vmThread, methodObject);
672
modifiers = J9_ROM_METHOD_FROM_RAM_METHOD(methodID->method)->modifiers;
673
674
switch(kind){
675
case J9_METHOD_HANDLE_KIND_STATIC:
676
vmSlotValue = (UDATA) methodID->method;
677
break;
678
case J9_METHOD_HANDLE_KIND_VIRTUAL:
679
vmSlotValue = methodID->vTableIndex;
680
break;
681
case J9_METHOD_HANDLE_KIND_INTERFACE:
682
Assert_JCL_true(J9_ARE_ANY_BITS_SET(methodID->vTableIndex, J9_JNI_MID_INTERFACE));
683
vmSlotValue = methodID->vTableIndex & ~J9_JNI_MID_INTERFACE;
684
break;
685
case J9_METHOD_HANDLE_KIND_SPECIAL:
686
if (specialToken == NULL) {
687
goto _cleanup;
688
}
689
if ((J9AccMethodVTable != (modifiers & J9AccMethodVTable))) {
690
/* Handle methods which aren't in the VTable, such as private methods and Object.getClass */
691
vmSlotValue = (UDATA) methodID->method;
692
} else {
693
vmSlotValue = (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);
694
Assert_JCL_true(0 != vmSlotValue);
695
}
696
break;
697
default:
698
/* Assert here - illegal should never be called with something that doesn't directly map to kind */
699
Assert_JCL_unreachable();
700
goto _cleanup;
701
}
702
703
J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_VMSLOT(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), vmSlotValue);
704
J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_RAWMODIFIERS(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), modifiers);
705
706
result = JNI_TRUE;
707
708
_cleanup:
709
vmFuncs->internalExitVMToJNI(vmThread);
710
711
return result;
712
}
713
714
jboolean JNICALL
715
Java_java_lang_invoke_PrimitiveHandle_setVMSlotAndRawModifiersFromConstructor(JNIEnv *env, jclass clazz, jobject handle, jobject ctor)
716
{
717
J9VMThread *vmThread = (J9VMThread *) env;
718
J9JavaVM *vm = vmThread->javaVM;
719
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
720
J9ReflectFunctionTable *reflectFunctions = &(vm->reflectFunctions);
721
J9JNIMethodID *methodID;
722
jboolean result = JNI_FALSE;
723
j9object_t methodObject;
724
725
vmFuncs->internalEnterVMFromJNI(vmThread);
726
/* Can't fail as we know the method is not null */
727
methodObject = J9_JNI_UNWRAP_REFERENCE(ctor);
728
methodID = reflectFunctions->idFromConstructorObject(vmThread, methodObject);
729
730
J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_VMSLOT(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), (UDATA)methodID->method);
731
J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_RAWMODIFIERS(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), J9_ROM_METHOD_FROM_RAM_METHOD(methodID->method)->modifiers);
732
733
result = JNI_TRUE;
734
735
vmFuncs->internalExitVMToJNI(vmThread);
736
return result;
737
}
738
739
/**
740
* Assign the vmSlot for a VirtualHandle when given a DirectHandle that is of KIND_SPECIAL.
741
* This method does no access checking as the access checks should have occurred when creating
742
* the SpecialHandle.
743
*/
744
jboolean JNICALL
745
Java_java_lang_invoke_PrimitiveHandle_setVMSlotAndRawModifiersFromSpecialHandle(JNIEnv *env, jclass clazz, jobject handle, jobject specialHandle)
746
{
747
J9VMThread *vmThread = (J9VMThread *) env;
748
J9JavaVM *vm = vmThread->javaVM;
749
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
750
jboolean result = JNI_FALSE;
751
UDATA vtableOffset;
752
j9object_t specialHandleObject;
753
J9Method *method;
754
j9object_t classObject;
755
J9Class *j9class;
756
757
vmFuncs->internalEnterVMFromJNI(vmThread);
758
specialHandleObject = J9_JNI_UNWRAP_REFERENCE(specialHandle);
759
760
method = (J9Method *)(UDATA) J9VMJAVALANGINVOKEPRIMITIVEHANDLE_VMSLOT(vmThread, specialHandleObject);
761
classObject = (j9object_t) J9VMJAVALANGINVOKEPRIMITIVEHANDLE_REFERENCECLASS(vmThread, specialHandleObject);
762
if ((method == NULL) || (classObject == NULL)) {
763
goto _done;
764
}
765
j9class = J9VM_J9CLASS_FROM_HEAPCLASS(vmThread, classObject);
766
if (j9class == NULL) {
767
goto _done;
768
}
769
vtableOffset = vmFuncs->getVTableOffsetForMethod(method, j9class, vmThread);
770
if (vtableOffset != 0) {
771
J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_VMSLOT(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), vtableOffset);
772
J9VMJAVALANGINVOKEPRIMITIVEHANDLE_SET_RAWMODIFIERS(vmThread, J9_JNI_UNWRAP_REFERENCE(handle), J9_ROM_METHOD_FROM_RAM_METHOD(method)->modifiers);
773
result = JNI_TRUE;
774
}
775
776
_done:
777
vmFuncs->internalExitVMToJNI(vmThread);
778
return result;
779
}
780
781
/* Return the field offset of the 'vmRef' field in j.l.Class.
782
* Needed by the JIT in MethodHandle's static initializer before Unsafe
783
* can be loaded. The 'ignored' parameter is to work around a javac bug.
784
*/
785
jint JNICALL
786
Java_java_lang_invoke_MethodHandle_vmRefFieldOffset(JNIEnv *env, jclass clazz, jclass ignored)
787
{
788
return (jint) J9VMJAVALANGCLASS_VMREF_OFFSET(((J9VMThread *) env));
789
}
790
791
#ifdef J9VM_OPT_PANAMA
792
jlong JNICALL
793
Java_java_lang_invoke_MethodHandles_findNativeAddress(JNIEnv *env, jclass jlClass, jstring methodName)
794
{
795
const char *nativeMethodName = NULL;
796
UDATA handle = 0;
797
jlong func = 0;
798
PORT_ACCESS_FROM_ENV(env);
799
800
nativeMethodName = (*env)->GetStringUTFChars(env, methodName, NULL);
801
802
if(0 == j9sl_open_shared_library(NULL, &handle, FALSE)) {
803
if(0 != j9sl_lookup_name(handle, (char *)nativeMethodName, (UDATA *)&func, "")){
804
func = 0;
805
}
806
}
807
808
return func;
809
}
810
#endif
811
812
void JNICALL
813
Java_java_lang_invoke_MutableCallSite_freeGlobalRef(JNIEnv *env, jclass mutableCallSite, jlong bypassOffset)
814
{
815
if (0 != bypassOffset) {
816
J9VMThread *vmThread = (J9VMThread *) env;
817
J9JavaVM *vm = vmThread->javaVM;
818
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
819
jobject globalRef = NULL;
820
821
vmFuncs->internalEnterVMFromJNI(vmThread);
822
globalRef = (jobject)((UDATA)J9VM_J9CLASS_FROM_HEAPCLASS(vmThread, J9_JNI_UNWRAP_REFERENCE(mutableCallSite))->ramStatics + ((UDATA)bypassOffset & ~(UDATA)J9_SUN_FIELD_OFFSET_MASK));
823
vmFuncs->j9jni_deleteGlobalRef(env, globalRef, FALSE);
824
vmFuncs->internalExitVMToJNI(vmThread);
825
}
826
return;
827
}
828
829
void JNICALL
830
Java_java_lang_invoke_ThunkTuple_registerNatives(JNIEnv *env, jclass nativeClass)
831
{
832
JNINativeMethod natives[] = {
833
{
834
"initialInvokeExactThunk",
835
"()J",
836
(void *)&vmInitialInvokeExactThunk
837
}
838
};
839
JNINativeMethod finalizeNative[] = {
840
{
841
"finalizeImpl",
842
"(J)V",
843
(void *)&vmFinalizeImpl
844
}
845
};
846
847
registerVMNativesIfNoJIT(env, nativeClass, natives, 1);
848
849
/* Always register this native - JIT may provide an implementation later.
850
* This is just a hook that will allow them to override the native if
851
* the code cache leaking is an issue.
852
*/
853
(*env)->RegisterNatives(env, nativeClass, finalizeNative, 1);
854
#if defined(J9VM_OPT_JAVA_OFFLOAD_SUPPORT)
855
/* Jazz 99339: Given that the non-zAAP eligible bit is set in RegisterNatives(),
856
* we need to clear the bit here for JCL natives to allow them to run on zAAP.
857
*/
858
clearNonZAAPEligibleBit(env, nativeClass, finalizeNative, 1);
859
#endif /* J9VM_OPT_JAVA_OFFLOAD_SUPPORT */
860
861
return;
862
}
863
864
865
void JNICALL
866
Java_java_lang_invoke_MutableCallSite_registerNatives(JNIEnv *env, jclass nativeClass)
867
{
868
JNINativeMethod natives[] = {
869
{
870
"invalidate",
871
"([J)V",
872
(void *)&vmInvalidate
873
}
874
};
875
registerVMNativesIfNoJIT(env, nativeClass, natives, 1);
876
return;
877
}
878
879
880
void JNICALL
881
Java_java_lang_invoke_InterfaceHandle_registerNatives(JNIEnv *env, jclass nativeClass)
882
{
883
JNINativeMethod natives[] = {
884
{
885
"convertITableIndexToVTableIndex",
886
"(JIJ)I",
887
(void *)&vmConvertITableIndexToVTableIndex
888
}
889
};
890
registerVMNativesIfNoJIT(env, nativeClass, natives, 1);
891
return;
892
}
893
894
/*
895
* Helper function to register vm versions of native methods if the jitconfig is null.
896
*/
897
static void
898
registerVMNativesIfNoJIT(JNIEnv *env, jclass nativeClass, JNINativeMethod *natives, jint numNatives)
899
{
900
J9VMThread *vmThread = (J9VMThread *) env;
901
902
if (NULL == vmThread->javaVM->jitConfig) {
903
(*env)->RegisterNatives(env, nativeClass, natives, numNatives);
904
#if defined(J9VM_OPT_JAVA_OFFLOAD_SUPPORT)
905
/* Jazz 99339: Given that the non-zAAP eligible bit is set in RegisterNatives(),
906
* we need to clear the bit here for JCL natives to allow them to run on zAAP.
907
*/
908
clearNonZAAPEligibleBit(env, nativeClass, natives, numNatives);
909
#endif /* J9VM_OPT_JAVA_OFFLOAD_SUPPORT */
910
}
911
912
return;
913
}
914
915
static void JNICALL
916
vmInvalidate(JNIEnv *env, jclass mutableCallSiteClass, jlongArray cookies)
917
{
918
/* No op - this native is supplied by the JIT dll when the jit is enabled.
919
* This is just a dummy native to prevent LinkageErrors when running Xint.
920
*/
921
return;
922
}
923
924
static jlong JNICALL
925
vmInitialInvokeExactThunk(JNIEnv *env, jclass ignored)
926
{
927
return 0;
928
}
929
930
static jlong JNICALL
931
vmConvertITableIndexToVTableIndex(JNIEnv *env, jclass InterfaceMethodHandle, jlong interfaceArg, jint itableIndex, jlong receiverClassArg)
932
{
933
return 0;
934
}
935
936
static void JNICALL
937
vmFinalizeImpl(JNIEnv *env, jclass methodHandleClass, jlong thunkAddress)
938
{
939
return;
940
}
941
942
/**
943
* Fill in a parameterized NLS message.
944
*
945
* Does not require VM access.
946
*
947
* @param[in] vmThread The current VM thread.
948
* @param[in] nlsTemplate A parameterized NLS message, as returned from j9nls_lookup_message().
949
* @return An allocated buffer containing the expanded NLS message. Caller must free this
950
* buffer using j9mem_free_memory().
951
*/
952
static char *
953
expandNLSTemplate(J9VMThread *vmThread, const char *nlsTemplate, ...)
954
{
955
PORT_ACCESS_FROM_VMC(vmThread);
956
char *msg = NULL;
957
958
if (NULL != nlsTemplate) {
959
UDATA msgLen = 0;
960
va_list args;
961
962
va_start(args, nlsTemplate);
963
msgLen = j9str_vprintf(NULL, 0, nlsTemplate, args);
964
va_end(args);
965
966
msg = (char *)j9mem_allocate_memory(msgLen, OMRMEM_CATEGORY_VM);
967
if (NULL != msg) {
968
va_start(args, nlsTemplate);
969
j9str_vprintf(msg, msgLen, nlsTemplate, args);
970
va_end(args);
971
}
972
}
973
return msg;
974
}
975
976
/**
977
* Set a LinkageError to indicate a class loading constraint violation between
978
* the MT and the looked up method or field.
979
*
980
* @param[in] vmThread The current J9VMThread *
981
* @param[in] methodOrFieldClass The defining class of the looked up field or method
982
* @param[in] signatureUTF8 The signature of the MethodType
983
*/
984
void
985
setClassLoadingConstraintLinkageError(J9VMThread *vmThread, J9Class *methodOrFieldClass, J9UTF8 *signatureUTF8)
986
{
987
J9JavaVM *vm = vmThread->javaVM;
988
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
989
PORT_ACCESS_FROM_VMC(vmThread);
990
J9UTF8 *className = J9ROMCLASS_CLASSNAME(methodOrFieldClass->romClass);
991
const char *nlsTemplate = j9nls_lookup_message(
992
J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE,
993
J9NLS_JCL_METHODTYPE_CLASS_LOADING_CONSTRAINT,
994
"loading constraint violation: %.*s not visible from %.*s");
995
char * msg = expandNLSTemplate(
996
vmThread,
997
nlsTemplate,
998
J9UTF8_LENGTH(signatureUTF8), J9UTF8_DATA(signatureUTF8),
999
J9UTF8_LENGTH(className), J9UTF8_DATA(className));
1000
vmFuncs->setCurrentExceptionUTF(vmThread, J9VMCONSTANTPOOL_JAVALANGLINKAGEERROR, msg);
1001
j9mem_free_memory(msg);
1002
}
1003
1004
#if defined(J9VM_OPT_JAVA_OFFLOAD_SUPPORT)
1005
/**
1006
* Clear the non-ZAAP eligible bit for JCL natives to allow them to run on zAAP.
1007
*
1008
* @param[in] env The JNI interface pointer
1009
* @param[in] nativeClass The class containing the native method
1010
* @param[in] nativeMethods The JNI native method pointer
1011
* @param[in] nativeMethodCount The count of native methods
1012
*/
1013
void
1014
clearNonZAAPEligibleBit(JNIEnv *env, jclass nativeClass, const JNINativeMethod *nativeMethods, jint nativeMethodCount)
1015
{
1016
J9VMThread *vmThread = (J9VMThread *) env;
1017
J9JavaVM *vm = vmThread->javaVM;
1018
J9InternalVMFunctions* vmFuncs = vm->internalVMFunctions;
1019
const JNINativeMethod *nativeMethod = nativeMethods;
1020
jint count = nativeMethodCount;
1021
J9Class *j9clazz = NULL;
1022
1023
vmFuncs->internalEnterVMFromJNI(vmThread);
1024
j9clazz = J9VM_J9CLASS_FROM_HEAPCLASS(vmThread, J9_JNI_UNWRAP_REFERENCE(nativeClass));
1025
1026
while (0 < count) {
1027
J9Method *jniMethod = vmFuncs->findJNIMethod(vmThread, j9clazz, nativeMethod->name, nativeMethod->signature);
1028
vmFuncs->atomicAndIntoConstantPool(vm, jniMethod, ~(UDATA)J9_STARTPC_NATIVE_REQUIRES_SWITCHING);
1029
count -= 1;
1030
nativeMethod +=1;
1031
}
1032
vmFuncs->internalExitVMToJNI(vmThread);
1033
}
1034
#endif /* J9VM_OPT_JAVA_OFFLOAD_SUPPORT */
1035
1036
#if JAVA_SPEC_VERSION >= 15
1037
void JNICALL
1038
Java_java_lang_invoke_MethodHandleNatives_checkClassBytes(JNIEnv *env, jclass jlClass, jbyteArray classRep)
1039
{
1040
J9VMThread *currentThread = (J9VMThread *)env;
1041
J9JavaVM *vm = currentThread->javaVM;
1042
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
1043
jsize length = 0;
1044
U_8* classBytes = NULL;
1045
I_32 rc = 0;
1046
U_8* segment = NULL;
1047
U_32 segmentLength = 0;
1048
PORT_ACCESS_FROM_JAVAVM(vm);
1049
1050
if (NULL == classRep) {
1051
throwNewNullPointerException(env, NULL);
1052
goto done;
1053
}
1054
length = (*env)->GetArrayLength(env, classRep);
1055
if (0 == length) {
1056
goto done;
1057
}
1058
1059
segmentLength = ESTIMATE_SIZE(length);
1060
segment = (U_8*)j9mem_allocate_memory(segmentLength, J9MEM_CATEGORY_VM_JCL);
1061
if (NULL == segment) {
1062
vmFuncs->setNativeOutOfMemoryError(currentThread, 0, 0);
1063
goto done;
1064
}
1065
memset(segment, 0, segmentLength);
1066
classBytes = (*env)->GetPrimitiveArrayCritical(env, classRep, NULL);
1067
1068
rc = vmFuncs->checkClassBytes(currentThread, classBytes, length, segment, segmentLength);
1069
(*env)->ReleasePrimitiveArrayCritical(env, classRep, classBytes, 0);
1070
if (0 != rc) {
1071
J9CfrError *cfrError = (J9CfrError *)segment;
1072
const char* errorMsg = OMRPORT_FROM_J9PORT(PORTLIB)->nls_lookup_message(OMRPORT_FROM_J9PORT(PORTLIB), J9NLS_DO_NOT_APPEND_NEWLINE, cfrError->errorCatalog, cfrError->errorCode, NULL);
1073
vmFuncs->internalEnterVMFromJNI(currentThread);
1074
vmFuncs->setCurrentExceptionUTF(currentThread, cfrError->errorAction, errorMsg);
1075
vmFuncs->internalExitVMToJNI(currentThread);
1076
}
1077
j9mem_free_memory(segment);
1078
done:
1079
return;
1080
}
1081
#endif /* JAVA_SPEC_VERSION >= 15 */
1082
1083