Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/j9vm31/jniinv.cpp
5985 views
1
/*******************************************************************************
2
* Copyright (c) 2021, 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 "j9vm31.h"
24
#include "omrcomp.h"
25
26
extern "C" {
27
28
/* Given LE supports only one TCB that can cross AMODE boundary, most likely
29
* we will only have 1 JavaVM in the address space. Simply use a static to
30
* track the live JavaVM31 instances.
31
*/
32
static JavaVM31* globalRootJavaVM31 = NULL;
33
34
static void initializeJavaVM31(JavaVM31 * JavaVM31, jlong JavaVM64);
35
static void freeJavaVM31(JavaVM31 * JavaVM31);
36
37
/* This is the function table of the 31-bit shim JNIInvokeInterface functions. */
38
struct JNIInvokeInterface_ EsJNIInvokeFunctions = {
39
NULL,
40
NULL,
41
NULL,
42
DestroyJavaVM,
43
AttachCurrentThread,
44
DetachCurrentThread,
45
GetEnv,
46
AttachCurrentThreadAsDaemon,
47
};
48
49
jint JNICALL
50
JNI_GetDefaultJavaVMInitArgs(void * vm_args)
51
{
52
/* Zero out the JavaVMInitArgs reserved / padding fields. */
53
JavaVMInitArgs *javaInitArgs = ((JavaVMInitArgs *) vm_args);
54
if (NULL != javaInitArgs) {
55
javaInitArgs->reservedOptionsPadding = NULL;
56
javaInitArgs->reservedAlignmentPadding = NULL;
57
58
for (int32_t i = 0; i < javaInitArgs->nOptions; i++) {
59
javaInitArgs->options[i].reservedOptionStringPadding = NULL;
60
javaInitArgs->options[i].reservedExtraInfoPadding = NULL;
61
}
62
}
63
64
const jint NUM_ARGS = 1;
65
J9_CEL4RO64_ArgType argTypes[NUM_ARGS] = { CEL4RO64_type_uint32_ptr };
66
uint64_t argValues[NUM_ARGS] = { (uint64_t)vm_args };
67
jint returnValue = JNI_ERR;
68
uint32_t cel4ro64ReturnCode = j9_cel4ro64_load_query_call_function(
69
LIBJVM_NAME, "JNI_GetDefaultJavaVMInitArgs",
70
argTypes, argValues, NUM_ARGS, CEL4RO64_type_jint, &returnValue);
71
72
if (J9_CEL4RO64_RETCODE_OK != cel4ro64ReturnCode) {
73
fprintf(stderr, "JNI_GetDefaultJavaVMInitArgs failed. CEL4RO64 rc: %d - %s\n", cel4ro64ReturnCode, j9_cel4ro64_get_error_message(cel4ro64ReturnCode));
74
return JNI_ERR;
75
}
76
return returnValue;
77
}
78
79
jint JNICALL
80
JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *vm_args)
81
{
82
uint64_t JavaVM64Result = 0;
83
uint64_t JNIEnv64Result = 0;
84
85
/* Zero out the JavaVMInitArgs reserved / padding fields. */
86
JavaVMInitArgs *javaInitArgs = ((JavaVMInitArgs *) vm_args);
87
if (NULL != javaInitArgs) {
88
javaInitArgs->reservedOptionsPadding = NULL;
89
javaInitArgs->reservedAlignmentPadding = NULL;
90
91
for (int32_t i = 0; i < javaInitArgs->nOptions; i++) {
92
javaInitArgs->options[i].reservedOptionStringPadding = NULL;
93
javaInitArgs->options[i].reservedExtraInfoPadding = NULL;
94
95
/* Abort, Exit and vsprintf hooks may be specified, in which
96
* case, we need to high tag the AMODE31 functions.
97
*/
98
if (NULL != javaInitArgs->options[i].extraInfo) {
99
/* extraInfo may have been stale garbage, so need to compare string. */
100
char *optionString = javaInitArgs->options[i].optionString;
101
if (NULL != optionString)
102
/* Have to do the string comparisons in CCSID 1208 - UTF-8. */
103
#pragma convert(1208)
104
if (0 == strncmp(optionString, "abort", strlen("abort"))) {
105
javaInitArgs->options[i].reservedExtraInfoPadding = (void *)HANDLE31_HIGHTAG;
106
} else if (0 == strncmp(optionString, "exit", strlen("exit"))) {
107
javaInitArgs->options[i].reservedExtraInfoPadding = (void *)HANDLE31_HIGHTAG;
108
} else if (0 == strncmp(optionString, "vfprintf", strlen("vfprintf"))) {
109
javaInitArgs->options[i].reservedExtraInfoPadding = (void *)HANDLE31_HIGHTAG;
110
}
111
#pragma convert(pop)
112
}
113
}
114
}
115
116
const jint NUM_ARGS = 3;
117
J9_CEL4RO64_ArgType argTypes[NUM_ARGS] = { CEL4RO64_type_JavaVM64, CEL4RO64_type_JNIEnv64, CEL4RO64_type_uint32_ptr };
118
uint64_t argValues[NUM_ARGS] = { (uint64_t)&JavaVM64Result, (uint64_t)&JNIEnv64Result, (uint64_t)vm_args };
119
jint returnValue = JNI_ERR;
120
uint32_t cel4ro64ReturnCode = j9_cel4ro64_load_query_call_function(
121
LIBJVM_NAME, "JNI_CreateJavaVM",
122
argTypes, argValues, NUM_ARGS, CEL4RO64_type_jint, &returnValue);
123
124
if (J9_CEL4RO64_RETCODE_OK != cel4ro64ReturnCode) {
125
fprintf(stderr, "JNI_CreateJavaVM failed. CEL4RO64 rc: %d - %s\n", cel4ro64ReturnCode, j9_cel4ro64_get_error_message(cel4ro64ReturnCode));
126
return JNI_ERR;
127
}
128
129
if (JNI_OK == returnValue) {
130
/* Create and return the corresponding 31-bit instance of JavaVM and JNIEnv. */
131
JavaVM31* javaVM31 = getJavaVM31(JavaVM64Result);
132
*pvm = (JavaVM*) javaVM31;
133
JNIEnv31* jniEnv31 = getJNIEnv31(JNIEnv64Result);
134
*penv = (JNIEnv*) jniEnv31;
135
jniEnv31->javaVM31 = javaVM31;
136
}
137
return returnValue;
138
}
139
140
jint JNICALL
141
JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
142
{
143
const jint NUM_ARGS = 3;
144
J9_CEL4RO64_ArgType argTypes[NUM_ARGS] = { CEL4RO64_type_uint32_ptr, CEL4RO64_type_jsize, CEL4RO64_type_uint32_ptr };
145
146
/* Allocate a temporary buffer to store the returned JavaVM64 instances.
147
* Will copy the corresponding 31-bit JavaVM instanes to vmBuf if successful below.
148
*/
149
uint64_t *tempJavaVM64Buffer = (uint64_t *)malloc(sizeof(jlong) * bufLen);
150
if (NULL == tempJavaVM64Buffer) {
151
return JNI_ERR;
152
}
153
154
uint64_t argValues[NUM_ARGS] = { (uint64_t)tempJavaVM64Buffer, bufLen, (uint64_t)nVMs };
155
jint returnValue = JNI_ERR;
156
uint32_t cel4ro64ReturnCode = j9_cel4ro64_load_query_call_function(
157
LIBJVM_NAME, "JNI_GetCreatedJavaVMs",
158
argTypes, argValues, NUM_ARGS, CEL4RO64_type_jint, &returnValue);
159
160
if (J9_CEL4RO64_RETCODE_OK != cel4ro64ReturnCode) {
161
fprintf(stderr, "JNI_GetCreatedJavaVMs failed. CEL4RO64 rc: %d - %s\n", cel4ro64ReturnCode, j9_cel4ro64_get_error_message(cel4ro64ReturnCode));
162
returnValue = JNI_ERR;
163
}
164
165
/* On success, copy the corresponding 31-bit JavaVM instances to vmBuf. */
166
if (JNI_OK == returnValue) {
167
for (int32_t i = 0; i < *nVMs; i++) {
168
vmBuf[i] = (JavaVM*)getJavaVM31(tempJavaVM64Buffer[i]);
169
}
170
}
171
free(tempJavaVM64Buffer);
172
return returnValue;
173
}
174
175
jint JNICALL
176
DestroyJavaVM(JavaVM *vm)
177
{
178
const jint NUM_ARGS = 1;
179
J9_CEL4RO64_ArgType argTypes[NUM_ARGS] = { CEL4RO64_type_JavaVM64 };
180
uint64_t argValues[NUM_ARGS] = { JAVAVM64_FROM_JAVAVM31(vm)};
181
jint returnValue = JNI_ERR;
182
uint32_t cel4ro64ReturnCode = j9_cel4ro64_load_query_call_function(
183
LIBJ9VM29_NAME, "DestroyJavaVM",
184
argTypes, argValues, NUM_ARGS, CEL4RO64_type_jint, &returnValue);
185
186
if (J9_CEL4RO64_RETCODE_OK != cel4ro64ReturnCode) {
187
fprintf(stderr, "DestroyJavaVM failed. CEL4RO64 rc: %d - %s\n", cel4ro64ReturnCode, j9_cel4ro64_get_error_message(cel4ro64ReturnCode));
188
returnValue = JNI_ERR;
189
}
190
/* If successful, we will free our corresponding 31-bit JavaVM instance and matching 31-bit JNIEnv. */
191
if (JNI_OK == returnValue) {
192
freeJavaVM31((JavaVM31 *)vm);
193
}
194
return returnValue;
195
}
196
197
jint JNICALL
198
AttachCurrentThread(JavaVM *vm, void **penv, void *args)
199
{
200
/* The current LE CEL4RO31/64 support will only allow 1 TCB to cross the AMODE boundary. As such, we need to
201
* check the result of CEL4RO64 for error codes, and handle accordingly.
202
*/
203
const jint NUM_ARGS = 3;
204
uint64_t JNIEnv64Result = 0;
205
J9_CEL4RO64_ArgType argTypes[NUM_ARGS] = { CEL4RO64_type_JavaVM64, CEL4RO64_type_JNIEnv64, CEL4RO64_type_uint32_ptr };
206
uint64_t argValues[NUM_ARGS] = { JAVAVM64_FROM_JAVAVM31(vm), (uint64_t)&JNIEnv64Result, (uint64_t)args };
207
jint returnValue = JNI_ERR;
208
uint32_t cel4ro64ReturnCode = J9_CEL4RO64_RETCODE_OK;
209
210
/* Zero initialize reservedNamePadding in JavaVMAttachArgs. */
211
JavaVMAttachArgs *vmAttachArgs = ((JavaVMAttachArgs *) args);
212
if (NULL != vmAttachArgs) {
213
vmAttachArgs->reservedNamePadding = NULL;
214
}
215
216
cel4ro64ReturnCode = j9_cel4ro64_load_query_call_function(
217
LIBJ9VM29_NAME, "AttachCurrentThread",
218
argTypes, argValues, NUM_ARGS, CEL4RO64_type_jint, &returnValue);
219
220
if (J9_CEL4RO64_RETCODE_OK != cel4ro64ReturnCode) {
221
fprintf(stderr, "AttachCurrentThread failed. CEL4RO64 rc: %d - %s\n", cel4ro64ReturnCode, j9_cel4ro64_get_error_message(cel4ro64ReturnCode));
222
return JNI_ERR;
223
}
224
/* If successful, we will return the correponding 31-bit JNIEnv. */
225
if (JNI_OK == returnValue) {
226
JNIEnv31* jniEnv31 = getJNIEnv31(JNIEnv64Result);
227
jniEnv31->javaVM31 = (JavaVM31 *)vm;
228
*penv = (JavaVM *)jniEnv31;
229
}
230
return returnValue;
231
}
232
233
jint JNICALL
234
DetachCurrentThread(JavaVM *vm) {
235
/* The current LE CEL4RO31/64 support will only allow 1 TCB to cross the AMODE boundary. In theory,
236
* we should have attached before calling DetachCurrentThread, but will confirm CEL4RO64 return code.
237
*/
238
const jint NUM_ARGS = 1;
239
J9_CEL4RO64_ArgType argTypes[NUM_ARGS] = { CEL4RO64_type_JavaVM64 };
240
uint64_t argValues[NUM_ARGS] = { JAVAVM64_FROM_JAVAVM31(vm) };
241
jint returnValue = JNI_ERR;
242
uint32_t cel4ro64ReturnCode = j9_cel4ro64_load_query_call_function(
243
LIBJ9VM29_NAME, "DetachCurrentThread",
244
argTypes, argValues, NUM_ARGS, CEL4RO64_type_jint, &returnValue);
245
246
if (J9_CEL4RO64_RETCODE_OK != cel4ro64ReturnCode) {
247
fprintf(stderr, "DetachCurrentThread failed. CEL4RO64 rc: %d - %s\n", cel4ro64ReturnCode, j9_cel4ro64_get_error_message(cel4ro64ReturnCode));
248
return JNI_ERR;
249
}
250
return returnValue;
251
}
252
253
jint JNICALL
254
GetEnv(JavaVM *vm, void **penv, jint version)
255
{
256
const jint NUM_ARGS = 3;
257
uint64_t JNIEnv64Result = 0;
258
J9_CEL4RO64_ArgType argTypes[NUM_ARGS] = { CEL4RO64_type_JavaVM64, CEL4RO64_type_JNIEnv64, CEL4RO64_type_jint };
259
uint64_t argValues[NUM_ARGS] = { JAVAVM64_FROM_JAVAVM31(vm), (uint64_t)&JNIEnv64Result, version };
260
jint returnValue = JNI_ERR;
261
uint32_t cel4ro64ReturnCode = j9_cel4ro64_load_query_call_function(
262
LIBJ9VM29_NAME, "GetEnv",
263
argTypes, argValues, NUM_ARGS, CEL4RO64_type_jint, &returnValue);
264
265
if (J9_CEL4RO64_RETCODE_OK != cel4ro64ReturnCode) {
266
fprintf(stderr, "GetEnv failed. CEL4RO64 rc: %d - %s\n", cel4ro64ReturnCode, j9_cel4ro64_get_error_message(cel4ro64ReturnCode));
267
return JNI_ERR;
268
}
269
/* If successful, we will return the correponding 31-bit JNIEnv. */
270
if (JNI_OK == returnValue) {
271
JNIEnv31* jniEnv31 = getJNIEnv31(JNIEnv64Result);
272
jniEnv31->javaVM31 = (JavaVM31 *)vm;
273
*penv = (JavaVM *)jniEnv31;
274
}
275
return returnValue;
276
}
277
278
jint JNICALL
279
AttachCurrentThreadAsDaemon(JavaVM *vm, void **penv, void *args)
280
{
281
/* The current LE CEL4RO31/64 support will only allow 1 TCB to cross the AMODE boundary. As such, we need to
282
* check the result of CEL4RO64 for error codes, and handle accordingly.
283
*/
284
const jint NUM_ARGS = 3;
285
uint64_t JNIEnv64Result = 0;
286
J9_CEL4RO64_ArgType argTypes[NUM_ARGS] = { CEL4RO64_type_JavaVM64, CEL4RO64_type_JNIEnv64, CEL4RO64_type_uint32_ptr };
287
uint64_t argValues[NUM_ARGS] = { JAVAVM64_FROM_JAVAVM31(vm), (uint64_t)&JNIEnv64Result, (uint64_t)args };
288
jint returnValue = JNI_ERR;
289
uint32_t cel4ro64ReturnCode = J9_CEL4RO64_RETCODE_OK;
290
291
/* Zero initialize reservedNamePadding in JavaVMAttachArgs. */
292
JavaVMAttachArgs *vmAttachArgs = ((JavaVMAttachArgs *) args);
293
if (NULL != vmAttachArgs) {
294
vmAttachArgs->reservedNamePadding = NULL;
295
}
296
297
cel4ro64ReturnCode = j9_cel4ro64_load_query_call_function(
298
LIBJ9VM29_NAME, "AttachCurrentThreadAsDaemon",
299
argTypes, argValues, NUM_ARGS, CEL4RO64_type_jint, &returnValue);
300
301
if (J9_CEL4RO64_RETCODE_OK != cel4ro64ReturnCode) {
302
fprintf(stderr, "AttachCurrentThreadAsDaemon failed. CEL4RO64 rc: %d - %s\n", cel4ro64ReturnCode, j9_cel4ro64_get_error_message(cel4ro64ReturnCode));
303
return JNI_ERR;
304
}
305
/* If successful, we will return the correponding 31-bit JNIEnv. */
306
if (JNI_OK == returnValue) {
307
JNIEnv31* jniEnv31 = getJNIEnv31(JNIEnv64Result);
308
jniEnv31->javaVM31 = (JavaVM31 *)vm;
309
*penv = (JavaVM *)jniEnv31;
310
}
311
return returnValue;
312
}
313
314
/**
315
* Following set of functions are JavaVM31 utility routines.
316
*/
317
318
319
JavaVM31 * JNICALL
320
getJavaVM31(uint64_t javaVM64)
321
{
322
/* Traverse list to find matching JavaVM31. */
323
for (JavaVM31 *curJavaVM31 = globalRootJavaVM31; curJavaVM31 != NULL; curJavaVM31 = curJavaVM31->next) {
324
if (javaVM64 == curJavaVM31->javaVM64) {
325
return curJavaVM31;
326
}
327
}
328
329
/* Create and initialize a new instance. */
330
JavaVM31 *newJavaVM31 = (JavaVM31 *)malloc(sizeof(JavaVM31));
331
if (NULL != newJavaVM31) {
332
initializeJavaVM31(newJavaVM31, javaVM64);
333
}
334
return newJavaVM31;
335
}
336
337
/**
338
* Initialize new JavaVM31 structure, with references to the corresponding 64-bit
339
* JavaVM, along with both 31-bit and 64-bit invoke function tables. Add to our
340
* list of JavaVM31.
341
*
342
* @param[in] javaVM31 The 31-bit JavaVM* instance to initialize.
343
* @param[in] javaVM64 The matching 64-bit JavaVM* from JVM.
344
*/
345
static void
346
initializeJavaVM31(JavaVM31 * javaVM31, jlong javaVM64)
347
{
348
javaVM31->functions = (JNIInvokeInterface_ *)GLOBAL_TABLE(EsJNIInvokeFunctions);
349
javaVM31->javaVM64 = javaVM64;
350
javaVM31->next = globalRootJavaVM31;
351
globalRootJavaVM31 = javaVM31;
352
}
353
354
/**
355
* Free the current 31-bit JavaVM31 instance.
356
*
357
* @param[in] javaVM31ToFree The 31-bit JavaVM instance to free.
358
*/
359
static void
360
freeJavaVM31(JavaVM31 * javaVM31ToFree)
361
{
362
/* Traverse globalRootJavaVM31 list and remove this instance of JavaVM31. */
363
JavaVM31 *currentJavaVM31 = globalRootJavaVM31;
364
365
if (currentJavaVM31 == javaVM31ToFree) {
366
globalRootJavaVM31 = currentJavaVM31->next;
367
} else {
368
/* Traverse list to find the entry to remove. */
369
while (NULL != currentJavaVM31) {
370
JavaVM31 *next = currentJavaVM31->next;
371
if (next == javaVM31ToFree) {
372
currentJavaVM31->next = next->next;
373
break;
374
}
375
currentJavaVM31 = next;
376
}
377
}
378
free(javaVM31ToFree);
379
}
380
381
} /* extern "C" */
382
383