Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/j9vm/jvm.c
5985 views
1
/*******************************************************************************
2
* Copyright (c) 2002, 2022 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
#if 0
24
#define DEBUG
25
#define DEBUG_TEST
26
#endif
27
28
#if defined(J9ZTPF)
29
/*
30
* setup USE_BSD_SELECT_PROTOTYPE so z/tpf's sys/socket.h gives us the *right* select() api.
31
*/
32
#include <tpf/icstk.h>
33
#include <tpf/c_eb0eb.h>
34
#define USE_BSD_SELECT_PROTOTYPE 1
35
#include <tpf/sysapi.h>
36
#include <tpf/tpfapi.h>
37
#include <time.h>
38
#endif /* defined(J9ZTPF) */
39
40
#include "j9vm_internal.h"
41
#include "j9pool.h"
42
#include "util_api.h"
43
#include "j9lib.h"
44
#include "exelib_api.h"
45
#include "j9.h"
46
#include "j9protos.h"
47
#include "j9consts.h"
48
#include "fltconst.h"
49
#include "j9comp.h"
50
#include "omrthread.h"
51
#include "j9cp.h"
52
#include "j2sever.h"
53
#include "j2senls.h"
54
#include "hashtable_api.h"
55
#include "rommeth.h"
56
#include "util_api.h"
57
#include "vmargs_api.h"
58
#include "mmhook.h"
59
#include "jvminit.h"
60
#include "sunvmi_api.h"
61
#include "omrformatconsts.h"
62
#ifdef J9VM_OPT_ZIP_SUPPORT
63
#include "vmi.h"
64
#include "vmzipcachehook.h"
65
#endif
66
#if defined(J9VM_OPT_JITSERVER)
67
#include "jitserver_api.h"
68
#include "jitserver_error.h"
69
#endif /* J9VM_OPT_JITSERVER */
70
71
#if defined(AIXPPC)
72
#include <procinfo.h>
73
#include <sys/types.h>
74
#include <unistd.h>
75
#endif /* defined(AIXPPC) */
76
77
#if defined(J9ZOS390)
78
#include <stdlib.h>
79
80
/*
81
* These offsets and constants are found in "Language Environment Vendor Interfaces", downloaded from
82
* https://www.ibm.com/servers/resourcelink/svc00100.nsf/pages/zosV2R4SA380688/$file/ceev100_v2r4.pdf
83
*/
84
#if defined(J9VM_ENV_DATA64)
85
#define OFFSET_CAA_CEDB 0x348
86
#define OFFSET_CEDB_LANG 0x18
87
#else /* defined(J9VM_ENV_DATA64) */
88
#define OFFSET_CAA_CEDB 0x218
89
#define OFFSET_CEDB_LANG 0x10
90
#endif /* defined(J9VM_ENV_DATA64) */
91
92
/* An enclave data block should begin with this eye-catcher. */
93
#pragma convlit(suspend)
94
static const char cedb_eye[4] = "CEDB";
95
#pragma convlit(resume)
96
97
/*
98
* Determine whether the mainline language is C/C++.
99
*/
100
static BOOLEAN
101
mainlineLanguageIsC(void)
102
{
103
BOOLEAN result = FALSE;
104
/* Locate the common anchor area. */
105
const char *caa = (const char *)_gtca();
106
/* Fetch the pointer to the C/C++ environment data block. */
107
const char *cedb = *(const char * const *)(caa + OFFSET_CAA_CEDB);
108
109
/* Do some basic checking of the cedb pointer. */
110
if ((NULL != cedb) && (0 == memcmp(cedb, cedb_eye, sizeof(cedb_eye)))) {
111
int16_t language = *(const int16_t *)(cedb + OFFSET_CEDB_LANG);
112
113
/* The code for C/C++ is 3. */
114
if (3 == language) {
115
result = TRUE;
116
}
117
}
118
119
return result;
120
}
121
122
struct arg_string
123
{
124
uint32_t length; /* length of value, including NUL terminator */
125
char value[];
126
};
127
128
struct arg_list
129
{
130
uint32_t argc; /* number of command-line arguments */
131
uint32_t env_size; /* number of environment variables */
132
const struct arg_string *string[];
133
};
134
#endif /* defined(J9ZOS390) */
135
136
#if defined(OSX)
137
#include <sys/types.h>
138
#include <sys/sysctl.h>
139
#endif /* defined(OSX) */
140
141
#if defined(WIN32)
142
#include <processenv.h>
143
#include <stdlib.h>
144
#endif /* defined(WIN32) */
145
146
/* Must include this after j9vm_internal.h */
147
#include <string.h>
148
149
#define _UTE_STATIC_
150
#include "ut_j9scar.h"
151
152
#ifdef J9OS_I5
153
#include "Xj9I5OSDebug.H"
154
#include "Xj9I5OSInterface.H"
155
#endif
156
157
#if defined(DEBUG)
158
#define DBG_MSG(x) printf x
159
#else
160
#define DBG_MSG(x)
161
#endif
162
163
#if defined(LINUX) && !defined(J9VM_ENV_DATA64)
164
#include <unistd.h>
165
/* glibc 2.4 and on provide lseek64(), do not use the syscall hack */
166
#if !__GLIBC_PREREQ(2,4)
167
/* Support code for CMVC 104382. */
168
#include <linux/unistd.h>
169
_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh);
170
#endif
171
#endif
172
173
#ifdef WIN32
174
#define IBM_MALLOCTRACE_STR L"IBM_MALLOCTRACE"
175
#define ALT_JAVA_HOME_DIR_STR L"_ALT_JAVA_HOME_DIR"
176
#else /* WIN32 */
177
#define IBM_MALLOCTRACE_STR "IBM_MALLOCTRACE"
178
#endif /* WIN32 */
179
180
#define MIN_GROWTH 128
181
/* DIR_SEPARATOR is defined in j9comp.h */
182
#define jclSeparator DIR_SEPARATOR
183
184
#define CALL_BUNDLED_FUNCTIONS_DIRECTLY 0
185
186
#if !CALL_BUNDLED_FUNCTIONS_DIRECTLY
187
#define CREATE_JAVA_VM_ENTRYPOINT "J9_CreateJavaVM"
188
#define GET_JAVA_VMS_ENTRYPOINT "J9_GetCreatedJavaVMs"
189
190
typedef jint (JNICALL *CreateVM)(JavaVM ** p_vm, void ** p_env, J9CreateJavaVMParams *createparams);
191
typedef jint (JNICALL *GetVMs)(JavaVM**, jsize, jsize*);
192
typedef jint (JNICALL *DetachThread)(JavaVM *);
193
#endif /* !CALL_BUNDLED_FUNCTIONS_DIRECTLY */
194
195
typedef jint (JNICALL *DestroyVM)(JavaVM *);
196
typedef int (*SigAction) (int signum, const struct sigaction *act, struct sigaction *oldact);
197
198
#ifdef J9ZOS390
199
typedef jint (JNICALL *pGetStringPlatform)(JNIEnv*, jstring, char*, jint, const char *);
200
typedef jint (JNICALL *pGetStringPlatformLength)(JNIEnv*, jstring, jint *, const char *);
201
typedef jint (JNICALL *pNewStringPlatform)(JNIEnv*, const char*, jstring *, const char *);
202
typedef jint (JNICALL *p_a2e_vsprintf)(char *, const char *, va_list);
203
#endif
204
205
#if !CALL_BUNDLED_FUNCTIONS_DIRECTLY
206
typedef UDATA* (*ThreadGlobal)(const char* name);
207
typedef IDATA (*ThreadAttachEx)(omrthread_t *handle, omrthread_attr_t *attr);
208
typedef void (*ThreadDetach)(omrthread_t thread);
209
typedef IDATA (*MonitorEnter)(omrthread_monitor_t monitor);
210
typedef IDATA (*MonitorExit)(omrthread_monitor_t monitor);
211
typedef IDATA (*MonitorInit)(omrthread_monitor_t* handle, UDATA flags, char* name);
212
typedef IDATA (*MonitorDestroy)(omrthread_monitor_t monitor);
213
typedef IDATA (*MonitorWait)(omrthread_monitor_t monitor);
214
typedef IDATA (*MonitorWaitTimed)(omrthread_monitor_t monitor, I_64 millis, IDATA nanos);
215
typedef IDATA (*MonitorNotify)(omrthread_monitor_t monitor);
216
typedef IDATA (*MonitorNotifyAll)(omrthread_monitor_t monitor) ;
217
typedef IDATA (* ThreadLibControl)(const char * key, UDATA value) ;
218
typedef IDATA (*SetCategory)(omrthread_t thread, UDATA category, UDATA type);
219
typedef IDATA (*LibEnableCPUMonitor)(omrthread_t thread);
220
221
typedef I_32 (*PortInitLibrary)(J9PortLibrary *portLib, J9PortLibraryVersion *version, UDATA size);
222
typedef UDATA (*PortGetSize)(struct J9PortLibraryVersion *version);
223
typedef I_32 (*PortGetVersion)(struct J9PortLibrary *portLibrary, struct J9PortLibraryVersion *version);
224
225
typedef void* (*J9GetInterface)(J9_INTERFACE_SELECTOR interfaceSelector, J9PortLibrary* portLib, void *userData);
226
#endif /* !CALL_BUNDLED_FUNCTIONS_DIRECTLY */
227
228
#if defined(J9ZOS390)
229
#define ZOS_THR_WEIGHT_NOT_FOUND ((UDATA) 0U)
230
#define ZOS_THR_WEIGHT_MEDIUM ((UDATA) 1U)
231
#define ZOS_THR_WEIGHT_HEAVY ((UDATA) 2U)
232
233
static UDATA checkZOSThrWeightEnvVar(void);
234
static BOOLEAN setZOSThrWeight(void);
235
#endif /* J9ZOS390 */
236
237
#ifdef WIN32
238
#define J9_MAX_ENV 32767
239
#define J9_MAX_PATH _MAX_PATH
240
static HINSTANCE j9vm_dllHandle = (HINSTANCE) 0;
241
static HANDLE jvm_dllHandle;
242
#else /* WIN32 */
243
#define J9_MAX_PATH PATH_MAX
244
static void *j9vm_dllHandle = NULL;
245
static void *java_dllHandle = NULL;
246
#endif /* WIN32 */
247
static J9StringBuffer * j9binBuffer = NULL;
248
static J9StringBuffer * jrebinBuffer = NULL;
249
static J9StringBuffer * j9libBuffer = NULL;
250
static J9StringBuffer * j9libvmBuffer = NULL;
251
static J9StringBuffer * j9Buffer = NULL;
252
static BOOLEAN jvmInSubdir=TRUE;
253
254
#if !CALL_BUNDLED_FUNCTIONS_DIRECTLY
255
static CreateVM globalCreateVM;
256
static GetVMs globalGetVMs;
257
258
static J9GetInterface f_j9_GetInterface = NULL;
259
#endif /* !CALL_BUNDLED_FUNCTIONS_DIRECTLY */
260
261
static DestroyVM globalDestroyVM;
262
263
#ifdef J9ZOS390
264
static pGetStringPlatform globalGetStringPlatform;
265
static pGetStringPlatformLength globalGetStringPlatformLength;
266
static pNewStringPlatform globalNewStringPlatform;
267
static p_a2e_vsprintf global_a2e_vsprintf;
268
#endif
269
270
#if !CALL_BUNDLED_FUNCTIONS_DIRECTLY
271
static ThreadGlobal f_threadGlobal;
272
static ThreadAttachEx f_threadAttachEx;
273
static ThreadDetach f_threadDetach;
274
/* Share these with the other *.c in the DLL */
275
MonitorEnter f_monitorEnter;
276
MonitorExit f_monitorExit;
277
static MonitorInit f_monitorInit;
278
static MonitorDestroy f_monitorDestroy;
279
static MonitorWaitTimed f_monitorWaitTimed;
280
static MonitorNotify f_monitorNotify;
281
static MonitorNotifyAll f_monitorNotifyAll;
282
static PortInitLibrary portInitLibrary;
283
static PortGetSize portGetSizeFn;
284
static PortGetVersion portGetVersionFn;
285
static ThreadLibControl f_threadLibControl;
286
static SetCategory f_setCategory;
287
static LibEnableCPUMonitor f_libEnableCPUMonitor;
288
#endif /* !CALL_BUNDLED_FUNCTIONS_DIRECTLY */
289
290
static UDATA monitor = 0;
291
static J9InternalVMFunctions globalInvokeInterface;
292
293
static struct J9PortLibrary j9portLibrary;
294
static char * newPath = NULL;
295
296
/* cannot be static because it's declared extern in vmi.c */
297
J9JavaVM *BFUjavaVM = NULL;
298
299
static jclass jlClass = NULL;
300
#ifdef J9VM_IVE_RAW_BUILD
301
static jfieldID classNameFID = NULL;
302
#endif /* J9VM_IVE_RAW_BUILD */
303
static jmethodID classDepthMID = NULL;
304
static jmethodID classLoaderDepthMID = NULL;
305
static jmethodID currentClassLoaderMID = NULL;
306
static jmethodID currentLoadedClassMID = NULL;
307
static jmethodID getNameMID = NULL;
308
309
static jclass jlThread = NULL;
310
static jmethodID sleepMID = NULL;
311
312
static jmethodID waitMID = NULL;
313
static jmethodID notifyMID = NULL;
314
static jmethodID notifyAllMID = NULL;
315
316
static UDATA jvmSEVersion = -1;
317
318
static void *omrsigDLL = NULL;
319
320
static void addToLibpath(const char *, BOOLEAN isPrepend);
321
322
/*
323
* PMR56610: allow CL to permanently add directories to LIBPATH during JVM initialization,
324
* while still removing directories added by the VM
325
*/
326
#if defined(AIXPPC)
327
typedef struct J9LibpathBackup {
328
char *fullpath; /* the whole libpath */
329
size_t j9prefixLen; /* length of the j9 prefix, including trailing ':' when needed */
330
} J9LibpathBackup;
331
332
static J9LibpathBackup libpathBackup = { NULL, 0 };
333
334
static void backupLibpath(J9LibpathBackup *, size_t origLibpathLen);
335
static void freeBackupLibpath(J9LibpathBackup *);
336
static void restoreLibpath(J9LibpathBackup *);
337
static const char *findInLibpath(const char *libpath, const char *path);
338
static char *deleteDirsFromLibpath(const char *const libpath, const char *const deleteStart, const size_t deleteLen);
339
static void setLibpath(const char *libpath);
340
341
#ifdef DEBUG_TEST
342
static void testBackupAndRestoreLibpath(void);
343
#endif /* DEBUG_TEST */
344
#endif /* AIXPPC */
345
346
/* Defined in j9memcategories.c */
347
extern OMRMemCategorySet j9MainMemCategorySet;
348
349
void exitHook(J9JavaVM *vm);
350
static jint JNI_CreateJavaVM_impl(JavaVM **pvm, void **penv, void *vm_args, BOOLEAN isJITServer);
351
static void* preloadLibrary(char* dllName, BOOLEAN inJVMDir);
352
static UDATA protectedStrerror(J9PortLibrary* portLib, void* savedErrno);
353
static UDATA strerrorSignalHandler(struct J9PortLibrary* portLibrary, U_32 gpType, void* gpInfo, void* userData);
354
static void throwNewUnsatisfiedLinkError(JNIEnv *env, char *message);
355
static int findDirContainingFile(J9StringBuffer **result, char *paths, char pathSeparator, char *fileToFind, int elementsToSkip);
356
static int findDirUplevelToDirContainingFile(J9StringBuffer **result, char *pathEnvar, char pathSeparator, char *fileInPath, int upLevels, int elementsToSkip);
357
static void truncatePath(char *inputPath);
358
359
#if defined(WIN32)
360
static jint formatErrorMessage(int errorCode, char *inBuffer, jint inBufferLength);
361
#endif
362
363
#if defined(J9VM_OPT_JITSERVER)
364
static int32_t startJITServer(struct JITServer *);
365
static int32_t waitForJITServerTermination(struct JITServer *);
366
static int32_t destroyJITServer(struct JITServer **);
367
#endif /* J9VM_OPT_JITSERVER */
368
369
/**
370
* Preload the VM, Thread, and Port libraries using platform-specific
371
* shared library functions, and modifying the process environment as
372
* required.
373
* @return TRUE on success, FALSE otherwise.
374
*/
375
static BOOLEAN preloadLibraries(void);
376
377
/**
378
* Check if the libraries have been preloaded
379
* @return TRUE if libraries have been loaded, false otherwise
380
*/
381
static BOOLEAN librariesLoaded(void);
382
383
#if defined(WIN32) || defined(WIN64)
384
#define strdup _strdup
385
#define write _write
386
#define close _close
387
#define read _read
388
#define open _open
389
#endif
390
391
#if defined(J9ZTPF)
392
#define LD_ENV_PATH "LD_LIBRARY_PATH"
393
#elif defined(J9ZOS390)
394
#define LD_ENV_PATH "LIBPATH"
395
#endif /* defined(J9ZTPF) */
396
397
#define J9_SIG_ERR -1
398
#define J9_SIG_IGNORED 1
399
400
#define J9_PRE_DEFINED_HANDLER_CHECK 2
401
#define J9_USE_OLD_JAVA_SIGNAL_HANDLER 2
402
403
#define J9_SIG_PREFIX "SIG"
404
405
/* Chosen based upon signal names listed in signalMap below. */
406
#define J9_SIGNAME_BUFFER_LENGTH 16
407
408
static void dummySignalHandler(jint sigNum);
409
static BOOLEAN isSignalUsedForShutdown(jint sigNum);
410
static BOOLEAN isSignalReservedByJVM(jint sigNum);
411
412
typedef struct {
413
const char *signalName;
414
jint signalValue;
415
} J9SignalMapping;
416
417
#if defined(WIN32)
418
#define J9_SIGNAL_MAP_ENTRY(name, value) { name, value }
419
#else /* defined(WIN32) */
420
#define J9_SIGNAL_MAP_ENTRY(name, value) { "SIG" name, value }
421
#endif /* defined(WIN32) */
422
423
static const J9SignalMapping signalMap[] = {
424
#if defined(SIGABRT)
425
J9_SIGNAL_MAP_ENTRY("ABRT", SIGABRT),
426
#endif /* defined(SIGABRT) */
427
#if defined(SIGALRM)
428
J9_SIGNAL_MAP_ENTRY("ALRM", SIGALRM),
429
#endif /* defined(SIGALRM) */
430
#if defined(SIGBREAK)
431
J9_SIGNAL_MAP_ENTRY("BREAK", SIGBREAK),
432
#endif /* defined(SIGBREAK) */
433
#if defined(SIGBUS)
434
J9_SIGNAL_MAP_ENTRY("BUS", SIGBUS),
435
#endif /* defined(SIGBUS) */
436
#if defined(SIGCHLD)
437
J9_SIGNAL_MAP_ENTRY("CHLD", SIGCHLD),
438
#endif /* defined(SIGCHLD) */
439
#if defined(SIGCONT)
440
J9_SIGNAL_MAP_ENTRY("CONT", SIGCONT),
441
#endif /* defined(SIGCONT) */
442
#if defined(SIGFPE)
443
J9_SIGNAL_MAP_ENTRY("FPE", SIGFPE),
444
#endif /* defined(SIGFPE) */
445
#if defined(SIGHUP)
446
J9_SIGNAL_MAP_ENTRY("HUP", SIGHUP),
447
#endif /* defined(SIGHUP) */
448
#if defined(SIGILL)
449
J9_SIGNAL_MAP_ENTRY("ILL", SIGILL),
450
#endif /* defined(SIGILL) */
451
#if defined(SIGINT)
452
J9_SIGNAL_MAP_ENTRY("INT", SIGINT),
453
#endif /* defined(SIGINT) */
454
#if defined(SIGIO)
455
J9_SIGNAL_MAP_ENTRY("IO", SIGIO),
456
#endif /* defined(SIGIO) */
457
#if defined(SIGPIPE)
458
J9_SIGNAL_MAP_ENTRY("PIPE", SIGPIPE),
459
#endif /* defined(SIGPIPE) */
460
#if defined(SIGPROF)
461
J9_SIGNAL_MAP_ENTRY("PROF", SIGPROF),
462
#endif /* defined(SIGPROF) */
463
#if defined(SIGQUIT)
464
J9_SIGNAL_MAP_ENTRY("QUIT", SIGQUIT),
465
#endif /* defined(SIGQUIT) */
466
#if defined(SIGSEGV)
467
J9_SIGNAL_MAP_ENTRY("SEGV", SIGSEGV),
468
#endif /* defined(SIGSEGV) */
469
#if defined(SIGSYS)
470
J9_SIGNAL_MAP_ENTRY("SYS", SIGSYS),
471
#endif /* defined(SIGSYS) */
472
#if defined(SIGTERM)
473
J9_SIGNAL_MAP_ENTRY("TERM", SIGTERM),
474
#endif /* defined(SIGTERM) */
475
#if defined(SIGTRAP)
476
J9_SIGNAL_MAP_ENTRY("TRAP", SIGTRAP),
477
#endif /* defined(SIGTRAP) */
478
#if defined(SIGTSTP)
479
J9_SIGNAL_MAP_ENTRY("TSTP", SIGTSTP),
480
#endif /* defined(SIGTSTP) */
481
#if defined(SIGTTIN)
482
J9_SIGNAL_MAP_ENTRY("TTIN", SIGTTIN),
483
#endif /* defined(SIGTTIN) */
484
#if defined(SIGTTOU)
485
J9_SIGNAL_MAP_ENTRY("TTOU", SIGTTOU),
486
#endif /* defined(SIGTTOU) */
487
#if defined(SIGURG)
488
J9_SIGNAL_MAP_ENTRY("URG", SIGURG),
489
#endif /* defined(SIGURG) */
490
#if defined(SIGUSR1)
491
J9_SIGNAL_MAP_ENTRY("USR1", SIGUSR1),
492
#endif /* defined(SIGUSR1) */
493
#if defined(SIGUSR2)
494
J9_SIGNAL_MAP_ENTRY("USR2", SIGUSR2),
495
#endif /* defined(SIGUSR2) */
496
#if defined(SIGVTALRM)
497
J9_SIGNAL_MAP_ENTRY("VTALRM", SIGVTALRM),
498
#endif /* defined(SIGVTALRM) */
499
#if defined(SIGWINCH)
500
J9_SIGNAL_MAP_ENTRY("WINCH", SIGWINCH),
501
#endif /* defined(SIGWINCH) */
502
#if defined(SIGXCPU)
503
J9_SIGNAL_MAP_ENTRY("XCPU", SIGXCPU),
504
#endif /* defined(SIGXCPU) */
505
#if defined(SIGXFSZ)
506
J9_SIGNAL_MAP_ENTRY("XFSZ", SIGXFSZ),
507
#endif /* defined(SIGXFSZ) */
508
#if defined(SIGRECONFIG)
509
J9_SIGNAL_MAP_ENTRY("RECONFIG", SIGRECONFIG),
510
#endif /* defined(SIGRECONFIG) */
511
#if defined(SIGKILL)
512
J9_SIGNAL_MAP_ENTRY("KILL", SIGKILL),
513
#endif /* defined(SIGKILL) */
514
#if defined(SIGSTOP)
515
J9_SIGNAL_MAP_ENTRY("STOP", SIGSTOP),
516
#endif /* defined(SIGSTOP) */
517
#if defined(SIGINFO)
518
J9_SIGNAL_MAP_ENTRY("INFO", SIGINFO),
519
#endif /* defined(SIGINFO) */
520
#if defined(SIGIOT)
521
J9_SIGNAL_MAP_ENTRY("IOT", SIGIOT),
522
#endif /* defined(SIGIOT) */
523
#if defined(SIGPOLL)
524
J9_SIGNAL_MAP_ENTRY("POLL", SIGPOLL),
525
#endif /* defined(SIGPOLL) */
526
{NULL, J9_SIG_ERR}
527
};
528
529
static void
530
captureCommandLine(void)
531
{
532
#if defined(WIN32)
533
#define ENV_VAR_NAME L"OPENJ9_JAVA_COMMAND_LINE"
534
#else /* defined(WIN32) */
535
#define ENV_VAR_NAME "OPENJ9_JAVA_COMMAND_LINE"
536
#endif /* defined(WIN32) */
537
538
#if defined(AIXPPC)
539
long int bufferSize = sysconf(_SC_ARG_MAX);
540
541
if (bufferSize > 0) {
542
char *buffer = malloc(bufferSize);
543
544
if (NULL != buffer) {
545
#if defined(J9VM_ENV_DATA64)
546
struct procsinfo64 info;
547
#else /* defined(J9VM_ENV_DATA64) */
548
struct procsinfo info;
549
#endif /* defined(J9VM_ENV_DATA64) */
550
551
memset(&info, '\0', sizeof(info));
552
info.pi_pid = getpid();
553
554
if (0 == getargs(&info, sizeof(info), buffer, bufferSize)) {
555
char *cursor = buffer;
556
557
/* replace the internal NULs with spaces */
558
for (;; ++cursor) {
559
if ('\0' == *cursor) {
560
if ('\0' == cursor[1]) {
561
/* the list ends with two NUL characters */
562
break;
563
}
564
*cursor = ' ';
565
}
566
}
567
568
/* it's not fatal if setenv() fails, so don't bother checking */
569
setenv(ENV_VAR_NAME, buffer, 1 /* overwrite */);
570
}
571
572
free(buffer);
573
}
574
}
575
#elif defined(J9ZOS390) /* defined(AIXPPC) */
576
#pragma convlit(suspend)
577
/*
578
* First, make sure the mainline language is C/C++ which uses parameter passing
579
* style 3 as described by [1]; other mainlines may use different styles.
580
*
581
* [1] https://www.ibm.com/docs/en/zos/2.4.0?topic=formats-c-c-parameter-passing-considerations
582
*/
583
if (mainlineLanguageIsC()) {
584
void *plist = __osplist;
585
if (NULL != plist) {
586
const struct arg_list *args = *(const struct arg_list **)plist;
587
uint32_t argc = args->argc;
588
uint32_t i = 0;
589
size_t length = 0;
590
char *buffer = NULL;
591
592
for (i = 0; i < argc; ++i) {
593
length += args->string[i]->length;
594
}
595
596
buffer = malloc(length);
597
if (NULL != buffer) {
598
char *cursor = buffer;
599
600
for (i = 0; i < argc; ++i) {
601
const struct arg_string *arg = args->string[i];
602
if (0 != i) {
603
*cursor = ' ';
604
cursor += 1;
605
}
606
memcpy(cursor, arg->value, arg->length - 1);
607
cursor += arg->length - 1;
608
}
609
610
*cursor = '\0';
611
612
/* it's not fatal if setenv() fails, so don't bother checking */
613
setenv(ENV_VAR_NAME, buffer, 1 /* overwrite */);
614
615
free(buffer);
616
}
617
}
618
}
619
#pragma convlit(resume)
620
#elif defined(LINUX) /* defined(AIXPPC) */
621
int fd = open("/proc/self/cmdline", O_RDONLY, 0);
622
623
if (fd >= 0) {
624
char *buffer = NULL;
625
size_t length = 0;
626
for (;;) {
627
char small_buffer[512];
628
ssize_t count = read(fd, small_buffer, sizeof(small_buffer));
629
if (count <= 0) {
630
break;
631
}
632
length += (size_t)count;
633
}
634
if (length < 2) {
635
goto done;
636
}
637
/* final NUL is already included in length */
638
buffer = malloc(length);
639
if (NULL == buffer) {
640
goto done;
641
}
642
if ((off_t)-1 == lseek(fd, 0, SEEK_SET)) {
643
goto done;
644
}
645
if (read(fd, buffer, length) != length) {
646
goto done;
647
}
648
/* replace the internal NULs with spaces */
649
for (length -= 2;; length -= 1) {
650
if (0 == length) {
651
break;
652
}
653
if ('\0' == buffer[length]) {
654
buffer[length] = ' ';
655
}
656
}
657
/* it's not fatal if setenv() fails, so don't bother checking */
658
setenv(ENV_VAR_NAME, buffer, 1 /* overwrite */);
659
done:
660
if (NULL != buffer) {
661
free(buffer);
662
}
663
close(fd);
664
}
665
#elif defined(OSX) /* defined(AIXPPC) */
666
int argmax = 0;
667
size_t length = 0;
668
int mib[3];
669
670
/* query the argument space limit */
671
mib[0] = CTL_KERN;
672
mib[1] = KERN_ARGMAX;
673
length = sizeof(argmax);
674
if (0 == sysctl(mib, 2, &argmax, &length, NULL, 0)) {
675
char *buffer = malloc(argmax);
676
677
if (NULL != buffer) {
678
int argc = 0;
679
int pid = getpid();
680
681
/* query the argument count */
682
mib[0] = CTL_KERN;
683
mib[1] = KERN_PROCARGS2;
684
mib[2] = pid;
685
length = argmax;
686
if ((argmax >= sizeof(argc)) && (0 == sysctl(mib, 3, buffer, &length, NULL, 0))) {
687
memcpy(&argc, buffer, sizeof(argc));
688
689
/* retrieve the arguments */
690
mib[0] = CTL_KERN;
691
mib[1] = KERN_PROCARGS;
692
mib[2] = pid;
693
length = argmax;
694
if (0 == sysctl(mib, 3, buffer, &length, NULL, 0)) {
695
char *cursor = buffer;
696
char *start = NULL;
697
char *limit = buffer + length;
698
699
for (; (cursor < limit) && ('\0' != *cursor); ++cursor) {
700
/* skip past the program path */
701
}
702
703
for (; (cursor < limit) && ('\0' == *cursor); ++cursor) {
704
/* skip past the padding after the program path */
705
}
706
707
/*
708
* remember the start of the first argument (this is the beginning
709
* of argv[0] which is often the same as the path we skipped above)
710
*/
711
start = cursor;
712
713
/* replace the internal NULs with spaces */
714
for (; cursor < limit; ++cursor) {
715
if ('\0' == *cursor) {
716
argc -= 1;
717
if (0 == argc) {
718
break;
719
}
720
*cursor = ' ';
721
}
722
}
723
724
/* it's not fatal if setenv() fails, so don't bother checking */
725
setenv(ENV_VAR_NAME, start, 1 /* overwrite */);
726
}
727
}
728
729
free(buffer);
730
}
731
}
732
#elif defined(WIN32) /* defined(AIXPPC) */
733
const wchar_t *commandLine = GetCommandLineW();
734
735
if (NULL != commandLine) {
736
/* it's not fatal if _wputenv_s() fails, so don't bother checking */
737
_wputenv_s(ENV_VAR_NAME, commandLine);
738
}
739
#endif /* defined(AIXPPC) */
740
741
#undef ENV_VAR_NAME
742
}
743
744
static void freeGlobals(void)
745
{
746
free(newPath);
747
newPath = NULL;
748
749
free(j9binBuffer);
750
j9binBuffer = NULL;
751
752
free(jrebinBuffer);
753
jrebinBuffer = NULL;
754
755
free(j9libBuffer);
756
j9libBuffer = NULL;
757
758
free(j9libvmBuffer);
759
j9libvmBuffer = NULL;
760
761
free(j9Buffer);
762
j9Buffer = NULL;
763
}
764
765
static J9StringBuffer* jvmBufferEnsure(J9StringBuffer* buffer, UDATA len) {
766
767
if (buffer == NULL) {
768
UDATA newSize = len > MIN_GROWTH ? len : MIN_GROWTH;
769
buffer = (J9StringBuffer*) malloc( newSize + 1 + sizeof(UDATA)); /* 1 for null terminator */
770
if (buffer != NULL) {
771
buffer->remaining = newSize;
772
buffer->data[0] = '\0';
773
}
774
return buffer;
775
}
776
777
if (len > buffer->remaining) {
778
UDATA newSize = len > MIN_GROWTH ? len : MIN_GROWTH;
779
J9StringBuffer* new = (J9StringBuffer*) malloc( strlen((const char*)buffer->data) + newSize + sizeof(UDATA) + 1 );
780
if (new) {
781
new->remaining = newSize;
782
strcpy(new->data, (const char*)buffer->data);
783
}
784
free(buffer);
785
return new;
786
}
787
788
return buffer;
789
}
790
791
792
static J9StringBuffer*
793
jvmBufferCat(J9StringBuffer* buffer, const char* string)
794
{
795
UDATA len = strlen(string);
796
797
buffer = jvmBufferEnsure(buffer, len);
798
if (buffer) {
799
strcat(buffer->data, string);
800
buffer->remaining -= len;
801
}
802
803
return buffer;
804
}
805
806
807
static char* jvmBufferData(J9StringBuffer* buffer) {
808
return buffer ? buffer->data : NULL;
809
}
810
811
jint JNICALL DestroyJavaVM(JavaVM * javaVM)
812
{
813
jint rc;
814
815
UT_MODULE_UNLOADED(J9_UTINTERFACE_FROM_VM((J9JavaVM*)javaVM));
816
rc = globalDestroyVM(javaVM);
817
818
if (JNI_OK == rc) {
819
if (NULL != j9portLibrary.port_shutdown_library) {
820
j9portLibrary.port_shutdown_library(&j9portLibrary);
821
}
822
823
freeGlobals();
824
825
#if defined(J9UNIX) || defined(J9ZOS390)
826
j9vm_dllHandle = 0;
827
java_dllHandle = 0;
828
#endif /* defined(J9UNIX) || defined(J9ZOS390) */
829
830
BFUjavaVM = NULL;
831
} else {
832
/* We are not shutting down the port library but we still
833
* need to make sure memcheck gets a chance to print its
834
* report.
835
*/
836
memoryCheck_print_report(&j9portLibrary);
837
}
838
839
return rc;
840
}
841
842
/**
843
* Check if the libraries have been preloaded
844
* @return TRUE if libraries have been loaded, false otherwise
845
*/
846
static BOOLEAN
847
librariesLoaded(void)
848
{
849
#if !CALL_BUNDLED_FUNCTIONS_DIRECTLY
850
if ((globalCreateVM == NULL)||(globalGetVMs == NULL)) {
851
return FALSE;
852
}
853
#endif
854
return TRUE;
855
}
856
857
#ifdef WIN32
858
859
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
860
{
861
BOOL rcDllMain = TRUE;
862
jvm_dllHandle = hModule;
863
864
if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
865
/* Disable DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications for WIN32*/
866
DisableThreadLibraryCalls(hModule);
867
}
868
869
return rcDllMain;
870
}
871
872
873
static BOOLEAN
874
preloadLibraries(void)
875
{
876
char* tempchar = 0;
877
char jvmDLLName[J9_MAX_PATH];
878
J9StringBuffer * jvmDLLNameBuffer = NULL;
879
wchar_t unicodeDLLName[J9_MAX_PATH + 1] = {0}; /*extra character is added to check if path is truncated by GetModuleFileNameW()*/
880
DWORD unicodeDLLNameLength = 0;
881
UINT prevMode;
882
HINSTANCE vmDLL = 0;
883
HINSTANCE threadDLL = 0;
884
HINSTANCE portDLL = 0;
885
char* vmDllName = J9_VM_DLL_NAME;
886
char* vmName = NULL;
887
static beenRun=FALSE;
888
if(beenRun) {
889
return TRUE;
890
}
891
beenRun = TRUE;
892
893
unicodeDLLNameLength = GetModuleFileNameW(jvm_dllHandle, unicodeDLLName, (J9_MAX_PATH + 1));
894
/* Don't use truncated path */
895
if (unicodeDLLNameLength > (DWORD)J9_MAX_PATH) {
896
fprintf(stderr,"ERROR: failed to load library. Path is too long: %ls\n", unicodeDLLName);
897
return FALSE;
898
}
899
900
/* Use of jvmDLLName is safe as the length is passed in */
901
WideCharToMultiByte(OS_ENCODING_CODE_PAGE, OS_ENCODING_WC_FLAGS, unicodeDLLName, -1, jvmDLLName, J9_MAX_PATH, NULL, NULL);
902
903
jvmDLLNameBuffer = jvmBufferCat(NULL, jvmDLLName);
904
j9binBuffer = jvmBufferCat(j9binBuffer, jvmDLLName);
905
906
/* detect if we're in a subdir or not - is the j9vm dll in the subdir? */
907
truncatePath(jvmBufferData(jvmDLLNameBuffer));
908
jvmDLLNameBuffer = jvmBufferCat(jvmDLLNameBuffer, "\\");
909
jvmDLLNameBuffer = jvmBufferCat(jvmDLLNameBuffer, vmDllName);
910
jvmDLLNameBuffer = jvmBufferCat(jvmDLLNameBuffer, ".dll");
911
912
/* Last argument tells Windows the size of the buffer */
913
MultiByteToWideChar(OS_ENCODING_CODE_PAGE, OS_ENCODING_MB_FLAGS, jvmBufferData(jvmDLLNameBuffer), -1, unicodeDLLName, J9_MAX_PATH);
914
if(INVALID_FILE_ATTRIBUTES != GetFileAttributesW(unicodeDLLName)) {
915
jvmInSubdir = TRUE;
916
} else {
917
jvmInSubdir = FALSE;
918
}
919
920
prevMode = SetErrorMode( SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS );
921
922
free(jvmDLLNameBuffer);
923
jvmDLLNameBuffer = NULL;
924
free(jrebinBuffer);
925
jrebinBuffer = NULL;
926
927
if(jvmInSubdir) {
928
/* truncate the \<my vm name>\jvm.dll from the string */
929
truncatePath(jvmBufferData(j9binBuffer));
930
jrebinBuffer = jvmBufferCat(NULL, jvmBufferData(j9binBuffer));
931
truncatePath(jvmBufferData(jrebinBuffer));
932
} else {
933
/* in this config, j9binBuffer and jrebinBuffer point to the same place - jre/bin/ */
934
truncatePath(jvmBufferData(j9binBuffer));
935
truncatePath(jvmBufferData(j9binBuffer));
936
jrebinBuffer = jvmBufferCat(NULL, jvmBufferData(j9binBuffer));
937
}
938
939
j9libBuffer = jvmBufferCat(NULL, jvmBufferData(jrebinBuffer));
940
truncatePath(jvmBufferData(j9libBuffer));
941
j9Buffer = jvmBufferCat(NULL, jvmBufferData(j9libBuffer));
942
truncatePath(jvmBufferData(j9Buffer));
943
j9libBuffer = jvmBufferCat(j9libBuffer, DIR_SEPARATOR_STR "lib");
944
945
j9libvmBuffer = jvmBufferCat(NULL, jvmBufferData(j9libBuffer));
946
/* append /<vm name> to j9libBuffer to get location of j9ddr.dat file */
947
vmName = strrchr(jvmBufferData(j9binBuffer), DIR_SEPARATOR);
948
if (NULL != vmName) {
949
j9libvmBuffer = jvmBufferCat(j9libvmBuffer, vmName);
950
}
951
952
DBG_MSG(("j9binBuffer = <%s>\n", jvmBufferData(j9binBuffer)));
953
DBG_MSG(("jrebinBuffer = <%s>\n", jvmBufferData(jrebinBuffer)));
954
DBG_MSG(("j9libBuffer = <%s>\n", jvmBufferData(j9libBuffer)));
955
DBG_MSG(("j9libvmBuffer = <%s>\n", jvmBufferData(j9libvmBuffer)));
956
DBG_MSG(("j9Buffer = <%s>\n", jvmBufferData(j9Buffer)));
957
958
#if !CALL_BUNDLED_FUNCTIONS_DIRECTLY
959
vmDLL = (HINSTANCE) preloadLibrary(vmDllName, TRUE);
960
preloadLibrary(J9_HOOKABLE_DLL_NAME, TRUE);
961
962
SetErrorMode( prevMode );
963
964
if (vmDLL < (HINSTANCE)HINSTANCE_ERROR) {
965
fprintf(stderr,"jvm.dll failed to load: %s\n", vmDllName);
966
return FALSE;
967
}
968
globalCreateVM = (CreateVM) GetProcAddress (vmDLL, (LPCSTR) CREATE_JAVA_VM_ENTRYPOINT );
969
globalGetVMs = (GetVMs) GetProcAddress (vmDLL, (LPCSTR) GET_JAVA_VMS_ENTRYPOINT);
970
if (!globalCreateVM || !globalGetVMs) {
971
FreeLibrary(vmDLL);
972
fprintf(stderr,"jvm.dll failed to load: global entrypoints not found\n");
973
return FALSE;
974
}
975
j9vm_dllHandle = vmDLL;
976
977
threadDLL = (HINSTANCE) preloadLibrary(J9_THREAD_DLL_NAME, TRUE);
978
f_threadGlobal = (ThreadGlobal) GetProcAddress (threadDLL, (LPCSTR) "omrthread_global");
979
f_threadAttachEx = (ThreadAttachEx) GetProcAddress (threadDLL, (LPCSTR) "omrthread_attach_ex");
980
f_threadDetach = (ThreadDetach) GetProcAddress (threadDLL, (LPCSTR) "omrthread_detach");
981
f_monitorEnter = (MonitorEnter) GetProcAddress (threadDLL, (LPCSTR) "omrthread_monitor_enter");
982
f_monitorExit = (MonitorExit) GetProcAddress (threadDLL, (LPCSTR) "omrthread_monitor_exit");
983
f_monitorInit = (MonitorInit) GetProcAddress (threadDLL, (LPCSTR) "omrthread_monitor_init_with_name");
984
f_monitorDestroy = (MonitorDestroy) GetProcAddress (threadDLL, (LPCSTR) "omrthread_monitor_destroy");
985
f_monitorWaitTimed = (MonitorWaitTimed) GetProcAddress (threadDLL, (LPCSTR) "omrthread_monitor_wait_timed");
986
f_monitorNotify = (MonitorNotify) GetProcAddress (threadDLL, (LPCSTR) "omrthread_monitor_notify");
987
f_monitorNotifyAll = (MonitorNotifyAll) GetProcAddress (threadDLL, (LPCSTR) "omrthread_monitor_notify_all");
988
f_threadLibControl = (ThreadLibControl) GetProcAddress (threadDLL, (LPCSTR) "omrthread_lib_control");
989
f_setCategory = (SetCategory) GetProcAddress (threadDLL, (LPCSTR) "omrthread_set_category");
990
f_libEnableCPUMonitor = (LibEnableCPUMonitor) GetProcAddress (threadDLL, (LPCSTR) "omrthread_lib_enable_cpu_monitor");
991
if (!f_threadGlobal || !f_threadAttachEx || !f_threadDetach || !f_monitorEnter || !f_monitorExit || !f_monitorInit || !f_monitorDestroy || !f_monitorWaitTimed
992
|| !f_monitorNotify || !f_monitorNotifyAll || !f_threadLibControl || !f_setCategory || !f_libEnableCPUMonitor) {
993
FreeLibrary(vmDLL);
994
FreeLibrary(threadDLL);
995
fprintf(stderr,"jvm.dll failed to load: thread library entrypoints not found\n");
996
return FALSE;
997
}
998
999
/* pre-load port library for memorycheck */
1000
portDLL = (HINSTANCE) preloadLibrary(J9_PORT_DLL_NAME, TRUE);
1001
portInitLibrary = (PortInitLibrary) GetProcAddress (portDLL, (LPCSTR) "j9port_init_library");
1002
portGetSizeFn = (PortGetSize) GetProcAddress (portDLL, (LPCSTR) "j9port_getSize");
1003
portGetVersionFn = (PortGetVersion) GetProcAddress (portDLL, (LPCSTR) "j9port_getVersion");
1004
if (!portInitLibrary) {
1005
FreeLibrary(vmDLL);
1006
FreeLibrary(threadDLL);
1007
FreeLibrary(portDLL);
1008
fprintf(stderr,"jvm.dll failed to load: %s entrypoints not found\n", J9_PORT_DLL_NAME);
1009
return FALSE;
1010
}
1011
preloadLibrary(J9_ZIP_DLL_NAME, TRUE);
1012
1013
#endif /* !CALL_BUNDLED_FUNCTIONS_DIRECTLY */
1014
/* CMVC 152702: with other JVM on the path this library can get loaded from the wrong
1015
* location if not preloaded. */
1016
return TRUE;
1017
}
1018
1019
static void
1020
bfuThreadStart(J9HookInterface** vmHooks, UDATA eventNum, void* eventData, void* userData)
1021
{
1022
J9VMThreadCreatedEvent* event = eventData;
1023
if (event->continueInitialization) {
1024
HANDLE win32Event = CreateEvent(NULL, FALSE, FALSE, NULL);
1025
1026
if (win32Event == NULL) {
1027
/* abort the creation of this thread */
1028
event->continueInitialization = 0;
1029
} else {
1030
event->vmThread->sidecarEvent = win32Event;
1031
}
1032
}
1033
}
1034
1035
1036
static void
1037
bfuThreadEnd(J9HookInterface** vmHooks, UDATA eventNum, void* eventData, void* userData)
1038
{
1039
J9VMThread* vmThread = ((J9VMThreadDestroyEvent*)eventData)->vmThread;
1040
HANDLE event = (HANDLE) vmThread->sidecarEvent;
1041
1042
if (event) {
1043
CloseHandle(event);
1044
vmThread->sidecarEvent = NULL;
1045
}
1046
}
1047
1048
1049
static void bfuInterrupt(J9VMThread * vmThread)
1050
{
1051
HANDLE event = (HANDLE) vmThread->sidecarEvent;
1052
1053
if (event) {
1054
SetEvent(event);
1055
}
1056
}
1057
1058
static void bfuClearInterrupt(J9VMThread * vmThread)
1059
{
1060
HANDLE event = (HANDLE) vmThread->sidecarEvent;
1061
1062
if (event) {
1063
ResetEvent(event);
1064
}
1065
}
1066
1067
static jint
1068
initializeWin32ThreadEvents(J9JavaVM* javaVM)
1069
{
1070
J9VMThread* aThread;
1071
J9HookInterface** hookInterface = javaVM->internalVMFunctions->getVMHookInterface(javaVM);
1072
1073
javaVM->sidecarInterruptFunction = bfuInterrupt;
1074
javaVM->sidecarClearInterruptFunction = bfuClearInterrupt;
1075
1076
if ((*hookInterface)->J9HookRegisterWithCallSite(hookInterface, J9HOOK_VM_THREAD_CREATED, bfuThreadStart, OMR_GET_CALLSITE(), NULL)) {
1077
return JNI_ERR;
1078
}
1079
if ((*hookInterface)->J9HookRegisterWithCallSite(hookInterface, J9HOOK_VM_THREAD_DESTROY, bfuThreadEnd, OMR_GET_CALLSITE(), NULL)) {
1080
return JNI_ERR;
1081
}
1082
1083
/* make sure that all existing threads gets an event, too */
1084
aThread = javaVM->mainThread;
1085
do {
1086
aThread->sidecarEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
1087
if (aThread->sidecarEvent == NULL) {
1088
return JNI_ERR;
1089
}
1090
aThread = aThread->linkNext;
1091
} while (aThread != javaVM->mainThread);
1092
1093
return JNI_OK;
1094
}
1095
1096
#endif
1097
1098
#ifndef WIN32
1099
J9StringBuffer *
1100
getj9bin()
1101
{
1102
/* misnamed - returns the directory that the jvm DLL is found in, NOT the directory that the J9 VM itself is in. */
1103
1104
J9StringBuffer *result = NULL;
1105
#if (defined(LINUX) && !defined(J9ZTPF)) || defined(OSX)
1106
Dl_info libraryInfo;
1107
int rc = dladdr((void *)getj9bin, &libraryInfo);
1108
1109
if (0 == rc) {
1110
fprintf(stderr, "ERROR: cannot determine JAVA home directory\n");
1111
abort();
1112
}
1113
1114
result = jvmBufferCat(NULL, libraryInfo.dli_fname);
1115
/* remove libjvm.so */
1116
truncatePath(jvmBufferData(result));
1117
#elif defined(J9ZOS390) || defined(J9ZTPF)
1118
#define VMDLL_NAME J9_VM_DLL_NAME
1119
1120
int foundPosition = 0;
1121
1122
/* assumes LIBPATH (or LD_LIBRARY_PATH for z/TPF) points to where all libjvm.so can be found */
1123
while(foundPosition = findDirUplevelToDirContainingFile(&result, LD_ENV_PATH, ':', "libjvm.so", 0, foundPosition)) {
1124
/* now screen to see if match is the right libjvm.so - it needs to have a j9vm DLL either in this dir, or in the parent. */
1125
DBG_MSG(("found a libjvm.so at offset %d - looking at elem: %s\n", foundPosition, result));
1126
1127
/* first try this dir - this will be true for 'vm in subdir' cases, and is the likely Java 6 case as of SR1. */
1128
if (isFileInDir(jvmBufferData(result), "lib" VMDLL_NAME J9PORT_LIBRARY_SUFFIX)) {
1129
return result;
1130
}
1131
1132
truncatePath(jvmBufferData(result));
1133
1134
/* trying parent */
1135
if (isFileInDir(jvmBufferData(result), "lib" VMDLL_NAME J9PORT_LIBRARY_SUFFIX)) {
1136
return result;
1137
}
1138
}
1139
1140
fprintf(stderr, "ERROR: cannot determine JAVA home directory\n");
1141
abort();
1142
1143
#else /* must be AIX / RS6000 */
1144
struct ld_info *linfo, *linfop;
1145
int linfoSize, rc;
1146
char *myAddress, *filename, *membername;
1147
1148
/* get loader information */
1149
linfoSize = 1024;
1150
linfo = malloc(linfoSize);
1151
for(;;) {
1152
rc = loadquery(L_GETINFO, linfo, linfoSize);
1153
if (rc != -1) {
1154
break;
1155
}
1156
linfoSize *=2; /* insufficient buffer size - increase */
1157
linfo = realloc(linfo, linfoSize);
1158
}
1159
1160
/* find entry for my loaded object */
1161
myAddress = ((char **)&getj9bin)[0];
1162
for (linfop = linfo;;) {
1163
char *textorg = (char *)linfop->ldinfo_textorg;
1164
char *textend = textorg + (unsigned long)linfop->ldinfo_textsize;
1165
if (myAddress >=textorg && (myAddress < textend)) {
1166
break;
1167
}
1168
if (!linfop->ldinfo_next) {
1169
abort();
1170
}
1171
linfop = (struct ld_info *)((char *)linfop + linfop->ldinfo_next);
1172
}
1173
1174
filename = linfop->ldinfo_filename;
1175
membername = filename+strlen(filename)+1;
1176
#ifdef DEBUG
1177
printf("ldinfo: filename is %s. membername is %s\n", filename, membername);
1178
#endif
1179
1180
result = jvmBufferCat(NULL, filename);
1181
/* remove '/libjvm.a' */
1182
truncatePath(jvmBufferData(result));
1183
1184
free(linfo);
1185
#endif /* defined(LINUX) && !defined(J9ZTPF) */
1186
return result;
1187
}
1188
#endif /* ifndef WIN32*/
1189
1190
#if defined(RS6000) || defined(LINUXPPC)
1191
#ifdef PPC64
1192
#ifdef J9VM_ENV_LITTLE_ENDIAN
1193
#define JVM_ARCH_DIR "ppc64le"
1194
#else /* J9VM_ENV_LITTLE_ENDIAN */
1195
#define JVM_ARCH_DIR "ppc64"
1196
#endif /* J9VM_ENV_LITTLE_ENDIAN */
1197
#else
1198
#define JVM_ARCH_DIR "ppc"
1199
#endif /* PPC64 */
1200
#elif defined(J9X86) || defined(WIN32)
1201
#define JVM_ARCH_DIR "i386"
1202
#elif defined(S390) || defined(J9ZOS390)
1203
#if defined(S39064) || defined(J9ZOS39064)
1204
#define JVM_ARCH_DIR "s390x"
1205
#else
1206
#define JVM_ARCH_DIR "s390"
1207
#endif /* S39064 || J9ZOS39064 */
1208
#elif defined(J9HAMMER)
1209
#define JVM_ARCH_DIR "amd64"
1210
#elif defined(J9ARM)
1211
#define JVM_ARCH_DIR "arm"
1212
#elif defined(J9AARCH64)
1213
#define JVM_ARCH_DIR "aarch64"
1214
#elif defined(RISCV64)
1215
#define JVM_ARCH_DIR "riscv64"
1216
#else
1217
#error "Must define an architecture"
1218
#endif
1219
1220
/* We use forward slashes here because J9VM_LIB_ARCH_DIR is not used on Windows. */
1221
#if (JAVA_SPEC_VERSION >= 9) || defined(OSX)
1222
/* On OSX, <arch> doesn't exist, so JVM_ARCH_DIR shouldn't be included in J9VM_LIB_ARCH_DIR. */
1223
#define J9VM_LIB_ARCH_DIR "/lib/"
1224
#else /* (JAVA_SPEC_VERSION >= 9) || defined(OSX) */
1225
#define J9VM_LIB_ARCH_DIR "/lib/" JVM_ARCH_DIR "/"
1226
#endif /* (JAVA_SPEC_VERSION >= 9) || defined(OSX) */
1227
1228
#if JAVA_SPEC_VERSION == 8
1229
/*
1230
* Remove the suffix from string if present.
1231
*/
1232
static void
1233
removeSuffix(char *string, const char *suffix)
1234
{
1235
size_t stringLength = strlen(string);
1236
size_t suffixLength = strlen(suffix);
1237
1238
if (stringLength >= suffixLength) {
1239
char *tail = &string[stringLength - suffixLength];
1240
1241
if (0 == strcmp(tail, suffix)) {
1242
*tail = '\0';
1243
}
1244
}
1245
}
1246
#endif /* JAVA_SPEC_VERSION == 8 */
1247
1248
#if defined(J9UNIX) || defined(J9ZOS390)
1249
static BOOLEAN
1250
preloadLibraries(void)
1251
{
1252
void *vmDLL, *threadDLL, *portDLL;
1253
char* lastSep = 0;
1254
char* tempchar = 0;
1255
char* exeInBuf;
1256
J9StringBuffer * jvmDLLNameBuffer = NULL;
1257
char *lastDirName;
1258
char* vmDllName = J9_VM_DLL_NAME;
1259
struct stat statBuf;
1260
#if defined(J9ZOS390)
1261
void *javaDLL;
1262
#endif
1263
1264
#if defined(AIXPPC)
1265
size_t origLibpathLen = 0;
1266
const char *origLibpath = NULL;
1267
#endif /* AIXPPC */
1268
1269
if (j9vm_dllHandle != 0) {
1270
return FALSE;
1271
}
1272
1273
#if defined(J9ZOS390)
1274
iconv_init();
1275
#endif
1276
1277
#if defined(AIXPPC)
1278
origLibpath = getenv("LIBPATH");
1279
if (NULL != origLibpath) {
1280
origLibpathLen = strlen(origLibpath);
1281
}
1282
#endif /* AIXPPC */
1283
1284
jvmDLLNameBuffer = getj9bin();
1285
j9binBuffer = jvmBufferCat(NULL, jvmBufferData(jvmDLLNameBuffer));
1286
1287
addToLibpath(jvmBufferData(j9binBuffer), TRUE);
1288
1289
/* Are we in classic? If so, point to the right arch dir. */
1290
lastDirName = strrchr(jvmBufferData(j9binBuffer), DIR_SEPARATOR);
1291
1292
if (NULL == lastDirName) {
1293
fprintf(stderr, "Preload libraries failed to find a valid J9 binary location\n" );
1294
exit( -1 ); /* failed */
1295
}
1296
1297
if (0 == strcmp(lastDirName + 1, "classic")) {
1298
truncatePath(jvmBufferData(j9binBuffer)); /* at jre/bin or jre/lib/<arch> */
1299
truncatePath(jvmBufferData(j9binBuffer)); /* at jre or jre/lib */
1300
#if JAVA_SPEC_VERSION == 8
1301
/* remove /lib if present */
1302
removeSuffix(jvmBufferData(j9binBuffer), "/lib"); /* at jre */
1303
#endif /* JAVA_SPEC_VERSION == 8 */
1304
j9binBuffer = jvmBufferCat(j9binBuffer, J9VM_LIB_ARCH_DIR "j9vm/");
1305
if (-1 != stat(jvmBufferData(j9binBuffer), &statBuf)) {
1306
/* does exist, carry on */
1307
jvmDLLNameBuffer = jvmBufferCat(NULL, jvmBufferData(j9binBuffer));
1308
} else {
1309
/* does not exist, rewind (likely a 5.0 build) */
1310
free(j9binBuffer);
1311
j9binBuffer = NULL;
1312
j9binBuffer = jvmBufferCat(NULL, jvmBufferData(jvmDLLNameBuffer));
1313
}
1314
}
1315
1316
/* detect if we're in a subdir or not */
1317
jvmDLLNameBuffer = jvmBufferCat(jvmDLLNameBuffer, "/lib");
1318
jvmDLLNameBuffer = jvmBufferCat(jvmDLLNameBuffer, vmDllName);
1319
jvmDLLNameBuffer = jvmBufferCat(jvmDLLNameBuffer, J9PORT_LIBRARY_SUFFIX);
1320
1321
if(-1 != stat (jvmBufferData(jvmDLLNameBuffer), &statBuf)) {
1322
jvmInSubdir = TRUE;
1323
} else {
1324
jvmInSubdir = FALSE;
1325
}
1326
1327
DBG_MSG(("jvmInSubdir: %d\n", jvmInSubdir));
1328
1329
free(jrebinBuffer);
1330
jrebinBuffer = NULL;
1331
1332
/* set up jre bin based on result of subdir knowledge */
1333
if(jvmInSubdir) {
1334
jrebinBuffer = jvmBufferCat(NULL, jvmBufferData(j9binBuffer));
1335
truncatePath(jvmBufferData(jrebinBuffer));
1336
} else {
1337
truncatePath(jvmBufferData(j9binBuffer));
1338
jrebinBuffer = jvmBufferCat(NULL, jvmBufferData(j9binBuffer));
1339
}
1340
j9libBuffer = jvmBufferCat(NULL, jvmBufferData(jrebinBuffer));
1341
#if !defined(OSX)
1342
/* <arch> directory doesn't exist on OSX so j9libBuffer shouldn't
1343
* be truncated on OSX for removing <arch>.
1344
*/
1345
#if JAVA_SPEC_VERSION == 8
1346
/* Remove <arch> */
1347
truncatePath(jvmBufferData(j9libBuffer));
1348
#endif /* JAVA_SPEC_VERSION == 8 */
1349
#endif /* !defined(OSX) */
1350
j9libvmBuffer = jvmBufferCat(NULL, jvmBufferData(j9binBuffer));
1351
j9Buffer = jvmBufferCat(NULL, jvmBufferData(jrebinBuffer));
1352
truncatePath(jvmBufferData(j9Buffer));
1353
1354
DBG_MSG(("j9binBuffer = <%s>\n", jvmBufferData(j9binBuffer)));
1355
DBG_MSG(("jrebinBuffer = <%s>\n", jvmBufferData(jrebinBuffer)));
1356
DBG_MSG(("j9libBuffer = <%s>\n", jvmBufferData(j9libBuffer)));
1357
DBG_MSG(("j9libvmBuffer = <%s>\n", jvmBufferData(j9libvmBuffer)));
1358
DBG_MSG(("j9Buffer = <%s>\n", jvmBufferData(j9Buffer)));
1359
1360
addToLibpath(jvmBufferData(jrebinBuffer), TRUE);
1361
1362
#if defined(AIXPPC)
1363
backupLibpath(&libpathBackup, origLibpathLen);
1364
#endif /* AIXPPC */
1365
1366
omrsigDLL = preloadLibrary("omrsig", TRUE);
1367
if (NULL == omrsigDLL) {
1368
fprintf(stderr, "libomrsig failed to load: omrsig\n" );
1369
exit( -1 ); /* failed */
1370
}
1371
1372
vmDLL = preloadLibrary(vmDllName, TRUE);
1373
if (NULL == vmDLL) {
1374
fprintf(stderr,"libjvm.so failed to load: %s\n", vmDllName);
1375
exit( -1 ); /* failed */
1376
}
1377
1378
globalCreateVM = (CreateVM) dlsym (vmDLL, CREATE_JAVA_VM_ENTRYPOINT );
1379
globalGetVMs = (GetVMs) dlsym (vmDLL, GET_JAVA_VMS_ENTRYPOINT);
1380
if ((NULL == globalCreateVM) || (NULL == globalGetVMs)) {
1381
dlclose(vmDLL);
1382
fprintf(stderr,"libjvm.so failed to load: global entrypoints not found\n");
1383
exit( -1 ); /* failed */
1384
}
1385
j9vm_dllHandle = vmDLL;
1386
1387
#ifdef J9ZOS390
1388
/* pre-load libjava.so for IMBZOS functions */
1389
javaDLL = preloadLibrary("java", FALSE);
1390
if (!javaDLL) {
1391
fprintf(stderr,"libjava.dll failed to load: %s\n", "java");
1392
exit( -1 ); /* failed */
1393
}
1394
globalGetStringPlatform = (pGetStringPlatform) dlsym (javaDLL, "IBMZOS_GetStringPlatform");
1395
globalGetStringPlatformLength = (pGetStringPlatformLength) dlsym (javaDLL, "IBMZOS_GetStringPlatformLength");
1396
globalNewStringPlatform = (pNewStringPlatform) dlsym (javaDLL, "IBMZOS_NewStringPlatform");
1397
global_a2e_vsprintf = (p_a2e_vsprintf) dlsym (javaDLL, "IBMZOS_a2e_vsprintf");
1398
if (!globalGetStringPlatform || !globalGetStringPlatformLength || !globalNewStringPlatform || !global_a2e_vsprintf) {
1399
dlclose(vmDLL);
1400
dlclose(javaDLL);
1401
fprintf(stderr,"libjava.dll failed to load: global entrypoints not found\n");
1402
exit( -1 ); /* failed */
1403
}
1404
java_dllHandle = javaDLL;
1405
#endif
1406
1407
threadDLL = preloadLibrary(J9_THREAD_DLL_NAME, TRUE);
1408
f_threadGlobal = (ThreadGlobal) dlsym (threadDLL, "omrthread_global");
1409
f_threadAttachEx = (ThreadAttachEx) dlsym (threadDLL, "omrthread_attach_ex");
1410
f_threadDetach = (ThreadDetach) dlsym (threadDLL, "omrthread_detach");
1411
f_monitorEnter = (MonitorEnter) dlsym (threadDLL, "omrthread_monitor_enter");
1412
f_monitorExit = (MonitorExit) dlsym (threadDLL, "omrthread_monitor_exit");
1413
f_monitorInit = (MonitorInit) dlsym (threadDLL, "omrthread_monitor_init_with_name");
1414
f_monitorDestroy = (MonitorDestroy) dlsym (threadDLL, "omrthread_monitor_destroy");
1415
f_monitorWaitTimed = (MonitorWaitTimed) dlsym (threadDLL, "omrthread_monitor_wait_timed");
1416
f_monitorNotify = (MonitorNotify) dlsym (threadDLL, "omrthread_monitor_notify");
1417
f_monitorNotifyAll = (MonitorNotifyAll) dlsym (threadDLL, "omrthread_monitor_notify_all");
1418
f_threadLibControl = (ThreadLibControl) dlsym (threadDLL, "omrthread_lib_control");
1419
f_setCategory = (SetCategory) dlsym (threadDLL, "omrthread_set_category");
1420
f_libEnableCPUMonitor = (LibEnableCPUMonitor) dlsym (threadDLL, "omrthread_lib_enable_cpu_monitor");
1421
if (!f_threadGlobal || !f_threadAttachEx || !f_threadDetach || !f_monitorEnter || !f_monitorExit || !f_monitorInit || !f_monitorDestroy || !f_monitorWaitTimed
1422
|| !f_monitorNotify || !f_monitorNotifyAll || !f_threadLibControl || !f_setCategory || !f_libEnableCPUMonitor) {
1423
dlclose(vmDLL);
1424
#ifdef J9ZOS390
1425
dlclose(javaDLL);
1426
#endif
1427
dlclose(threadDLL);
1428
fprintf(stderr,"libjvm.so failed to load: thread library entrypoints not found\n");
1429
exit( -1 ); /* failed */
1430
}
1431
portDLL = preloadLibrary(J9_PORT_DLL_NAME, TRUE);
1432
portInitLibrary = (PortInitLibrary) dlsym (portDLL, "j9port_init_library");
1433
portGetSizeFn = (PortGetSize) dlsym (portDLL, "j9port_getSize");
1434
portGetVersionFn = (PortGetVersion) dlsym (portDLL, "j9port_getVersion");
1435
if (!portInitLibrary) {
1436
dlclose(vmDLL);
1437
#ifdef J9ZOS390
1438
dlclose(javaDLL);
1439
#endif
1440
dlclose(threadDLL);
1441
dlclose(portDLL);
1442
fprintf(stderr,"libjvm.so failed to load: %s entrypoints not found\n", J9_PORT_DLL_NAME);
1443
exit( -1 ); /* failed */
1444
}
1445
1446
return TRUE;
1447
}
1448
#endif /* defined(J9UNIX) || defined(J9ZOS390) */
1449
1450
1451
1452
1453
int jio_fprintf(FILE * stream, const char * format, ...) {
1454
va_list args;
1455
1456
Trc_SC_fprintf_Entry();
1457
1458
va_start( args, format );
1459
vfprintf(stream, format, args);
1460
va_end( args );
1461
1462
Trc_SC_fprintf_Exit(0);
1463
1464
return 0;
1465
}
1466
1467
1468
1469
int
1470
jio_snprintf(char * str, int n, const char * format, ...)
1471
{
1472
va_list args;
1473
int result;
1474
1475
Trc_SC_snprintf_Entry();
1476
1477
va_start(args, format);
1478
result = vsnprintf( str, n, format, args );
1479
va_end(args);
1480
1481
Trc_SC_snprintf_Exit(result);
1482
1483
return result;
1484
1485
}
1486
1487
1488
1489
int
1490
jio_vfprintf(FILE * stream, const char * format, va_list args)
1491
{
1492
1493
Trc_SC_vfprintf_Entry(stream, format);
1494
1495
vfprintf(stream, format, args);
1496
1497
Trc_SC_vfprintf_Exit(0);
1498
1499
return 0;
1500
}
1501
1502
1503
1504
int
1505
jio_vsnprintf(char * str, int n, const char * format, va_list args)
1506
{
1507
int result;
1508
1509
Trc_SC_vsnprintf_Entry(str, n, format);
1510
1511
result = vsnprintf( str, n, format, args );
1512
1513
Trc_SC_vsnprintf_Exit(result);
1514
1515
return result;
1516
}
1517
1518
typedef struct J9SpecialArguments {
1519
UDATA localVerboseLevel;
1520
IDATA *xoss;
1521
UDATA *argEncoding;
1522
IDATA *ibmMallocTraceSet;
1523
const char *executableJarPath;
1524
} J9SpecialArguments;
1525
/**
1526
* Look for special options:
1527
* -verbose:init
1528
* -Xoss
1529
* argument encoding
1530
* -Xcheck:memory
1531
* and return the total size required for the strings
1532
*/
1533
static UDATA
1534
initialArgumentScan(JavaVMInitArgs *args, J9SpecialArguments *specialArgs)
1535
{
1536
BOOLEAN xCheckFound = FALSE;
1537
const char *xCheckString = "-Xcheck";
1538
const char *javaCommand = "-Dsun.java.command=";
1539
const char *javaCommandValue = NULL;
1540
const char *classPath = "-Djava.class.path=";
1541
const char *classPathValue = NULL;
1542
jint argCursor;
1543
UDATA argumentsSize = 0;
1544
1545
#ifdef WIN32
1546
Assert_SC_notNull(specialArgs->argEncoding);
1547
#endif
1548
for (argCursor=0; argCursor < args->nOptions; argCursor++) {
1549
argumentsSize += strlen(args->options[argCursor].optionString) + 1; /* add space for the \0 */
1550
/* scan for -Xoss */
1551
if (0 == strncmp(args->options[argCursor].optionString, "-Xoss", 5)) {
1552
*(specialArgs->xoss) = argCursor;
1553
} else if (strncmp(args->options[argCursor].optionString, OPT_VERBOSE_INIT, strlen(OPT_VERBOSE_INIT))==0) {
1554
specialArgs->localVerboseLevel = VERBOSE_INIT;
1555
} else if (0 == strncmp(args->options[argCursor].optionString, javaCommand, strlen(javaCommand))) {
1556
javaCommandValue = args->options[argCursor].optionString + strlen(javaCommand);
1557
} else if (0 == strncmp(args->options[argCursor].optionString, classPath, strlen(classPath))) {
1558
classPathValue = args->options[argCursor].optionString + strlen(classPath);
1559
} else if (0 == strncmp(args->options[argCursor].optionString, xCheckString, strlen(xCheckString))) {
1560
xCheckFound = TRUE;
1561
} else if (0 == strcmp(args->options[argCursor].optionString, VMOPT_XARGENCODING)) {
1562
*(specialArgs->argEncoding) = ARG_ENCODING_PLATFORM;
1563
} else if (0 == strcmp(args->options[argCursor].optionString, VMOPT_XNOARGSCONVERSION)) {
1564
*(specialArgs->argEncoding) = ARG_ENCODING_LATIN;
1565
} else if (0 == strcmp(args->options[argCursor].optionString, VMOPT_XARGENCODINGUTF8)) {
1566
*(specialArgs->argEncoding) = ARG_ENCODING_UTF;
1567
} else if (0 == strcmp(args->options[argCursor].optionString, VMOPT_XARGENCODINGLATIN)) {
1568
*(specialArgs->argEncoding) = ARG_ENCODING_LATIN;
1569
}
1570
}
1571
1572
if ((NULL != classPathValue) && (NULL != javaCommandValue) && (strcmp(javaCommandValue, classPathValue) == 0)) {
1573
specialArgs->executableJarPath = javaCommandValue;
1574
}
1575
1576
if (TRUE == xCheckFound) {
1577
/* scan backwards for -Xcheck:memory. There may be multiple -Xcheck options, so check them all, stop when we hit -Xcheck:memory */
1578
for( argCursor = args->nOptions - 1 ; argCursor >= 0; argCursor-- ) {
1579
char* memcheckArgs[2];
1580
1581
/* fake up command-line args for parseCmdLine */
1582
memcheckArgs[0] = ""; /* program name -- unused */
1583
memcheckArgs[1] = args->options[argCursor].optionString;
1584
if (memoryCheck_parseCmdLine(&j9portLibrary, 1, memcheckArgs) != 0) {
1585
/* Abandon -Xcheck processing */
1586
/* -Xcheck:memory overrides env var */
1587
*(specialArgs->ibmMallocTraceSet) = FALSE;
1588
break;
1589
}
1590
}
1591
}
1592
return argumentsSize;
1593
}
1594
1595
static void
1596
printVmArgumentsList(J9VMInitArgs *argList)
1597
{
1598
UDATA i;
1599
JavaVMInitArgs *actualArgs = argList->actualVMArgs;
1600
for (i = 0; i < argList->nOptions; ++i) {
1601
J9CmdLineOption* j9Option = &(argList->j9Options[i]);
1602
char *envVar = j9Option->fromEnvVar;
1603
1604
if (NULL == envVar) {
1605
envVar = "N/A";
1606
}
1607
fprintf(stderr, "Option %" OMR_PRIuPTR " optionString=\"%s\" extraInfo=%p from environment variable =\"%s\"\n", i,
1608
actualArgs->options[i].optionString,
1609
actualArgs->options[i].extraInfo,
1610
envVar);
1611
}
1612
}
1613
1614
static void
1615
setNLSCatalog(struct J9PortLibrary* portLib)
1616
{
1617
J9StringBuffer *nlsSearchPathBuffer = NULL;
1618
const char *nlsSearchPaths = NULL;
1619
PORT_ACCESS_FROM_PORT(portLib);
1620
1621
if (J2SE_CURRENT_VERSION >= J2SE_V11) {
1622
/*
1623
* j9libBuffer doesn't end in a slash, but j9nls_set_catalog ignores everything after
1624
* the last slash. Append a slash to our local copy of j9libBuffer
1625
*/
1626
nlsSearchPathBuffer = jvmBufferCat(nlsSearchPathBuffer, jvmBufferData(j9libBuffer));
1627
} else {
1628
/*
1629
* j9binBuffer doesn't end in a slash, but j9nls_set_catalog ignores everything after
1630
* the last slash. Append a slash to our local copy of j9bin
1631
*/
1632
nlsSearchPathBuffer = jvmBufferCat(nlsSearchPathBuffer, jvmBufferData(j9binBuffer));
1633
}
1634
nlsSearchPathBuffer = jvmBufferCat(nlsSearchPathBuffer, DIR_SEPARATOR_STR);
1635
nlsSearchPaths = jvmBufferData(nlsSearchPathBuffer);
1636
1637
j9nls_set_catalog(&nlsSearchPaths, 1, "java", "properties");
1638
free(nlsSearchPathBuffer);
1639
nlsSearchPathBuffer = NULL;
1640
}
1641
1642
1643
static jint initializeReflectionGlobals(JNIEnv * env, BOOLEAN includeAccessors) {
1644
J9VMThread *vmThread = (J9VMThread *) env;
1645
J9JavaVM * vm = vmThread->javaVM;
1646
jclass clazz, clazzConstructorAccessorImpl, clazzMethodAccessorImpl;
1647
1648
clazz = (*env)->FindClass(env, "java/lang/Class");
1649
if (!clazz) {
1650
return JNI_ERR;
1651
}
1652
1653
jlClass = (*env)->NewGlobalRef(env, clazz);
1654
if (!jlClass) {
1655
return JNI_ERR;
1656
}
1657
1658
#ifdef J9VM_IVE_RAW_BUILD /* J9VM_IVE_RAW_BUILD is not enabled by default */
1659
classNameFID = (*env)->GetFieldID(env, clazz, "name", "Ljava/lang/String;");
1660
if (!classNameFID) {
1661
return JNI_ERR;
1662
}
1663
#else /* J9VM_IVE_RAW_BUILD */
1664
classDepthMID = (*env)->GetStaticMethodID(env, clazz, "classDepth", "(Ljava/lang/String;)I");
1665
if (!classDepthMID) {
1666
return JNI_ERR;
1667
}
1668
1669
classLoaderDepthMID = (*env)->GetStaticMethodID(env, clazz, "classLoaderDepth", "()I");
1670
if (!classLoaderDepthMID) {
1671
return JNI_ERR;
1672
}
1673
1674
currentClassLoaderMID = (*env)->GetStaticMethodID(env, clazz, "currentClassLoader", "()Ljava/lang/ClassLoader;");
1675
if (!currentClassLoaderMID) {
1676
return JNI_ERR;
1677
}
1678
1679
currentLoadedClassMID = (*env)->GetStaticMethodID(env, clazz, "currentLoadedClass", "()Ljava/lang/Class;");
1680
if (!currentLoadedClassMID) {
1681
return JNI_ERR;
1682
}
1683
#endif /* J9VM_IVE_RAW_BUILD */
1684
1685
getNameMID = (*env)->GetMethodID(env, clazz, "getName", "()Ljava/lang/String;");
1686
if (!getNameMID) {
1687
return JNI_ERR;
1688
}
1689
1690
clazz = (*env)->FindClass(env, "java/lang/Thread");
1691
if (!clazz) {
1692
return JNI_ERR;
1693
}
1694
1695
jlThread = (*env)->NewGlobalRef(env, clazz);
1696
if (!jlThread) {
1697
return JNI_ERR;
1698
}
1699
1700
sleepMID = (*env)->GetStaticMethodID(env, clazz, "sleep", "(J)V");
1701
if (!sleepMID) {
1702
return JNI_ERR;
1703
}
1704
1705
clazz = (*env)->FindClass(env, "java/lang/Object");
1706
if (!clazz) {
1707
return JNI_ERR;
1708
}
1709
1710
waitMID = (*env)->GetMethodID(env, clazz, "wait", "(J)V");
1711
if (!waitMID) {
1712
return JNI_ERR;
1713
}
1714
1715
notifyMID = (*env)->GetMethodID(env, clazz, "notify", "()V");
1716
if (!notifyMID) {
1717
return JNI_ERR;
1718
}
1719
1720
notifyAllMID = (*env)->GetMethodID(env, clazz, "notifyAll", "()V");
1721
if (!notifyAllMID) {
1722
return JNI_ERR;
1723
}
1724
1725
if (includeAccessors) {
1726
if (J2SE_VERSION(vm) >= J2SE_V11) {
1727
clazzConstructorAccessorImpl = (*env)->FindClass(env, "jdk/internal/reflect/ConstructorAccessorImpl");
1728
clazzMethodAccessorImpl = (*env)->FindClass(env, "jdk/internal/reflect/MethodAccessorImpl");
1729
} else {
1730
clazzConstructorAccessorImpl = (*env)->FindClass(env, "sun/reflect/ConstructorAccessorImpl");
1731
clazzMethodAccessorImpl = (*env)->FindClass(env, "sun/reflect/MethodAccessorImpl");
1732
}
1733
if ( (NULL == clazzConstructorAccessorImpl) || (NULL == clazzMethodAccessorImpl)) {
1734
return JNI_ERR;
1735
}
1736
vm->srConstructorAccessor = (*env)->NewGlobalRef(env, clazzConstructorAccessorImpl);
1737
if (NULL == vm->srConstructorAccessor) {
1738
return JNI_ERR;
1739
}
1740
vm->srMethodAccessor = (*env)->NewGlobalRef(env, clazzMethodAccessorImpl);
1741
if (NULL == vm->srMethodAccessor) {
1742
return JNI_ERR;
1743
}
1744
}
1745
return JNI_OK;
1746
}
1747
1748
/**
1749
* jint JNICALL JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *vm_args)
1750
* Load and initialize a virtual machine instance.
1751
* This provides an invocation API that runs the J9 VM in BFU/sidecar mode.
1752
*
1753
* @param pvm pointer to the location where the JavaVM interface
1754
* pointer will be placed
1755
* @param penv pointer to the location where the JNIEnv interface
1756
* pointer for the main thread will be placed
1757
* @param vm_args java virtual machine initialization arguments
1758
*
1759
* @returns zero on success; otherwise, return a negative number
1760
*
1761
* DLL: jvm
1762
*/
1763
jint JNICALL
1764
JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *vm_args)
1765
{
1766
return JNI_CreateJavaVM_impl(pvm, penv, vm_args, FALSE);
1767
}
1768
1769
#if defined(J9VM_OPT_JITSERVER)
1770
int32_t JNICALL
1771
JITServer_CreateServer(JITServer **jitServer, void *serverArgs)
1772
{
1773
JNIEnv *env = NULL;
1774
JITServer *server = NULL;
1775
jint rc = JITSERVER_OK;
1776
1777
server = malloc(sizeof(JITServer));
1778
if (NULL == server) {
1779
rc = JITSERVER_OOM;
1780
goto _end;
1781
}
1782
server->startJITServer = startJITServer;
1783
server->waitForJITServerTermination = waitForJITServerTermination;
1784
server->destroyJITServer = destroyJITServer;
1785
rc = JNI_CreateJavaVM_impl(&server->jvm, (void **)&env, serverArgs, TRUE);
1786
1787
if (JNI_OK != rc) {
1788
rc = JITSERVER_CREATE_FAILED;
1789
goto _end;
1790
}
1791
*jitServer = server;
1792
rc = JITSERVER_OK; /* success */
1793
1794
_end:
1795
if ((JITSERVER_OK != rc) && (NULL != server)) {
1796
free(server);
1797
*jitServer = NULL;
1798
}
1799
return rc;
1800
}
1801
1802
/**
1803
* Starts an instance of JITServer.
1804
*
1805
* @param jitServer pointer to the JITServer interface
1806
*
1807
* @returns JITSERVER_OK on success, else negative error code
1808
*/
1809
static int32_t
1810
startJITServer(JITServer *jitServer)
1811
{
1812
JavaVM *vm = jitServer->jvm;
1813
JNIEnv *env = NULL;
1814
int32_t rc = JITSERVER_OK;
1815
1816
rc = (*vm)->AttachCurrentThread(vm, (void **)&env, NULL);
1817
if (JNI_OK == rc) {
1818
J9JITConfig *jitConfig = ((J9JavaVM *)vm)->jitConfig;
1819
rc = jitConfig->startJITServer(jitConfig);
1820
if (0 != rc) {
1821
rc = JITSERVER_STARTUP_FAILED;
1822
} else {
1823
rc = JITSERVER_OK;
1824
}
1825
(*vm)->DetachCurrentThread(vm);
1826
} else {
1827
rc = JITSERVER_THREAD_ATTACH_FAILED;
1828
}
1829
return rc;
1830
}
1831
1832
/**
1833
* Wait for JITServer to terminate.
1834
*
1835
* @param jitServer pointer to the JITServer interface
1836
*
1837
* @returns JITSERVER_OK on success, else negative error code
1838
*/
1839
static int32_t
1840
waitForJITServerTermination(JITServer *jitServer)
1841
{
1842
JavaVM *vm = jitServer->jvm;
1843
JNIEnv *env = NULL;
1844
int32_t rc = JITSERVER_OK;
1845
1846
rc = (*vm)->AttachCurrentThread(vm, (void **)&env, NULL);
1847
if (JNI_OK == rc) {
1848
J9JITConfig *jitConfig = ((J9JavaVM *)vm)->jitConfig;
1849
rc = jitConfig->waitJITServerTermination(jitConfig);
1850
if (0 != rc) {
1851
rc = JITSERVER_WAIT_TERM_FAILED;
1852
} else {
1853
rc = JITSERVER_OK;
1854
}
1855
(*vm)->DetachCurrentThread(vm);
1856
} else {
1857
rc = JITSERVER_THREAD_ATTACH_FAILED;
1858
}
1859
return rc;
1860
}
1861
1862
/**
1863
* Frees the resources allocated by JITServer_CreateServer.
1864
*
1865
* @param jitServer double pointer to the JITServer interface. Must not be NULL
1866
*
1867
* @returns JITSERVER_OK on success, else negative error code
1868
*
1869
* @note on return *jitServer is set to NULL
1870
*/
1871
static int32_t
1872
destroyJITServer(JITServer **jitServer)
1873
{
1874
JavaVM *vm = (*jitServer)->jvm;
1875
jint rc = (*vm)->DestroyJavaVM(vm);
1876
free(*jitServer);
1877
*jitServer = NULL;
1878
if (JNI_OK == rc) {
1879
rc = JITSERVER_OK;
1880
} else {
1881
rc = JITSERVER_DESTROY_ERROR;
1882
}
1883
return rc;
1884
}
1885
1886
#endif /* J9VM_OPT_JITSERVER */
1887
1888
/*
1889
* Helper method to load and initialize a virtual machine instance.
1890
*
1891
* @param pvm pointer to the location where the JavaVM interface
1892
* pointer will be placed
1893
* @param penv pointer to the location where the JNIEnv interface
1894
* pointer for the main thread will be placed
1895
* @param vm_args java virtual machine initialization arguments
1896
*
1897
* @returns zero on success; otherwise, return a negative number
1898
*/
1899
static jint
1900
JNI_CreateJavaVM_impl(JavaVM **pvm, void **penv, void *vm_args, BOOLEAN isJITServer)
1901
{
1902
J9JavaVM *j9vm = NULL;
1903
jint result = JNI_OK;
1904
IDATA xoss = -1;
1905
IDATA ibmMallocTraceSet = FALSE;
1906
char cwd[J9_MAX_PATH];
1907
#if defined(WIN32)
1908
wchar_t unicodeTemp[J9_MAX_PATH];
1909
char *altLibraryPathBuffer = NULL;
1910
char *executableJarPath = NULL;
1911
#endif /* defined(WIN32) */
1912
UDATA argEncoding = ARG_ENCODING_DEFAULT;
1913
UDATA altJavaHomeSpecified = 0; /* not used on non-Windows */
1914
J9PortLibraryVersion portLibraryVersion;
1915
#if defined(AIXPPC)
1916
char *origLibpath = NULL;
1917
#endif /* AIXPPC */
1918
I_32 portLibraryInitStatus;
1919
UDATA expectedLibrarySize;
1920
UDATA localVerboseLevel = 0;
1921
J9CreateJavaVMParams createParams = {0};
1922
JavaVMInitArgs *args = NULL;
1923
UDATA launcherArgumentsSize = 0;
1924
J9VMInitArgs *j9ArgList = NULL;
1925
char *xServiceBuffer = NULL;
1926
const char *libpathValue = NULL;
1927
const char *ldLibraryPathValue = NULL;
1928
J9SpecialArguments specialArgs;
1929
omrthread_t attachedThread = NULL;
1930
specialArgs.localVerboseLevel = localVerboseLevel;
1931
specialArgs.xoss = &xoss;
1932
specialArgs.argEncoding = &argEncoding;
1933
specialArgs.executableJarPath = NULL;
1934
specialArgs.ibmMallocTraceSet = &ibmMallocTraceSet;
1935
#ifdef J9ZTPF
1936
1937
result = tpf_eownrc(TPF_SET_EOWNR, "IBMRT4J ");
1938
1939
if (result < 0) {
1940
fprintf(stderr, "Failed to issue tpf_eownrc.");
1941
return JNI_ERR;
1942
}
1943
result = tmslc(TMSLC_ENABLE+TMSLC_HOLD, "IBMRT4J");
1944
if (result < 0) {
1945
fprintf(stderr, "Failed to start time slicing.");
1946
return JNI_ERR;
1947
}
1948
#endif /* defined(J9ZTPF) */
1949
captureCommandLine();
1950
/*
1951
* Linux uses LD_LIBRARY_PATH
1952
* z/OS uses LIBPATH
1953
* AIX uses both
1954
* use native OS calls because port library isn't ready.
1955
* Copy the strings because the value returned by getenv may change.
1956
*/
1957
#if defined(AIXPPC) || defined(J9ZOS390)
1958
libpathValue = getenv(ENV_LIBPATH);
1959
if (NULL != libpathValue) {
1960
size_t pathLength = strlen(libpathValue) +1;
1961
char *envTemp = malloc(pathLength);
1962
if (NULL == envTemp) {
1963
result = JNI_ERR;
1964
goto exit;
1965
}
1966
strcpy(envTemp, libpathValue);
1967
libpathValue = envTemp;
1968
}
1969
#endif
1970
#if defined(J9UNIX)
1971
ldLibraryPathValue = getenv(ENV_LD_LIB_PATH);
1972
if (NULL != ldLibraryPathValue) {
1973
size_t pathLength = strlen(ldLibraryPathValue) +1;
1974
char *envTemp = malloc(pathLength);
1975
if (NULL == envTemp) {
1976
result = JNI_ERR;
1977
goto exit;
1978
}
1979
strcpy(envTemp, ldLibraryPathValue);
1980
ldLibraryPathValue = envTemp;
1981
}
1982
#endif /* defined(J9UNIX) */
1983
1984
if (BFUjavaVM != NULL) {
1985
result = JNI_ERR;
1986
goto exit;
1987
}
1988
1989
#ifdef J9OS_I5
1990
/* debug code */
1991
Xj9BreakPoint("jvm");
1992
/* Force iSeries create JVM flow */
1993
if (Xj9IleCreateJavaVmCalled() == 0) {
1994
result = Xj9CallIleCreateJavaVm(pvm, penv, vm_args);
1995
goto exit;
1996
}
1997
#endif
1998
1999
#if defined(AIXPPC)
2000
/* CMVC 137180:
2001
* in some cases the LIBPATH does not contain /usr/lib, when
2002
* trying to load application native libraries that are linked against
2003
* libraries in /usr/lib we could fail to find those libraries if /usr/lib
2004
* is not on the LIBPATH.
2005
*/
2006
{
2007
/* github #8504 shows tests fail if the libpath is modified
2008
* when creating a new process from Java. The easy fix is to only
2009
* append to the libpath if /usr/lib isn't already present.
2010
* Example libpath:
2011
* LIBPATH=/jre/lib/ppc64/j9vm:/jre/lib/ppc64:/jre/lib/ppc64/jli:/jre/../lib/ppc64:/usr/lib
2012
*/
2013
2014
const char *currentLibPath = getenv("LIBPATH");
2015
BOOLEAN appendToLibPath = TRUE;
2016
if (NULL != currentLibPath) {
2017
const size_t currentLibPathLength = strlen(currentLibPath);
2018
const char *usrLib = "/usr/lib";
2019
const UDATA usrLibLength = LITERAL_STRLEN("/usr/lib");
2020
const char *needle = strstr(currentLibPath, usrLib);
2021
while (NULL != needle) {
2022
/* Note, inside the loop we're guaranteed to have
2023
* usrLibLength of string to operate on so we can
2024
* always peek needle[usrLibLength] and will get
2025
* either a value or '\0'
2026
*/
2027
const ptrdiff_t offsetFromStart = needle - currentLibPath;
2028
if ((0 == offsetFromStart) || (':' == needle[-1])) {
2029
if ((':' == needle[usrLibLength]) || ('\0' == needle[usrLibLength])) {
2030
/* Found a match */
2031
appendToLibPath = FALSE;
2032
break;
2033
}
2034
}
2035
needle = strstr(needle + usrLibLength, usrLib);
2036
}
2037
}
2038
if (appendToLibPath) {
2039
addToLibpath("/usr/lib", FALSE);
2040
}
2041
}
2042
/* CMVC 135358.
2043
* This function modifies LIBPATH while dlopen()ing J9 shared libs.
2044
* Save the original, with appended /usr/lib so that it can be
2045
* restored at the end of the function. Can't reuse the getenv
2046
* result from above.
2047
*/
2048
origLibpath = getenv("LIBPATH");
2049
#endif
2050
2051
/* no tracing for this function, since it's unlikely to be used once the VM is running and the trace engine is initialized */
2052
preloadLibraries();
2053
2054
#ifdef WIN32
2055
if (GetCurrentDirectoryW(J9_MAX_PATH, unicodeTemp) == 0) {
2056
strcpy(cwd, "\\");
2057
} else {
2058
WideCharToMultiByte(OS_ENCODING_CODE_PAGE, OS_ENCODING_WC_FLAGS, unicodeTemp, -1, cwd, J9_MAX_PATH, NULL, NULL);
2059
}
2060
#else
2061
if (getcwd(cwd, J9_MAX_PATH) == NULL) {
2062
strcpy(cwd, ".");
2063
}
2064
#endif
2065
#ifdef DEBUG
2066
printf("cwd = %s\n", cwd);
2067
#endif
2068
2069
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
2070
if (0 != omrthread_attach_ex(&attachedThread, J9THREAD_ATTR_DEFAULT)) {
2071
result = JNI_ERR;
2072
}
2073
#else /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
2074
if (0 != f_threadAttachEx(&attachedThread, J9THREAD_ATTR_DEFAULT)) {
2075
result = JNI_ERR;
2076
}
2077
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
2078
if (JNI_OK != result) {
2079
goto exit;
2080
}
2081
2082
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
2083
omrthread_lib_enable_cpu_monitor(attachedThread);
2084
#else /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
2085
f_libEnableCPUMonitor(attachedThread);
2086
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
2087
2088
#if defined(J9ZOS390)
2089
/*
2090
* When we init the port lib, the 'Signal Reporter' thread will be spawned.
2091
* On z/OS, we need to know whether this thread should be spawned as a medium
2092
* or heavy weight thread. We do this here but we will only take into
2093
* account JAVA_THREAD_MODEL - i.e., if the customer is using '-Xthr:tw=heavy'
2094
* instead of the env var, the 'Signal Reporter' thread will still be launched
2095
* as a medium weight thread (see PR100512).
2096
*/
2097
if (!setZOSThrWeight()) {
2098
return JNI_ERR;
2099
}
2100
#endif /* defined(J9ZOS390) */
2101
2102
/* Use portlibrary version which we compiled against, and have allocated space
2103
* for on the stack. This version may be different from the one in the linked DLL.
2104
*/
2105
J9PORT_SET_VERSION(&portLibraryVersion, J9PORT_CAPABILITY_MASK);
2106
2107
expectedLibrarySize = sizeof(J9PortLibrary);
2108
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
2109
portLibraryInitStatus = j9port_init_library(&j9portLibrary, &portLibraryVersion, expectedLibrarySize);
2110
#else
2111
portLibraryInitStatus = portInitLibrary(&j9portLibrary, &portLibraryVersion, expectedLibrarySize);
2112
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
2113
2114
if (0 != portLibraryInitStatus) {
2115
J9PortLibraryVersion actualVersion;
2116
/* port lib init failure */
2117
switch (portLibraryInitStatus) {
2118
case J9PORT_ERROR_INIT_WRONG_MAJOR_VERSION: {
2119
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
2120
j9port_getVersion(&j9portLibrary, &actualVersion);
2121
#else
2122
portGetVersionFn(&j9portLibrary, &actualVersion);
2123
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
2124
2125
fprintf(stderr,"Error: Port Library failed to initialize: expected major version %u, actual version is %u\n",
2126
portLibraryVersion.majorVersionNumber, actualVersion.majorVersionNumber);
2127
break;
2128
}
2129
case J9PORT_ERROR_INIT_WRONG_SIZE: {
2130
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
2131
UDATA actualSize = j9port_getSize(&portLibraryVersion);
2132
#else
2133
UDATA actualSize = portGetSizeFn(&portLibraryVersion);
2134
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
2135
fprintf(stderr,"Error: Port Library failed to initialize: expected library size %" OMR_PRIuPTR ", actual size is %" OMR_PRIuPTR "\n",
2136
expectedLibrarySize, actualSize);
2137
break;
2138
}
2139
case J9PORT_ERROR_INIT_WRONG_CAPABILITIES: {
2140
fprintf(stderr,"Error: Port Library failed to initialize: capabilities do not match\n");
2141
break;
2142
}
2143
default: fprintf(stderr,"Error: Port Library failed to initialize: %i\n", portLibraryInitStatus); break;
2144
/* need this to handle legacy port libraries */
2145
}
2146
2147
#if defined(AIXPPC)
2148
/* Release memory if allocated by strdup() in backupLibpath() previously */
2149
freeBackupLibpath(&libpathBackup);
2150
2151
/* restore LIBPATH to avoid polluting child processes */
2152
setLibpath(origLibpath);
2153
#endif /* AIXPPC */
2154
result = JNI_ERR;
2155
goto exit;
2156
}
2157
2158
/* Get the thread library memory categories */
2159
{
2160
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
2161
IDATA threadCategoryResult = omrthread_lib_control(J9THREAD_LIB_CONTROL_GET_MEM_CATEGORIES, (UDATA)&j9MainMemCategorySet);
2162
#else
2163
IDATA threadCategoryResult = f_threadLibControl(J9THREAD_LIB_CONTROL_GET_MEM_CATEGORIES, (UDATA)&j9MainMemCategorySet);
2164
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
2165
2166
if (threadCategoryResult) {
2167
fprintf(stderr,"Error: Couldn't get memory categories from thread library.\n");
2168
#if defined(AIXPPC)
2169
/* Release memory if allocated by strdup() in backupLibpath() previously */
2170
freeBackupLibpath(&libpathBackup);
2171
2172
/* restore LIBPATH to avoid polluting child processes */
2173
setLibpath(origLibpath);
2174
#endif /* AIXPPC */
2175
result = JNI_ERR;
2176
goto exit;
2177
}
2178
}
2179
/* Register the J9 memory categories with the port library */
2180
j9portLibrary.omrPortLibrary.port_control(&j9portLibrary.omrPortLibrary, J9PORT_CTLDATA_MEM_CATEGORIES_SET, (UDATA)&j9MainMemCategorySet);
2181
2182
Assert_SC_true(J2SE_CURRENT_VERSION >= J2SE_18);
2183
setNLSCatalog(&j9portLibrary);
2184
2185
2186
#ifdef WIN32
2187
if (GetEnvironmentVariableW(IBM_MALLOCTRACE_STR, NULL, 0) > 0)
2188
ibmMallocTraceSet = TRUE;
2189
altJavaHomeSpecified = (GetEnvironmentVariableW(ALT_JAVA_HOME_DIR_STR, NULL, 0) > 0);
2190
#endif
2191
#if defined(J9UNIX) || defined(J9ZOS390)
2192
if (getenv(IBM_MALLOCTRACE_STR)) {
2193
ibmMallocTraceSet = TRUE;
2194
}
2195
#endif /* defined(J9UNIX) || defined(J9ZOS390) */
2196
2197
args = (JavaVMInitArgs *)vm_args;
2198
launcherArgumentsSize = initialArgumentScan(args, &specialArgs);
2199
localVerboseLevel = specialArgs.localVerboseLevel;
2200
2201
if (VERBOSE_INIT == localVerboseLevel) {
2202
createParams.flags |= J9_CREATEJAVAVM_VERBOSE_INIT;
2203
}
2204
#if defined(J9VM_OPT_JITSERVER)
2205
if (isJITServer) {
2206
createParams.flags |= J9_CREATEJAVAVM_START_JITSERVER;
2207
}
2208
#endif /* J9VM_OPT_JITSERVER */
2209
2210
if (ibmMallocTraceSet) {
2211
/* We have no access to the original command line, so cannot
2212
* pass in a valid argv to this function.
2213
* Currently this function only used argv to help set the NLS
2214
* catalog.
2215
* The catalog has already been set above. */
2216
memoryCheck_initialize(&j9portLibrary, "all", NULL);
2217
}
2218
2219
{
2220
char *optionsDefaultFileLocation = NULL;
2221
BOOLEAN doAddExtDir = FALSE;
2222
J9JavaVMArgInfoList vmArgumentsList;
2223
J9ZipFunctionTable *zipFuncs = NULL;
2224
vmArgumentsList.pool = pool_new(sizeof(J9JavaVMArgInfo),
2225
32, /* expect at least ~16 arguments, overallocate to accommodate user arguments */
2226
0, 0,
2227
J9_GET_CALLSITE(), OMRMEM_CATEGORY_VM, POOL_FOR_PORT(&j9portLibrary));
2228
if (NULL == vmArgumentsList.pool) {
2229
result = JNI_ERR;
2230
goto exit;
2231
}
2232
vmArgumentsList.head = NULL;
2233
vmArgumentsList.tail = NULL;
2234
if (NULL != specialArgs.executableJarPath) {
2235
#if !CALL_BUNDLED_FUNCTIONS_DIRECTLY
2236
if (NULL == f_j9_GetInterface) {
2237
#ifdef WIN32
2238
f_j9_GetInterface = (J9GetInterface) GetProcAddress (j9vm_dllHandle, (LPCSTR) "J9_GetInterface");
2239
#else
2240
f_j9_GetInterface = (J9GetInterface) dlsym (j9vm_dllHandle, "J9_GetInterface");
2241
#endif /* WIN32 */
2242
}
2243
/* j9binBuffer->data is null terminated */
2244
zipFuncs = (J9ZipFunctionTable*) f_j9_GetInterface(IF_ZIPSUP, &j9portLibrary, j9binBuffer->data);
2245
#else /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
2246
zipFuncs = (J9ZipFunctionTable*) J9_GetInterface(IF_ZIPSUP, &j9portLibrary, j9binBuffer);
2247
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
2248
#if defined(WIN32)
2249
{
2250
BOOLEAN conversionSucceed = FALSE;
2251
int32_t size = 0;
2252
UDATA pathLen = strlen(specialArgs.executableJarPath);
2253
2254
PORT_ACCESS_FROM_PORT(&j9portLibrary);
2255
/* specialArgs.executableJarPath is retrieved from JavaVMInitArgs.options[i].optionString
2256
* which was set by Java Launcher in system default code page encoding.
2257
*/
2258
size = j9str_convert(J9STR_CODE_WINDEFAULTACP, J9STR_CODE_MUTF8, specialArgs.executableJarPath, pathLen, NULL, 0);
2259
if (size > 0) {
2260
size += 1; /* leave room for null */
2261
executableJarPath = j9mem_allocate_memory(size, OMRMEM_CATEGORY_VM);
2262
if (NULL != executableJarPath) {
2263
size = j9str_convert(J9STR_CODE_WINDEFAULTACP, J9STR_CODE_MUTF8, specialArgs.executableJarPath, pathLen, executableJarPath, size);
2264
if (size > 0) {
2265
conversionSucceed = TRUE;
2266
}
2267
}
2268
}
2269
if (!conversionSucceed) {
2270
result = JNI_ERR;
2271
goto exit;
2272
}
2273
/* specialArgs.executableJarPath was assigned with javaCommandValue which is
2274
* args->options[argCursor].optionString + strlen(javaCommand) within initialArgumentScan().
2275
* The optionString will be freed later at destroyJvmInitArgs().
2276
* Hence overwriting specialArgs.executableJarPath won't cause memory leak.
2277
*/
2278
specialArgs.executableJarPath = executableJarPath;
2279
}
2280
#endif /* defined(WIN32) */
2281
}
2282
if (J2SE_CURRENT_VERSION >= J2SE_V11) {
2283
optionsDefaultFileLocation = jvmBufferData(j9libBuffer);
2284
} else {
2285
optionsDefaultFileLocation = jvmBufferData(j9binBuffer);
2286
doAddExtDir = TRUE;
2287
}
2288
/* now add implicit VM arguments */
2289
if (
2290
/* Add the default options file */
2291
(0 != addOptionsDefaultFile(&j9portLibrary, &vmArgumentsList, optionsDefaultFileLocation, localVerboseLevel))
2292
|| (0 != addXjcl(&j9portLibrary, &vmArgumentsList, J2SE_CURRENT_VERSION))
2293
|| (0 != addBootLibraryPath(&j9portLibrary, &vmArgumentsList, "-Dcom.ibm.oti.vm.bootstrap.library.path=",
2294
jvmBufferData(j9binBuffer), jvmBufferData(jrebinBuffer)))
2295
|| (0 != addBootLibraryPath(&j9portLibrary, &vmArgumentsList, "-Dsun.boot.library.path=",
2296
jvmBufferData(j9binBuffer), jvmBufferData(jrebinBuffer)))
2297
|| (0 != addJavaLibraryPath(&j9portLibrary, &vmArgumentsList, argEncoding, jvmInSubdir,
2298
jvmBufferData(j9binBuffer), jvmBufferData(jrebinBuffer),
2299
libpathValue, ldLibraryPathValue))
2300
|| (0 != addJavaHome(&j9portLibrary, &vmArgumentsList, altJavaHomeSpecified, jvmBufferData(j9libBuffer)))
2301
|| (doAddExtDir && (0 != addExtDir(&j9portLibrary, &vmArgumentsList, jvmBufferData(j9libBuffer), args, J2SE_CURRENT_VERSION)))
2302
|| (0 != addUserDir(&j9portLibrary, &vmArgumentsList, cwd))
2303
#if !defined(OPENJ9_BUILD)
2304
|| (0 != addJavaPropertiesOptions(&j9portLibrary, &vmArgumentsList, localVerboseLevel))
2305
#endif /* defined(OPENJ9_BUILD) */
2306
|| (0 != addJarArguments(&j9portLibrary, &vmArgumentsList, specialArgs.executableJarPath, zipFuncs, localVerboseLevel))
2307
|| (0 != addEnvironmentVariables(&j9portLibrary, args, &vmArgumentsList, localVerboseLevel))
2308
|| (0 != addLauncherArgs(&j9portLibrary, args, launcherArgumentsSize, &vmArgumentsList,
2309
&xServiceBuffer, argEncoding, localVerboseLevel))
2310
#if (JAVA_SPEC_VERSION != 8) || defined(OPENJ9_BUILD)
2311
|| (0 != addEnvironmentVariableArguments(&j9portLibrary, ENVVAR_JAVA_OPTIONS, &vmArgumentsList, localVerboseLevel))
2312
#endif /* (JAVA_SPEC_VERSION != 8) || defined(OPENJ9_BUILD) */
2313
|| (0 != addXserviceArgs(&j9portLibrary, &vmArgumentsList, xServiceBuffer, localVerboseLevel))
2314
) {
2315
result = JNI_ERR;
2316
goto exit;
2317
}
2318
2319
if (NULL != libpathValue) {
2320
free((void *)libpathValue);
2321
}
2322
if (NULL != ldLibraryPathValue) {
2323
free((void *)ldLibraryPathValue);
2324
}
2325
j9ArgList = createJvmInitArgs(&j9portLibrary, args, &vmArgumentsList, &argEncoding);
2326
if (ARG_ENCODING_LATIN == argEncoding) {
2327
createParams.flags |= J9_CREATEJAVAVM_ARGENCODING_LATIN;
2328
} else if (ARG_ENCODING_UTF == argEncoding) {
2329
createParams.flags |= J9_CREATEJAVAVM_ARGENCODING_UTF8;
2330
} else if (ARG_ENCODING_PLATFORM == argEncoding) {
2331
createParams.flags |= J9_CREATEJAVAVM_ARGENCODING_PLATFORM;
2332
}
2333
2334
pool_kill(vmArgumentsList.pool);
2335
if (NULL == j9ArgList) {
2336
result = JNI_ERR;
2337
goto exit;
2338
}
2339
}
2340
2341
createParams.j2seVersion = J2SE_CURRENT_VERSION;
2342
if (jvmInSubdir) {
2343
createParams.j2seVersion |= J2SE_LAYOUT_VM_IN_SUBDIR;
2344
}
2345
createParams.j2seRootDirectory = jvmBufferData(j9binBuffer);
2346
createParams.j9libvmDirectory = jvmBufferData(j9libvmBuffer);
2347
2348
createParams.portLibrary = &j9portLibrary;
2349
createParams.globalJavaVM = &BFUjavaVM;
2350
2351
if (VERBOSE_INIT == localVerboseLevel) {
2352
fprintf(stderr, "VM known paths\t- j9libvm directory: %s\n\t\t- j2seRoot directory: %s\n",
2353
createParams.j9libvmDirectory,
2354
createParams.j2seRootDirectory);
2355
2356
printVmArgumentsList(j9ArgList);
2357
}
2358
createParams.vm_args = j9ArgList;
2359
2360
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
2361
result = J9_CreateJavaVM((JavaVM**)&BFUjavaVM, penv, &createParams);
2362
#else
2363
result = globalCreateVM((JavaVM**)&BFUjavaVM, penv, &createParams);
2364
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
2365
2366
#ifdef DEBUG
2367
fprintf(stdout,"Finished, result %d, env %llx\n", result, (long long)*penv);
2368
fflush(stdout);
2369
#endif
2370
if (result == JNI_OK) {
2371
BOOLEAN initializeReflectAccessors = TRUE;
2372
JavaVM * vm = (JavaVM*)BFUjavaVM;
2373
*pvm = vm;
2374
2375
/* Initialize the Sun VMI */
2376
ENSURE_VMI();
2377
2378
memcpy(&globalInvokeInterface, *vm, sizeof(J9InternalVMFunctions));
2379
globalDestroyVM = globalInvokeInterface.DestroyJavaVM;
2380
globalInvokeInterface.DestroyJavaVM = DestroyJavaVM;
2381
issueWriteBarrier();
2382
*vm = (struct JNIInvokeInterface_ *) &globalInvokeInterface;
2383
2384
#ifdef WIN32
2385
result = initializeWin32ThreadEvents(BFUjavaVM);
2386
if (result != JNI_OK) {
2387
(**pvm)->DestroyJavaVM(*pvm);
2388
goto exit;
2389
}
2390
#endif
2391
2392
/* Initialize the VM interface */
2393
result = initializeReflectionGlobals(*penv, initializeReflectAccessors);
2394
if (result != JNI_OK) {
2395
(**pvm)->DestroyJavaVM(*pvm);
2396
goto exit;
2397
}
2398
} else {
2399
freeGlobals();
2400
}
2401
2402
if ((result == JNI_OK) && (BFUjavaVM->runtimeFlags & J9_RUNTIME_SHOW_VERSION)) {
2403
JNIEnv * env = *penv;
2404
jclass clazz = (*env)->FindClass(env, "sun/misc/Version");
2405
2406
if (clazz == NULL) {
2407
(*env)->ExceptionClear(env);
2408
} else {
2409
jmethodID mid = (*env)->GetStaticMethodID(env, clazz, "print", "()V");
2410
2411
if (mid != NULL) {
2412
(*env)->CallStaticVoidMethod(env, clazz, mid);
2413
if (!(*env)->ExceptionCheck(env)) {
2414
j9portLibrary.omrPortLibrary.tty_printf(&j9portLibrary.omrPortLibrary, "\n");
2415
}
2416
}
2417
(*env)->ExceptionClear(env);
2418
(*env)->DeleteLocalRef(env, clazz);
2419
}
2420
}
2421
2422
#if defined(AIXPPC)
2423
/* restore LIBPATH to avoid polluting child processes */
2424
restoreLibpath(&libpathBackup);
2425
#ifdef DEBUG_TEST
2426
testBackupAndRestoreLibpath();
2427
#endif /* DEBUG_TEST */
2428
#endif /* AIXPPC */
2429
2430
if (JNI_OK == result) {
2431
J9JavaVM *env = (J9JavaVM *) BFUjavaVM;
2432
J9VMThread *currentThread = env->mainThread;
2433
omrthread_t thread = currentThread->osThread;
2434
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
2435
omrthread_set_category(thread, J9THREAD_CATEGORY_APPLICATION_THREAD, J9THREAD_TYPE_SET_MODIFY);
2436
#else
2437
f_setCategory(thread, J9THREAD_CATEGORY_APPLICATION_THREAD, J9THREAD_TYPE_SET_MODIFY);
2438
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
2439
}
2440
2441
exit:
2442
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
2443
if (NULL != attachedThread) {
2444
omrthread_detach(attachedThread);
2445
}
2446
#else /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
2447
if (NULL != attachedThread) {
2448
f_threadDetach(attachedThread);
2449
}
2450
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
2451
#if defined(WIN32)
2452
if (NULL != executableJarPath) {
2453
PORT_ACCESS_FROM_PORT(&j9portLibrary);
2454
/* specialArgs.executableJarPath (overwritten with executableJarPath) is only used by
2455
* addJarArguments(... specialArgs.executableJarPath, ...) which uses the path to load the jar files
2456
* and doesn't require the path afterwards.
2457
* So executableJarPath can be freed after that usage.
2458
*/
2459
j9mem_free_memory(executableJarPath);
2460
}
2461
#endif /* defined(WIN32) */
2462
2463
return result;
2464
}
2465
2466
2467
/**
2468
* jint JNICALL JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
2469
* Return pointers to all the virtual machine instances that have been
2470
* created.
2471
* This provides an invocation API that runs the J9 VM in BFU/sidecar mode
2472
*
2473
* @param vmBuf pointer to the buffer where the pointer to virtual
2474
* machine instances will be placed
2475
* @param bufLen the length of the buffer
2476
* @param nVMs a pointer to and integer
2477
*
2478
* @returns zero on success; otherwise, return a negative number
2479
*
2480
* DLL: jvm
2481
*/
2482
2483
2484
jint JNICALL
2485
JNI_GetCreatedJavaVMs(JavaVM **vmBuf, jsize bufLen, jsize *nVMs)
2486
{
2487
jint result;
2488
Trc_SC_GetCreatedJavaVMs_Entry(vmBuf, bufLen, nVMs);
2489
2490
/* for proxy we cannot preload the libraries as we don't know whether proxy is enabled or not at this point
2491
* However, if the libraries have not already been preloaded then we know that no vms have been created and
2492
* can return the right answer
2493
*/
2494
if(librariesLoaded()){
2495
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
2496
result = J9_GetCreatedJavaVMs(vmBuf, bufLen, nVMs);
2497
#else
2498
result = globalGetVMs(vmBuf, bufLen, nVMs);
2499
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
2500
} else {
2501
/* simply return that there have been no JVMs created */
2502
result = JNI_OK;
2503
*nVMs = 0;
2504
}
2505
2506
Trc_SC_GetCreatedJavaVMs_Exit(result, *nVMs);
2507
return result;
2508
}
2509
2510
2511
/**
2512
* jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *vm_args)
2513
* Return a default configuration for the java virtual machine
2514
* implementation.
2515
* This provides an invocation API that runs the J9 VM in BFU/sidecar mode
2516
*
2517
* @param vm_args pointer to a vm-specific initialization structure
2518
* into which the default arguments are filled.
2519
*
2520
* @returns zero on success; otherwise, return a negative number
2521
*
2522
* DLL: jvm
2523
*/
2524
2525
jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *vm_args) {
2526
jint requestedVersion = ((JavaVMInitArgs *)vm_args)->version;
2527
2528
switch (requestedVersion) {
2529
case JNI_VERSION_1_1:
2530
((JDK1_1InitArgs *)vm_args)->javaStackSize = J9_OS_STACK_SIZE;
2531
break;
2532
case JNI_VERSION_1_2:
2533
case JNI_VERSION_1_4:
2534
case JNI_VERSION_1_6:
2535
case JNI_VERSION_1_8:
2536
#if JAVA_SPEC_VERSION >= 9
2537
case JNI_VERSION_9:
2538
#endif /* JAVA_SPEC_VERSION >= 9 */
2539
#if JAVA_SPEC_VERSION >= 10
2540
case JNI_VERSION_10:
2541
#endif /* JAVA_SPEC_VERSION >= 10 */
2542
return JNI_OK;
2543
}
2544
2545
return JNI_EVERSION;
2546
}
2547
2548
2549
2550
2551
#ifdef J9ZOS390
2552
/**
2553
* jint JNICALL GetStringPlatform(JNIEnv*, jstring, char*, jint, const char *);
2554
* This provides an invocation API that runs the J9 VM in BFU/sidecar mode
2555
*
2556
* @returns zero on success; otherwise, return a negative number
2557
*
2558
* DLL: java
2559
*/
2560
2561
jint
2562
GetStringPlatform(JNIEnv* env, jstring instr, char* outstr, jint outlen, const char* encoding)
2563
{
2564
jint result;
2565
2566
preloadLibraries();
2567
2568
Trc_SC_GetStringPlatform_Entry(env, instr, outstr, outlen, encoding);
2569
2570
result = globalGetStringPlatform(env, instr, outstr, outlen, encoding);
2571
2572
Trc_SC_GetStringPlatform_Exit(env, result);
2573
2574
return result;
2575
}
2576
2577
2578
2579
/**
2580
* jint JNICALL GetStringPlatformLength(JNIEnv*, jstring, char*, jint, const char *);
2581
* This provides an invocation API that runs the J9 VM in BFU/sidecar mode
2582
*
2583
* @returns zero on success; otherwise, return a negative number
2584
*
2585
* DLL: java
2586
*/
2587
2588
jint
2589
GetStringPlatformLength(JNIEnv* env, jstring instr, jint* outlen, const char* encoding)
2590
{
2591
jint result;
2592
2593
preloadLibraries();
2594
2595
Trc_SC_GetStringPlatformLength_Entry(env, instr, outlen, encoding);
2596
result = globalGetStringPlatformLength(env, instr, outlen, encoding);
2597
Trc_SC_GetStringPlatformLength_Exit(env, result, *outlen);
2598
2599
return result;
2600
}
2601
2602
2603
2604
/**
2605
* jint JNICALL NewStringPlatform(JNIEnv*, const char *, jstring*, const char*);
2606
* This provides an invocation API that runs the J9 VM in BFU/sidecar mode
2607
*
2608
* @returns zero on success; otherwise, return a negative number
2609
*
2610
* DLL: java
2611
*/
2612
2613
jint
2614
NewStringPlatform(JNIEnv* env, const char* instr, jstring* outstr, const char* encoding)
2615
{
2616
jint result;
2617
2618
preloadLibraries();
2619
Trc_SC_NewStringPlatform_Entry(env, instr, outstr, encoding);
2620
result = globalNewStringPlatform(env, instr, outstr, encoding);
2621
Trc_SC_NewStringPlatform_Exit(env, result);
2622
2623
return result;
2624
}
2625
2626
2627
2628
/**
2629
* jint JNICALL JNI_a2e_vsprintf(char *, const char *, va_list)
2630
* This provides an invocation API that runs the J9 VM in BFU/sidecar mode
2631
*
2632
* @returns zero on success; otherwise, return a negative number
2633
*
2634
* DLL: java
2635
*/
2636
2637
jint
2638
JNI_a2e_vsprintf(char *target, const char *format, va_list args)
2639
{
2640
jint result;
2641
2642
preloadLibraries();
2643
2644
Trc_SC_a2e_vsprintf_Entry(target, format);
2645
2646
result = global_a2e_vsprintf(target, format, args);
2647
2648
Trc_SC_a2e_vsprintf_Exit(result);
2649
2650
return result;
2651
}
2652
#endif /* J9ZOS390 */
2653
2654
2655
int isFileInDir(char *dir, char *file){
2656
size_t length, dirLength;
2657
char *fullpath = NULL;
2658
FILE *f = NULL;
2659
int foundFile = 0;
2660
2661
dirLength = strlen(dir);
2662
/* Construct 'full' path */
2663
if (dir[dirLength-1] == DIR_SEPARATOR) {
2664
/* remove trailing '/' */
2665
dir[dirLength-1] = '\0';
2666
dirLength--;
2667
}
2668
2669
length = dirLength + strlen(file) + 2; /* 2= '/' + null char */
2670
fullpath = malloc(length);
2671
if (NULL != fullpath) {
2672
strcpy(fullpath, dir);
2673
fullpath[dirLength] = DIR_SEPARATOR;
2674
strcpy(fullpath+dirLength+1, file);
2675
2676
/* See if file exists - use fopen() for portability */
2677
f = fopen(fullpath, "rb");
2678
if (NULL != f) {
2679
foundFile = 1;
2680
fclose(f);
2681
}
2682
free(fullpath);
2683
}
2684
return foundFile;
2685
}
2686
2687
2688
/*
2689
* find directory containing a given file.
2690
* @returns 0 for not found, and a positive integer on success, which represents which path element the file was found in.
2691
**/
2692
int findDirContainingFile(J9StringBuffer **result, char *paths, char pathSeparator, char *fileToFind, int elementsToSkip) {
2693
char *startOfDir, *endOfDir, *pathsCopy;
2694
int isEndOfPaths, foundIt, count=elementsToSkip;
2695
2696
/* Copy input as it is modified */
2697
paths = strdup(paths);
2698
if (!paths) {
2699
return FALSE;
2700
}
2701
2702
pathsCopy = paths;
2703
while(elementsToSkip--) {
2704
pathsCopy = strchr(pathsCopy, pathSeparator);
2705
if(pathsCopy) {
2706
pathsCopy++; /* advance past separator */
2707
} else {
2708
free(paths);
2709
return 0;
2710
}
2711
}
2712
2713
/* Search each dir in the list for fileToFind */
2714
startOfDir = endOfDir = pathsCopy;
2715
for (isEndOfPaths=FALSE, foundIt=FALSE; !foundIt && !isEndOfPaths; endOfDir++) {
2716
2717
isEndOfPaths = endOfDir[0] == '\0';
2718
if (isEndOfPaths || (endOfDir[0] == pathSeparator)) {
2719
endOfDir[0] = '\0';
2720
if (strlen(startOfDir) && isFileInDir(startOfDir, fileToFind)) {
2721
foundIt = TRUE;
2722
if (NULL != *result) {
2723
free(*result);
2724
*result = NULL;
2725
}
2726
*result = jvmBufferCat(NULL, startOfDir);
2727
}
2728
startOfDir = endOfDir+1;
2729
count+=1;
2730
}
2731
}
2732
2733
free(paths); /* from strdup() */
2734
if(foundIt) {
2735
return count;
2736
} else {
2737
return 0;
2738
}
2739
}
2740
2741
2742
2743
int findDirUplevelToDirContainingFile(J9StringBuffer **result, char *pathEnvar, char pathSeparator, char *fileInPath, int upLevels, int elementsToSkip) {
2744
char *paths;
2745
int rc;
2746
2747
/* Get the list of paths */
2748
paths = getenv(pathEnvar);
2749
if (!paths) {
2750
return FALSE;
2751
}
2752
2753
/* find the directory */
2754
rc = findDirContainingFile(result, paths, pathSeparator, fileInPath, elementsToSkip);
2755
2756
/* Now move upLevel to it - this may not work for directories of form
2757
/aaa/bbb/.. ... and so on.
2758
If that is a problem, could always use /.. to move up.
2759
*/
2760
if (rc) {
2761
for (; upLevels > 0; upLevels--) {
2762
truncatePath(jvmBufferData(*result));
2763
}
2764
}
2765
return rc;
2766
}
2767
2768
2769
void
2770
exitHook(J9JavaVM *vm)
2771
{
2772
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
2773
while (omrthread_monitor_enter(vm->vmThreadListMutex), vm->sidecarExitFunctions)
2774
#else
2775
while (f_monitorEnter(vm->vmThreadListMutex), vm->sidecarExitFunctions)
2776
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
2777
{
2778
J9SidecarExitFunction * current = vm->sidecarExitFunctions;
2779
2780
vm->sidecarExitFunctions = current->next;
2781
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
2782
omrthread_monitor_exit(vm->vmThreadListMutex);
2783
#else
2784
f_monitorExit(vm->vmThreadListMutex);
2785
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
2786
current->func();
2787
free(current);
2788
}
2789
2790
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
2791
omrthread_monitor_exit(vm->vmThreadListMutex);
2792
#else
2793
f_monitorExit(vm->vmThreadListMutex);
2794
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
2795
}
2796
2797
static void*
2798
preloadLibrary(char* dllName, BOOLEAN inJVMDir)
2799
{
2800
J9StringBuffer *buffer = NULL;
2801
void* handle = NULL;
2802
#ifdef WIN32
2803
wchar_t unicodePath[J9_MAX_PATH];
2804
char * bufferData;
2805
size_t bufferLength;
2806
#endif
2807
2808
if(inJVMDir) {
2809
buffer = jvmBufferCat(buffer, jvmBufferData(j9binBuffer));
2810
} else {
2811
buffer = jvmBufferCat(buffer, jvmBufferData(jrebinBuffer));
2812
}
2813
#ifdef WIN32
2814
buffer = jvmBufferCat(buffer, "\\");
2815
buffer = jvmBufferCat(buffer, dllName);
2816
buffer = jvmBufferCat(buffer, ".dll");
2817
bufferData = jvmBufferData(buffer);
2818
bufferLength = strlen(bufferData);
2819
MultiByteToWideChar(OS_ENCODING_CODE_PAGE, OS_ENCODING_MB_FLAGS, bufferData, -1, unicodePath, (int)bufferLength + 1);
2820
handle = (void*)LoadLibraryExW (unicodePath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
2821
if (handle == NULL) {
2822
fprintf(stderr,"jvm.dll preloadLibrary: LoadLibrary(%s) error: %x\n", buffer->data, GetLastError());
2823
}
2824
#endif
2825
#if defined(J9UNIX)
2826
buffer = jvmBufferCat(buffer, "/lib");
2827
buffer = jvmBufferCat(buffer, dllName);
2828
buffer = jvmBufferCat(buffer, J9PORT_LIBRARY_SUFFIX);
2829
#ifdef AIXPPC
2830
loadAndInit(jvmBufferData(buffer), L_RTLD_LOCAL, NULL);
2831
#endif
2832
handle = (void*)dlopen(jvmBufferData(buffer), RTLD_NOW);
2833
#ifdef AIXPPC
2834
if (handle == NULL) {
2835
int len = strlen(buffer->data);
2836
buffer->data[len - 2] = 'a';
2837
buffer->data[len - 1] = '\0';
2838
loadAndInit(buffer->data, L_RTLD_LOCAL, NULL);
2839
handle = (void*)dlopen(buffer->data, RTLD_NOW);
2840
if (handle == NULL) {
2841
/* get original error, otherwise the error displayed will be for a missing .a library. */
2842
buffer->data[len - 2] = 's';
2843
buffer->data[len - 1] = 'o';
2844
loadAndInit(buffer->data, L_RTLD_LOCAL, NULL);
2845
handle = (void*)dlopen(buffer->data, RTLD_NOW);
2846
}
2847
}
2848
#endif /* AIXPPC */
2849
if (handle == NULL) {
2850
fprintf(stderr,"libjvm.so preloadLibrary(%s): %s\n", buffer->data, dlerror());
2851
}
2852
#endif /* defined(J9UNIX) */
2853
#ifdef J9ZOS390
2854
buffer = jvmBufferCat(buffer, "/lib");
2855
buffer = jvmBufferCat(buffer, dllName);
2856
buffer = jvmBufferCat(buffer, ".so");
2857
handle = (void*)dllload(jvmBufferData(buffer));
2858
if (handle == NULL) {
2859
perror("libjvm.so preloadLibrary: dllload() failed");
2860
}
2861
#endif
2862
2863
free(buffer);
2864
return handle;
2865
}
2866
2867
/*
2868
* This section contains a bunch of 'extra' symbols that Linux needs above and beyond Windows.
2869
* Included everywhere because the makefile generator makes it hard to create different export lists
2870
* for different platforms.
2871
*/
2872
int
2873
pre_block(pre_block_t buf)
2874
{
2875
return 0;
2876
}
2877
2878
2879
2880
int
2881
post_block() {
2882
return 0;
2883
}
2884
2885
#if defined(AIXPPC)
2886
static void
2887
setLibpath(const char *libpath)
2888
{
2889
setenv("LIBPATH", libpath, 1);
2890
}
2891
#endif /* AIXPPC */
2892
2893
static void
2894
addToLibpath(const char *dir, BOOLEAN isPrepend)
2895
{
2896
#if defined(AIXPPC) || defined(J9ZOS390)
2897
char *oldPath, *newPath;
2898
int rc, newSize;
2899
#if defined(J9ZOS390)
2900
char *putenvPath;
2901
int putenvSize;
2902
#endif
2903
2904
oldPath = getenv("LIBPATH");
2905
#ifdef DEBUG
2906
printf("\nLIBPATH before = %s\n", oldPath ? oldPath : "<empty>");
2907
#endif
2908
newSize = (oldPath ? strlen(oldPath) : 0) + strlen(dir) + 2; /* 1 for :, 1 for \0 terminator */
2909
newPath = malloc(newSize);
2910
2911
if(!newPath) {
2912
fprintf(stderr, "addToLibpath malloc(%d) 1 failed, aborting\n", newSize);
2913
abort();
2914
}
2915
#if defined(AIXPPC)
2916
if (oldPath) {
2917
if (isPrepend) {
2918
strcpy(newPath, dir);
2919
strcat(newPath, ":");
2920
strcat(newPath, oldPath);
2921
} else {
2922
strcpy(newPath, oldPath);
2923
strcat(newPath, ":");
2924
strcat(newPath, dir);
2925
}
2926
} else {
2927
strcpy(newPath, dir);
2928
}
2929
2930
#else
2931
/* ZOS doesn't like it when we pre-pend to LIBPATH */
2932
if (oldPath) {
2933
strcpy(newPath, oldPath);
2934
strcat(newPath, ":");
2935
} else {
2936
newPath[0] = '\0';
2937
}
2938
strcat(newPath, dir);
2939
#endif
2940
2941
#if defined(J9ZOS390)
2942
putenvSize = newSize + strlen("LIBPATH=");
2943
putenvPath = malloc(putenvSize);
2944
if(!putenvPath) {
2945
fprintf(stderr, "addToLibpath malloc(%d) 2 failed, aborting\n", putenvSize);
2946
abort();
2947
}
2948
2949
strcpy(putenvPath,"LIBPATH=");
2950
strcat(putenvPath, newPath);
2951
rc = putenv(putenvPath);
2952
free(putenvPath);
2953
#else
2954
rc = setenv("LIBPATH", newPath, 1);
2955
#endif
2956
2957
#ifdef DEBUG
2958
printf("\nLIBPATH after = %s\n", getenv("LIBPATH"));
2959
#endif
2960
free(newPath);
2961
#endif
2962
}
2963
2964
#if defined(AIXPPC)
2965
/**
2966
* Backup the entire LIBPATH after we have prepended VM directory.
2967
*
2968
* @pre libpathBackup can't be NULL.
2969
*
2970
* @param libpathBackup The structure that stores a copy of the current LIBPATH.
2971
* @param origLibpathLen The length of the original LIBPATH before prepending VM dir.
2972
*/
2973
static void
2974
backupLibpath(J9LibpathBackup *libpathBackup, size_t origLibpathLen)
2975
{
2976
const char *curLibpath = getenv("LIBPATH");
2977
2978
libpathBackup->fullpath = NULL;
2979
libpathBackup->j9prefixLen = 0;
2980
2981
if (NULL != curLibpath) {
2982
/* If j9prefix is not at the end of LIBPATH, then trailing ':' is included in j9prefixLen */
2983
libpathBackup->j9prefixLen = strlen(curLibpath) - origLibpathLen;
2984
2985
/* If j9prefixLen == 0, there is no VM prefix to remove. We don't
2986
* need to save a copy of the LIBPATH because we don't need to
2987
* do any processing in restoreLibpath().
2988
*/
2989
if (libpathBackup->j9prefixLen > 0) {
2990
libpathBackup->fullpath = strdup(curLibpath);
2991
if (NULL == libpathBackup->fullpath) {
2992
fprintf(stderr, "backupLibpath: strdup() failed to allocate memory for the backup path\n");
2993
abort();
2994
}
2995
}
2996
}
2997
}
2998
#endif /* AIXPPC */
2999
3000
#if defined(AIXPPC)
3001
/**
3002
* Release memory if allocated by strdup() in backupLibpath().
3003
*
3004
* @pre libpathBackup can't be NULL.
3005
*
3006
* @param libpathBackup The structure that stores a copy of the current LIBPATH.
3007
*/
3008
static void
3009
freeBackupLibpath(J9LibpathBackup *libpathBackup)
3010
{
3011
if (NULL != libpathBackup->fullpath) {
3012
free(libpathBackup->fullpath);
3013
libpathBackup->fullpath = NULL;
3014
}
3015
libpathBackup->j9prefixLen = 0;
3016
}
3017
#endif /* AIXPPC */
3018
3019
#if defined(AIXPPC)
3020
/**
3021
* We allow CL (Class Library) to prepend or append to the existing LIBPATH,
3022
* but it can't change the original one.
3023
* Remove any VM prefix from the current LIBPATH while keeping other parts unchanged.
3024
*
3025
* @pre libpathBackup can't be NULL.
3026
*
3027
* @param libpathBackup Ptr to the LIBPATH before being modified by CL.
3028
*/
3029
static void
3030
restoreLibpath(J9LibpathBackup *libpathBackup)
3031
{
3032
if ((NULL != libpathBackup->fullpath) && (libpathBackup->j9prefixLen > 0)) {
3033
const char *curPath = getenv("LIBPATH");
3034
3035
if (NULL != curPath) {
3036
const char *j9pathLoc = findInLibpath(curPath, libpathBackup->fullpath);
3037
3038
if (NULL != j9pathLoc) {
3039
char *newPath = deleteDirsFromLibpath(curPath, j9pathLoc, libpathBackup->j9prefixLen);
3040
3041
#ifdef DEBUG
3042
printf("restoreLibpath: old LIBPATH = <%s>\n", curPath);
3043
printf("restoreLibpath: new LIBPATH = <%s>\n", newPath);
3044
#endif
3045
setLibpath(newPath);
3046
free(newPath);
3047
}
3048
}
3049
3050
free(libpathBackup->fullpath);
3051
libpathBackup->fullpath = NULL;
3052
libpathBackup->j9prefixLen = 0;
3053
}
3054
}
3055
#endif /* AIXPPC */
3056
3057
#if defined(AIXPPC)
3058
/**
3059
* Search the current LIBPATH for the backup LIBPATH.
3060
*
3061
* @pre libpath is properly formed.
3062
* @pre backupPath is a non-NULL, non-empty string.
3063
*
3064
* @param libpath The ptr to the current LIBPATH.
3065
* @param backupPath The ptr to the backup LIBPATH.
3066
* @return ptr to the match start if found, NULL if there is no match.
3067
*/
3068
static const char *
3069
findInLibpath(const char *libpath, const char *backupPath)
3070
{
3071
size_t backupPathLen = strlen(backupPath);
3072
BOOLEAN leadingColon = FALSE;
3073
BOOLEAN trailingColon = FALSE;
3074
const char *libpathdir = libpath;
3075
3076
if (':' == backupPath[0]) {
3077
/* Shouldn't happen, but this will work if it does */
3078
leadingColon = TRUE;
3079
}
3080
if (':' == backupPath[backupPathLen - 1]) {
3081
trailingColon = TRUE;
3082
}
3083
3084
while (NULL != libpathdir) {
3085
if (!leadingColon) {
3086
/* Skip leading ':'s from libpathdir */
3087
while (':' == libpathdir[0]) {
3088
libpathdir += 1;
3089
}
3090
}
3091
if (0 == strncmp(libpathdir, backupPath, backupPathLen)) {
3092
if (('\0' == libpathdir[backupPathLen]) || (':' == libpathdir[backupPathLen]) || trailingColon) {
3093
return libpathdir;
3094
}
3095
}
3096
3097
/*
3098
* The pointer moves forward by one step if a mismatch occurs previously,
3099
* otherwise strchr() would repeatedly return the first char ':' of the original
3100
* libpathdir if there is no match. Under such circumstance, it would end up
3101
* being in an infinite loop (e.g. libpath = ::x:y, path = b:x:y, prefixlen = 1).
3102
* The change works even if the first char of libpathdir isn't ':'.
3103
*/
3104
libpathdir = strchr(libpathdir + 1, ':');
3105
}
3106
return NULL;
3107
}
3108
#endif /* AIXPPC */
3109
3110
#if defined(AIXPPC)
3111
/**
3112
* Copy a libpath and delete a section from it.
3113
*
3114
* @pre libpath is properly formed.
3115
* @pre The section to be deleted consists of one or more complete directories in the libpath.
3116
* @pre deleteStart is a ptr into libpath string
3117
* @pre deleteLen is greater than 0
3118
*
3119
* @param libpath The value of the current LIBPATH, a null-terminated string.
3120
* @param deleteStart Ptr to the position of libpath to start deleting from.
3121
* @param deleteLen Number of chars to delete. It does not include null-terminators.
3122
* It may include leading or trailing ':'s.
3123
*
3124
* @return a new libpath string
3125
*/
3126
static char *
3127
deleteDirsFromLibpath(const char *const libpath, const char *const deleteStart, const size_t deleteLen)
3128
{
3129
char *newPath = NULL;
3130
size_t preLen = deleteStart - libpath;
3131
const char *postStart = deleteStart + deleteLen;
3132
size_t postLen = strlen(postStart);
3133
size_t delim = 0;
3134
3135
/* Remove trailing : from the prefix */
3136
while ((preLen > 0) && (':' == libpath[preLen - 1])) {
3137
preLen -= 1;
3138
}
3139
3140
if (postLen > 0) {
3141
/* Remove leading : from the postfix */
3142
while (':' == postStart[0]) {
3143
postStart += 1;
3144
postLen -= 1;
3145
}
3146
}
3147
3148
if ((preLen > 0) && (postLen > 0)) {
3149
/* Add delimiter : */
3150
delim = 1;
3151
}
3152
3153
newPath = malloc(preLen + delim + postLen + 1);
3154
if (NULL == newPath) {
3155
fprintf(stderr, "deleteDirsFromLibpath: malloc(%zu) failed, aborting\n", preLen + delim + postLen + 1);
3156
abort();
3157
}
3158
3159
memcpy(newPath, libpath, preLen);
3160
if (delim > 0) {
3161
newPath[preLen] = ':';
3162
}
3163
3164
memcpy(newPath + preLen + delim, postStart, postLen);
3165
3166
/* Set the NUL terminator at the end */
3167
newPath[preLen + delim + postLen] = '\0';
3168
3169
return newPath;
3170
}
3171
#endif /* AIXPPC */
3172
3173
#if defined(AIXPPC) && defined(DEBUG_TEST)
3174
static void
3175
testBackupAndRestoreLibpath(void)
3176
{
3177
int failed = 0;
3178
int passed = 0;
3179
char *origLibpath = getenv("LIBPATH");
3180
3181
J9LibpathBackup bkp = {NULL, 0};
3182
3183
printf("testBackupAndRestoreLibpath:------------ BEGIN ------------------------\n");
3184
3185
/*
3186
* Typical tests
3187
*/
3188
3189
/* Remove the path added by VM when restoring LIBPATH */
3190
printf("TESTCASE_1: Remove the path added by VM when restoring LIBPATH\n");
3191
setLibpath("compressedrefs:/usr/lib");
3192
backupLibpath(&bkp, strlen("/usr/lib"));
3193
restoreLibpath(&bkp);
3194
if (0 == strcmp(getenv("LIBPATH"), "/usr/lib")) {
3195
printf("Test result: PASSED at </usr/lib>\n");
3196
passed++;
3197
} else {
3198
fprintf(stderr, "Test result: FAILED at </usr/lib>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3199
failed++;
3200
}
3201
3202
/* Ignore multiple colons prefixing the backup path when restoring LIBPATH */
3203
printf("TESTCASE_2: Ignore colons prefixing the backup path when restoring LIBPATH\n");
3204
setLibpath("::abc");
3205
backupLibpath(&bkp, strlen("abc"));
3206
restoreLibpath(&bkp);
3207
if (0 == strcmp(getenv("LIBPATH"), "abc")) {
3208
printf("Test result: PASSED at <abc>\n");
3209
passed++;
3210
} else {
3211
fprintf(stderr, "Test result: FAILED at <abc>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3212
failed++;
3213
}
3214
3215
/*
3216
* Test fullpath searching
3217
*/
3218
3219
/* Set up LIBPATH again with exactly the same path */
3220
printf("TESTCASE_3: Set up libpath again with exactly the same path\n");
3221
setLibpath("x:y");
3222
backupLibpath(&bkp, 0);
3223
setLibpath("x:y");
3224
restoreLibpath(&bkp);
3225
if (0 == strcmp(getenv("LIBPATH"), "")) {
3226
printf("testcase_3: PASSED at <>\n");
3227
passed++;
3228
} else {
3229
fprintf(stderr, "testcase_3: FAILED at <>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3230
failed++;
3231
}
3232
3233
/* The backup path is followed by a single colon */
3234
printf("TESTCASE_4: The backup path is followed by a single colon\n");
3235
setLibpath("x:y");
3236
backupLibpath(&bkp, 0);
3237
setLibpath("x:y:");
3238
restoreLibpath(&bkp);
3239
if (0 == strcmp(getenv("LIBPATH"), "")) {
3240
printf("testcase_4: PASSED at <>\n");
3241
passed++;
3242
} else {
3243
fprintf(stderr, "testcase_4: FAILED at <>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3244
failed++;
3245
}
3246
3247
/* The backup path is followed by multiple colons */
3248
printf("TESTCASE_5: The backup path is followed by multiple colons\n");
3249
setLibpath("x:y");
3250
backupLibpath(&bkp, 0);
3251
setLibpath("x:y:::");
3252
restoreLibpath(&bkp);
3253
if (0 == strcmp(getenv("LIBPATH"), "")) {
3254
printf("TESTCASE_5: PASSED at <>\n");
3255
passed++;
3256
} else {
3257
fprintf(stderr, "TESTCASE_5: FAILED at <>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3258
failed++;
3259
}
3260
3261
/* The backup path is followed by multiple paths */
3262
printf("TESTCASE_6: The backup path is followed by multiple paths\n");
3263
setLibpath("x:y");
3264
backupLibpath(&bkp, 0);
3265
setLibpath("x:y:def:ghi");
3266
restoreLibpath(&bkp);
3267
if (0 == strcmp(getenv("LIBPATH"), "def:ghi")) {
3268
printf("TESTCASE_6: PASSED at <def:ghi>\n");
3269
passed++;
3270
} else {
3271
fprintf(stderr, "TESTCASE_6: FAILED at <def:ghi>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3272
failed++;
3273
}
3274
3275
/* The backup path stays at the start except for a single colon */
3276
printf("TESTCASE_7: The backup path stays at the start except for a single colon\n");
3277
setLibpath("x:y");
3278
backupLibpath(&bkp, 0);
3279
setLibpath(":x:y:def:ghi");
3280
restoreLibpath(&bkp);
3281
if (0 == strcmp(getenv("LIBPATH"), "def:ghi")) {
3282
printf("TESTCASE_7: PASSED at <def:ghi>\n");
3283
passed++;
3284
} else {
3285
fprintf(stderr, "TESTCASE_7: FAILED at <def:ghi>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3286
failed++;
3287
}
3288
3289
/* The backup path stays at the start except for multiple colons */
3290
printf("TESTCASE_8: The backup path stays at the start except for multiple colons\n");
3291
setLibpath("x:y");
3292
backupLibpath(&bkp, 0);
3293
setLibpath(":::x:y:def:ghi");
3294
restoreLibpath(&bkp);
3295
if (0 == strcmp(getenv("LIBPATH"), "def:ghi")) {
3296
printf("TESTCASE_8: PASSED at <def:ghi>\n");
3297
passed++;
3298
} else {
3299
fprintf(stderr, "TESTCASE_8: FAILED at <def:ghi>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3300
failed++;
3301
}
3302
3303
/* Partial match at the start */
3304
printf("TESTCASE_9: Partial match at the start\n");
3305
setLibpath("x:y");
3306
backupLibpath(&bkp, 0);
3307
setLibpath("::x:ydef:ghi");
3308
restoreLibpath(&bkp);
3309
if (0 == strcmp(getenv("LIBPATH"), "::x:ydef:ghi")) {
3310
printf("TESTCASE_9: PASSED at <::x:ydef:ghi>\n");
3311
passed++;
3312
} else {
3313
fprintf(stderr, "TESTCASE_9: FAILED at <::x:ydef:ghi>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3314
failed++;
3315
}
3316
3317
/* Partial match at the end */
3318
printf("TESTCASE_10: Partial match at the end\n");
3319
setLibpath("x:y");
3320
backupLibpath(&bkp, 0);
3321
setLibpath("::abc:defx:y::");
3322
restoreLibpath(&bkp);
3323
if (0 == strcmp(getenv("LIBPATH"), "::abc:defx:y::")) {
3324
printf("TESTCASE_10: PASSED at <::abc:defx:y::>\n");
3325
passed++;
3326
} else {
3327
fprintf(stderr, "TESTCASE_10: FAILED at <::abc:defx:y::>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3328
failed++;
3329
}
3330
3331
/* Partial match in the middle */
3332
printf("TESTCASE_11: Partial match in the middle \n");
3333
setLibpath("x:y");
3334
backupLibpath(&bkp, 0);
3335
setLibpath("::abc:def::x:yghi:jkl");
3336
restoreLibpath(&bkp);
3337
if (0 == strcmp(getenv("LIBPATH"), "::abc:def::x:yghi:jkl")) {
3338
printf("TESTCASE_11: PASSED at <::abc:def::x:yghi:jkl>\n");
3339
passed++;
3340
} else {
3341
fprintf(stderr, "TESTCASE_11: FAILED at <::abc:def::x:yghi:jkl>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3342
failed++;
3343
}
3344
3345
/* The backup path stays at the end with a single colon ahead of it */
3346
printf("TESTCASE_12: The backup path stays at the end with a single colon ahead of it\n");
3347
setLibpath("x:y");
3348
backupLibpath(&bkp, 0);
3349
setLibpath(":x:y");
3350
restoreLibpath(&bkp);
3351
if (0 == strcmp(getenv("LIBPATH"), "")) {
3352
printf("TESTCASE_12: PASSED at <>\n");
3353
passed++;
3354
} else {
3355
fprintf(stderr, "TESTCASE_12: FAILED at <>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3356
failed++;
3357
}
3358
3359
/* The backup path stays at the end with multiple colons ahead of it */
3360
printf("TESTCASE_13: The backup path stays at the end with multiple colons ahead of it\n");
3361
setLibpath("x:y");
3362
backupLibpath(&bkp, 0);
3363
setLibpath("::x:y");
3364
restoreLibpath(&bkp);
3365
if (0 == strcmp(getenv("LIBPATH"), "")) {
3366
printf("TESTCASE_13: PASSED at <>\n");
3367
passed++;
3368
} else {
3369
fprintf(stderr, "TESTCASE_13: FAILED at <>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3370
failed++;
3371
}
3372
3373
/* The backup path stays at the end with multiple paths ahead of it */
3374
printf("TESTCASE_14: The backup path stays at the end with multiple paths ahead of it\n");
3375
setLibpath("x:y");
3376
backupLibpath(&bkp, 0);
3377
setLibpath("abc:def:x:y");
3378
restoreLibpath(&bkp);
3379
if (0 == strcmp(getenv("LIBPATH"), "abc:def")) {
3380
printf("TESTCASE_14: PASSED at <abc:def>\n");
3381
passed++;
3382
} else {
3383
fprintf(stderr, "TESTCASE_14: FAILED at <abc:def>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3384
failed++;
3385
}
3386
3387
/* The backup path stays at the end with multiple empty paths ahead of it */
3388
printf("TESTCASE_15: The backup path stays at the end with multiple empty paths ahead of it\n");
3389
setLibpath("x:y");
3390
backupLibpath(&bkp, 0);
3391
setLibpath("abc:::def:x:y");
3392
restoreLibpath(&bkp);
3393
if (0 == strcmp(getenv("LIBPATH"), "abc:::def")) {
3394
printf("TESTCASE_15: PASSED at <abc:::def>\n");
3395
passed++;
3396
} else {
3397
fprintf(stderr, "TESTCASE_15: FAILED at <abc:::def>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3398
failed++;
3399
}
3400
3401
/* An empty path plus a single colon at the start stays ahead of the backup path */
3402
printf("TESTCASE_16: An empty path plus a single colon at the start stays ahead of the backup path\n");
3403
setLibpath("x:y");
3404
backupLibpath(&bkp, 0);
3405
setLibpath(":abc::def:x:y");
3406
restoreLibpath(&bkp);
3407
if (0 == strcmp(getenv("LIBPATH"), ":abc::def")) {
3408
printf("TESTCASE_16: PASSED at <:abc::def>\n");
3409
passed++;
3410
} else {
3411
fprintf(stderr, "TESTCASE_16: FAILED at <:abc::def>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3412
failed++;
3413
}
3414
3415
/* Multiple empty paths plus a single colon at the start stays ahead of the backup path */
3416
printf("TESTCASE_17: Multiple empty paths plus a single colon at the start stays ahead of the backup patht\n");
3417
setLibpath("x:y");
3418
backupLibpath(&bkp, 0);
3419
setLibpath(":abc::def::x:y");
3420
restoreLibpath(&bkp);
3421
if (0 == strcmp(getenv("LIBPATH"), ":abc::def")) {
3422
printf("TESTCASE_17: PASSED at <:abc::def>\n");
3423
passed++;
3424
} else {
3425
fprintf(stderr, "TESTCASE_17: FAILED at <:abc::def>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3426
failed++;
3427
}
3428
3429
/* The backup path stays at the end except for a single colon */
3430
printf("TESTCASE_18: The backup path stays at the end except for a single colon\n");
3431
setLibpath("x:y");
3432
backupLibpath(&bkp, 0);
3433
setLibpath("abc:def:x:y:");
3434
restoreLibpath(&bkp);
3435
if (0 == strcmp(getenv("LIBPATH"), "abc:def")) {
3436
printf("TESTCASE_18: PASSED at <abc:def>\n");
3437
passed++;
3438
} else {
3439
fprintf(stderr, "TESTCASE_18: FAILED at <abc:def>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3440
failed++;
3441
}
3442
3443
/* The backup path stays at the end except for an empty path */
3444
printf("TESTCASE_19: The backup path stays at the end except for an empty path\n");
3445
setLibpath("x:y");
3446
backupLibpath(&bkp, 0);
3447
setLibpath("abc:def:x:y::");
3448
restoreLibpath(&bkp);
3449
if (0 == strcmp(getenv("LIBPATH"), "abc:def")) {
3450
printf("TESTCASE_19: PASSED at <abc:def>\n");
3451
passed++;
3452
} else {
3453
fprintf(stderr, "TESTCASE_19: FAILED at <abc:def>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3454
failed++;
3455
}
3456
3457
/* The backup path comes with a trailing colon */
3458
printf("TESTCASE_20: The backup path comes with a trailing colon\n");
3459
setLibpath("x:y:");
3460
backupLibpath(&bkp, 0);
3461
setLibpath("abc:x:y:ghi");
3462
restoreLibpath(&bkp);
3463
if (0 == strcmp(getenv("LIBPATH"), "abc:ghi")) {
3464
printf("TESTCASE_20: PASSED at <abc:ghi>\n");
3465
passed++;
3466
} else {
3467
fprintf(stderr, "TESTCASE_20: FAILED at <abc:ghi>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3468
failed++;
3469
}
3470
3471
/* The backup path comes with a leading colon */
3472
printf("TESTCASE_21: The backup path comes with a leading colon\n");
3473
setLibpath(":x:y");
3474
backupLibpath(&bkp, 0);
3475
setLibpath("::abc:def::x:y:ghi");
3476
restoreLibpath(&bkp);
3477
if (0 == strcmp(getenv("LIBPATH"), "::abc:def:ghi")) {
3478
printf("TESTCASE_21: PASSED at <::abc:def:ghi>\n");
3479
passed++;
3480
} else {
3481
fprintf(stderr, "TESTCASE_21: FAILED at <::abc:def:ghi>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3482
failed++;
3483
}
3484
3485
/*
3486
* Test path deletion
3487
*/
3488
3489
/* Delete from the start when restoring LIBPATH */
3490
printf("TESTCASE_22: Delete from the start when restoring LIBPATH\n");
3491
setLibpath("abc::def:xyz");
3492
backupLibpath(&bkp, strlen("xyz"));
3493
setLibpath("abc::def:xyz:morestuff");
3494
restoreLibpath(&bkp);
3495
if (0 == strcmp(getenv("LIBPATH"), "xyz:morestuff")) {
3496
printf("TESTCASE_22: PASSED at <xyz:morestuff>\n");
3497
passed++;
3498
} else {
3499
fprintf(stderr, "TESTCASE_22: FAILED at <xyz:morestuff>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3500
failed++;
3501
}
3502
3503
/* Delete from the middle when restoring LIBPATH */
3504
printf("TESTCASE_23: Delete from the middle when restoring LIBPATH\n");
3505
setLibpath("abc::def:xyz");
3506
backupLibpath(&bkp, strlen("xyz"));
3507
setLibpath(":stuff:abc::def:xyz:morestuff");
3508
restoreLibpath(&bkp);
3509
if (0 == strcmp(getenv("LIBPATH"), ":stuff:xyz:morestuff")) {
3510
printf("TESTCASE_23: PASSED at <:stuff:xyz:morestuff>\n");
3511
passed++;
3512
} else {
3513
fprintf(stderr, "TESTCASE_23: FAILED at <:stuff:xyz:morestuff>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3514
failed++;
3515
}
3516
3517
/* Delete from the end when restoring LIBPATH */
3518
printf("TESTCASE_24: Delete from the end when restoring LIBPATH\n");
3519
setLibpath("abc::def:xyz");
3520
backupLibpath(&bkp, strlen("xyz"));
3521
setLibpath(":stuff:morestuff:abc::def:xyz");
3522
restoreLibpath(&bkp);
3523
if (0 == strcmp(getenv("LIBPATH"), ":stuff:morestuff:xyz")) {
3524
printf("TESTCASE_24: PASSED at <:stuff:morestuff:xyz>\n");
3525
passed++;
3526
} else {
3527
fprintf(stderr, "TESTCASE_24: FAILED at <:stuff:morestuff:xyz>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3528
failed++;
3529
}
3530
3531
/* Ignore colons in the prefix when restoring LIBPATH */
3532
printf("TESTCASE_25: Ignore colons in the prefix when restoring LIBPATH\n");
3533
setLibpath("abc::def::xyz");
3534
backupLibpath(&bkp, strlen("xyz"));
3535
setLibpath("stuff:abc::def::xyz:morestuff");
3536
restoreLibpath(&bkp);
3537
if (0 == strcmp(getenv("LIBPATH"), "stuff:xyz:morestuff")) {
3538
printf("TESTCASE_25: PASSED at <stuff:xyz:morestuff>\n");
3539
passed++;
3540
} else {
3541
fprintf(stderr, "TESTCASE_25: FAILED at <stuff:xyz:morestuff>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3542
failed++;
3543
}
3544
3545
/* Skip colons from both start and end when restoring LIBPATH */
3546
printf("TESTCASE_26: Skip colons from both start and end when restoring LIBPATH\n");
3547
setLibpath("abc::def:");
3548
backupLibpath(&bkp, 0);
3549
setLibpath("::abc::def::");
3550
restoreLibpath(&bkp);
3551
if (0 == strcmp(getenv("LIBPATH"), "")) {
3552
printf("TESTCASE_26: PASSED at <>\n");
3553
passed++;
3554
} else {
3555
fprintf(stderr, "TESTCASE_26: FAILED at <>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3556
failed++;
3557
}
3558
3559
/* Insert colon from the end when restoring LIBPATH */
3560
printf("TESTCASE_27: Insert colon from the end when restoring LIBPATH\n");
3561
setLibpath(":abc::def:xyz");
3562
backupLibpath(&bkp, strlen("xyz"));
3563
setLibpath("stuff:abc::def:xyz:morestuff");
3564
restoreLibpath(&bkp);
3565
if (0 == strcmp(getenv("LIBPATH"), "stuff:xyz:morestuff")) {
3566
printf("TESTCASE_27: PASSED at <stuff:xyz:morestuff>\n");
3567
passed++;
3568
} else {
3569
fprintf(stderr, "TESTCASE_27: FAILED at <stuff:xyz:morestuff>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3570
failed++;
3571
}
3572
3573
/* Empty backup path before restoring LIBPATH */
3574
printf("TESTCASE_28: Empty backup path before restoring LIBPATH\n");
3575
setLibpath("");
3576
backupLibpath(&bkp, 0);
3577
setLibpath("stuff:abc::def:xyz:morestuff");
3578
restoreLibpath(&bkp);
3579
if (0 == strcmp(getenv("LIBPATH"), "stuff:abc::def:xyz:morestuff")) {
3580
printf("TESTCASE_28: PASSED at <stuff:abc::def:xyz:morestuff>\n");
3581
passed++;
3582
} else {
3583
fprintf(stderr, "TESTCASE_28: FAILED at <stuff:abc::def:xyz:morestuff>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3584
failed++;
3585
}
3586
3587
/* Keep backup path and empty prefix when restoring LIBPATH */
3588
printf("TESTCASE_29: Keep backup path and empty prefix when restoring LIBPATH\n");
3589
setLibpath("abc:def");
3590
backupLibpath(&bkp, strlen("abc:def"));
3591
setLibpath("stuff:abc:def:xyz:morestuff");
3592
restoreLibpath(&bkp);
3593
if (0 == strcmp(getenv("LIBPATH"), "stuff:abc:def:xyz:morestuff")) {
3594
printf("TESTCASE_29: PASSED at <stuff:abc:def:xyz:morestuff>\n");
3595
passed++;
3596
} else {
3597
fprintf(stderr, "TESTCASE_29: FAILED at <stuff:abc:def:xyz:morestuff>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3598
failed++;
3599
}
3600
3601
/* The length of current path is greater than the backup path when restoring LIBPATH */
3602
printf("TESTCASE_30: The length of current path is greater than the backup path when restoring LIBPATH\n");
3603
setLibpath("abc:def:ghi");
3604
backupLibpath(&bkp, 0);
3605
setLibpath("abc:def");
3606
restoreLibpath(&bkp);
3607
if (0 == strcmp(getenv("LIBPATH"), "abc:def")) {
3608
printf("TESTCASE_30: PASSED at <abc:def>\n");
3609
passed++;
3610
} else {
3611
fprintf(stderr, "TESTCASE_30: FAILED at <abc:def>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3612
failed++;
3613
}
3614
3615
/* The backup path is prefixed by multiple colons */
3616
printf("TESTCASE_31: The backup path is prefixed by multiple colons\n");
3617
setLibpath(":::abc");
3618
backupLibpath(&bkp, strlen("abc"));
3619
setLibpath("abc");
3620
restoreLibpath(&bkp);
3621
if (0 == strcmp(getenv("LIBPATH"), "abc")) {
3622
printf("TESTCASE_31: PASSED at <abc>\n");
3623
passed++;
3624
} else {
3625
fprintf(stderr, "TESTCASE_31: FAILED at <abc>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3626
failed++;
3627
}
3628
3629
/* Only VM prefix exists in the backup path when restoring LIBPATH */
3630
printf("TESTCASE_32: Only VM prefix exists in the backup path when restoring LIBPATH\n");
3631
setLibpath(":::abc");
3632
backupLibpath(&bkp, 0);
3633
setLibpath("abc");
3634
restoreLibpath(&bkp);
3635
if (0 == strcmp(getenv("LIBPATH"), "abc")) {
3636
printf("TESTCASE_32: PASSED at <abc>\n");
3637
passed++;
3638
} else {
3639
fprintf(stderr, "TESTCASE_32: FAILED at <abc>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3640
failed++;
3641
}
3642
3643
/* Colons prefixing the backup LIBPATH is more than that of the current LIBPATH */
3644
printf("TESTCASE_33: Colons prefixing the backup LIBPATH is more than that of the current LIBPATH\n");
3645
setLibpath(":::abc:xyz");
3646
backupLibpath(&bkp, strlen("abc:xyz"));
3647
setLibpath("def::abc:xyz");
3648
restoreLibpath(&bkp);
3649
if (0 == strcmp(getenv("LIBPATH"), "def::abc:xyz")) {
3650
printf("TESTCASE_33: PASSED at <def::abc:xyz>\n");
3651
passed++;
3652
} else {
3653
fprintf(stderr, "TESTCASE_33: FAILED at <def::abc:xyz>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3654
failed++;
3655
}
3656
3657
/* Colons prefixing the backup LIBPATH is less than that of the current LIBPATH (1) */
3658
printf("TESTCASE_34: Colons prefixing the backup LIBPATH is less than that of the current LIBPATH (1)\n");
3659
setLibpath(":::abc:xyz");
3660
backupLibpath(&bkp, strlen("abc:xyz"));
3661
setLibpath("def:::abc:xyz");
3662
restoreLibpath(&bkp);
3663
if (0 == strcmp(getenv("LIBPATH"), "def:abc:xyz")) {
3664
printf("TESTCASE_34: PASSED at <def:abc:xyz>\n");
3665
passed++;
3666
} else {
3667
fprintf(stderr, "TESTCASE_34: FAILED at <def:abc:xyz>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3668
failed++;
3669
}
3670
3671
/* Colons prefixing the backup LIBPATH is less than that of the current LIBPATH (2) */
3672
printf("TESTCASE_35: Colons prefixing the backup LIBPATH is less than that of the current LIBPATH (2)\n");
3673
setLibpath(":::abc:xyz");
3674
backupLibpath(&bkp, strlen("abc:xyz"));
3675
setLibpath("def::::abc:xyz");
3676
restoreLibpath(&bkp);
3677
if (0 == strcmp(getenv("LIBPATH"), "def:abc:xyz")) {
3678
printf("TESTCASE_35: PASSED at <def:abc:xyz>\n");
3679
passed++;
3680
} else {
3681
fprintf(stderr, "TESTCASE_35: FAILED at <def:abc:xyz>: LIBPATH = <%s>\n", getenv("LIBPATH"));
3682
failed++;
3683
}
3684
3685
printf("---------- TEST RESULTS ----------\n");
3686
printf("Number of PASSED tests: %d\n", passed);
3687
printf("Number of FAILED tests: %d\n", failed);
3688
3689
if (0 == failed) {
3690
printf("testBackupAndRestoreLibpath:---- TEST_PASSED ---------\n");
3691
} else {
3692
printf("testBackupAndRestoreLibpath:---- TEST_FAILED ---------\n");
3693
}
3694
3695
setLibpath(origLibpath);
3696
}
3697
#endif /* AIXPPC and DEBUG_TEST */
3698
3699
#if defined(WIN32)
3700
3701
static jint
3702
formatErrorMessage(int errorCode, char *inBuffer, jint inBufferLength)
3703
{
3704
size_t i=0;
3705
int rc = 0, j=0;
3706
size_t outLength, lastChar;
3707
_TCHAR buffer[JVM_DEFAULT_ERROR_BUFFER_SIZE];
3708
_TCHAR noCRLFbuffer[JVM_DEFAULT_ERROR_BUFFER_SIZE];
3709
3710
if (inBufferLength <= 1) {
3711
if (inBufferLength == 1) {
3712
inBuffer[0] = '\0';
3713
}
3714
return 0;
3715
}
3716
3717
rc = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, JVM_DEFAULT_ERROR_BUFFER_SIZE, NULL );
3718
if (rc == 0) {
3719
inBuffer[0] = '\0';
3720
return 0;
3721
}
3722
3723
j=0;
3724
for (i = 0; i < _tcslen(buffer)+1 ; i++) {
3725
if(buffer[i] == _TEXT('\n') ) {
3726
noCRLFbuffer[j++]=_TEXT(' ');
3727
} else if(buffer[i] == _TEXT('\r')) {
3728
continue;
3729
} else {
3730
noCRLFbuffer[j++]=buffer[i];
3731
}
3732
}
3733
3734
lastChar = _tcslen(noCRLFbuffer)-1;
3735
3736
if(_istspace(noCRLFbuffer[lastChar])) {
3737
noCRLFbuffer[lastChar] = _TEXT('\0');
3738
}
3739
3740
/* We always return multibyte */
3741
3742
#ifdef UNICODE
3743
outLength = WideCharToMultiByte(CP_UTF8, 0, noCRLFbuffer, -1, inBuffer, inBufferLength-1, NULL, NULL);
3744
#else
3745
outLength = strlen(noCRLFbuffer)+1;
3746
if(outLength > (size_t)inBufferLength) {
3747
outLength = (size_t)inBufferLength;
3748
}
3749
strncpy(inBuffer, noCRLFbuffer, outLength);
3750
inBuffer[inBufferLength-1]='\0';
3751
#endif
3752
3753
Assert_SC_true(outLength <= I_32_MAX);
3754
return (jint)outLength;
3755
}
3756
3757
#endif /* WIN32 */
3758
3759
static UDATA
3760
protectedStrerror(J9PortLibrary* portLib, void* savedErrno)
3761
{
3762
return (UDATA) strerror((int) (IDATA) savedErrno);
3763
}
3764
3765
3766
static UDATA
3767
strerrorSignalHandler(struct J9PortLibrary* portLibrary, U_32 gpType, void* gpInfo, void* userData)
3768
{
3769
return J9PORT_SIG_EXCEPTION_RETURN;
3770
}
3771
3772
static void
3773
throwNewUnsatisfiedLinkError(JNIEnv *env, char *message)
3774
{
3775
jclass exceptionClass = (*env)->FindClass(env, "java/lang/UnsatisfiedLinkError");
3776
if (NULL != exceptionClass) {
3777
(*env)->ThrowNew(env, exceptionClass, message);
3778
}
3779
}
3780
3781
/*
3782
* Remove one segment of a path.
3783
*/
3784
static void
3785
truncatePath(char *inputPath) {
3786
char *lastOccurence = strrchr(inputPath, DIR_SEPARATOR);
3787
/* strrchr() returns NULL if it cannot find the character */
3788
if (NULL != lastOccurence) {
3789
*lastOccurence = '\0';
3790
}
3791
}
3792
3793
/**********************************************************************
3794
* JVM_ functions start here
3795
**********************************************************************/
3796
3797
/**
3798
* void JNICALL JVM_OnExit(void *ptr)
3799
* This function seems to be required by fontmanager.dll but is not
3800
* called?
3801
*
3802
* @param exitCode?
3803
*
3804
* @returns ?
3805
*
3806
* DLL: jvm
3807
*/
3808
void JNICALL
3809
JVM_OnExit(void (*func)(void))
3810
{
3811
J9SidecarExitFunction * newFunc;
3812
3813
Trc_SC_OnExit_Entry(func);
3814
3815
newFunc = (J9SidecarExitFunction *) malloc(sizeof(J9SidecarExitFunction));
3816
if (newFunc) {
3817
newFunc->func = func;
3818
3819
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
3820
omrthread_monitor_enter(BFUjavaVM->vmThreadListMutex);
3821
#else
3822
f_monitorEnter(BFUjavaVM->vmThreadListMutex);
3823
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
3824
3825
newFunc->next = BFUjavaVM->sidecarExitFunctions;
3826
BFUjavaVM->sidecarExitFunctions = newFunc;
3827
3828
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
3829
omrthread_monitor_exit(BFUjavaVM->vmThreadListMutex);
3830
#else
3831
f_monitorExit(BFUjavaVM->vmThreadListMutex);
3832
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
3833
3834
BFUjavaVM->sidecarExitHook = &exitHook;
3835
} else {
3836
Trc_SC_OnExit_OutOfMemory();
3837
}
3838
3839
Trc_SC_OnExit_Exit(newFunc);
3840
}
3841
3842
/**
3843
* void * JNICALL JVM_LoadSystemLibrary(char *libName)
3844
*
3845
* Attempts to load the shared library specified by libName. If
3846
* successful, returns the file handle, otherwise returns NULL.
3847
*
3848
* @param libName a null terminated string containing the libName.
3849
*
3850
* @return the shared library's handle if successful, throws java/lang/UnsatisfiedLinkError on failure
3851
*/
3852
void* JNICALL
3853
JVM_LoadSystemLibrary(const char *libName)
3854
{
3855
#ifdef WIN32
3856
UDATA dllHandle = 0;
3857
size_t libNameLen = strlen(libName);
3858
UDATA flags = 0;
3859
3860
Trc_SC_LoadSystemLibrary_Entry(libName);
3861
3862
if ((libNameLen <= 4) ||
3863
('.' != libName[libNameLen - 4]) ||
3864
('d' != j9_cmdla_tolower(libName[libNameLen - 3])) ||
3865
('l' != j9_cmdla_tolower(libName[libNameLen - 2])) ||
3866
('l' != j9_cmdla_tolower(libName[libNameLen - 1])))
3867
{
3868
flags = J9PORT_SLOPEN_DECORATE;
3869
}
3870
3871
if (0 == j9util_open_system_library((char *)libName, &dllHandle, flags)) {
3872
Trc_SC_LoadSystemLibrary_Exit(dllHandle);
3873
return (void *)dllHandle;
3874
}
3875
#endif
3876
3877
#if defined(J9UNIX) || defined(J9ZOS390)
3878
void *dllHandle = NULL;
3879
3880
Trc_SC_LoadSystemLibrary_Entry(libName);
3881
3882
#if defined(AIXPPC)
3883
/* CMVC 137341:
3884
* dlopen() searches for libraries using the LIBPATH envvar as it was when the process
3885
* was launched. This causes multiple issues such as:
3886
* - finding 32 bit binaries for libomrsig.so instead of the 64 bit binary needed and vice versa
3887
* - finding compressed reference binaries instead of non-compressed ref binaries
3888
*
3889
* calling loadAndInit(libname, 0 -> no flags, NULL -> use the currently defined LIBPATH) allows
3890
* us to load the library with the current libpath instead of the one at process creation
3891
* time. We can then call dlopen() as per normal and the just loaded library will be found.
3892
* */
3893
loadAndInit((char *)libName, L_RTLD_LOCAL, NULL);
3894
#endif /* defined(AIXPPC) */
3895
dllHandle = dlopen((char *)libName, RTLD_LAZY);
3896
if (NULL != dllHandle) {
3897
Trc_SC_LoadSystemLibrary_Exit(dllHandle);
3898
return dllHandle;
3899
}
3900
3901
#endif /* defined(J9UNIX) || defined(J9ZOS390) */
3902
3903
/* We are here means we failed to load library. Throw java.lang.UnsatisfiedLinkError */
3904
Trc_SC_LoadSystemLibrary_LoadFailed(libName);
3905
3906
if (NULL != BFUjavaVM) {
3907
JNIEnv *env = NULL;
3908
JavaVM *vm = (JavaVM *)BFUjavaVM;
3909
(*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_2);
3910
if (NULL != env) {
3911
char errMsg[512];
3912
jio_snprintf(errMsg, sizeof(errMsg), "Failed to load library \"%s\"", libName);
3913
errMsg[sizeof(errMsg) - 1] = '\0';
3914
throwNewUnsatisfiedLinkError(env, errMsg);
3915
}
3916
}
3917
Trc_SC_LoadSystemLibrary_Exit(NULL);
3918
3919
return NULL;
3920
}
3921
3922
/**
3923
* Prior to jdk17:
3924
* void * JNICALL JVM_LoadLibrary(char *libName)
3925
*
3926
* Beginning in jdk17:
3927
* void * JNICALL JVM_LoadLibrary(char *libName, jboolean throwOnFailure)
3928
*
3929
* Attempts to load the shared library specified by libName.
3930
* If successful, returns the file handle, otherwise returns NULL or throws
3931
* UnsatisfiedLinkError if throwOnFailure.
3932
*
3933
* @param libName a null terminated string containing the libName.
3934
* For Windows platform, this incoming libName is encoded as J9STR_CODE_WINDEFAULTACP,
3935
* and is required to be converted to J9STR_CODE_MUTF8 for internal usages.
3936
*
3937
* @return the shared library's handle if successful, throws java/lang/UnsatisfiedLinkError on failure
3938
*
3939
* DLL: jvm
3940
*
3941
* NOTE this is required by jdk15+ jdk.internal.loader.NativeLibraries.load().
3942
* It is only invoked by jdk.internal.loader.BootLoader.loadLibrary().
3943
*/
3944
void * JNICALL
3945
#if JAVA_SPEC_VERSION < 17
3946
JVM_LoadLibrary(const char *libName)
3947
#else /* JAVA_SPEC_VERSION < 17 */
3948
JVM_LoadLibrary(const char *libName, jboolean throwOnFailure)
3949
#endif /* JAVA_SPEC_VERSION < 17 */
3950
{
3951
void *result = NULL;
3952
J9JavaVM *javaVM = (J9JavaVM *)BFUjavaVM;
3953
PORT_ACCESS_FROM_JAVAVM(javaVM);
3954
3955
#if defined(WIN32)
3956
char *libNameConverted = NULL;
3957
UDATA libNameLen = strlen(libName);
3958
UDATA libNameLenConverted = j9str_convert(J9STR_CODE_WINDEFAULTACP, J9STR_CODE_MUTF8, libName, libNameLen, NULL, 0);
3959
if (libNameLenConverted > 0) {
3960
libNameLenConverted += 1; /* an extra byte for null */
3961
libNameConverted = j9mem_allocate_memory(libNameLenConverted, OMRMEM_CATEGORY_VM);
3962
if (NULL != libNameConverted) {
3963
libNameLenConverted = j9str_convert(J9STR_CODE_WINDEFAULTACP, J9STR_CODE_MUTF8, libName, libNameLen, libNameConverted, libNameLenConverted);
3964
if (libNameLenConverted > 0) {
3965
/* j9str_convert null-terminated the string */
3966
libName = libNameConverted;
3967
}
3968
}
3969
}
3970
if (libName == libNameConverted) {
3971
#endif /* defined(WIN32) */
3972
Trc_SC_LoadLibrary_Entry(libName);
3973
{
3974
UDATA handle = 0;
3975
UDATA flags = J9_ARE_ANY_BITS_SET(javaVM->extendedRuntimeFlags, J9_EXTENDED_RUNTIME_LAZY_SYMBOL_RESOLUTION) ? J9PORT_SLOPEN_LAZY : 0;
3976
UDATA slOpenResult = j9sl_open_shared_library((char *)libName, &handle, flags);
3977
3978
Trc_SC_LoadLibrary_OpenShared(libName);
3979
if (0 != slOpenResult) {
3980
slOpenResult = j9sl_open_shared_library((char *)libName, &handle, flags | J9PORT_SLOPEN_DECORATE);
3981
Trc_SC_LoadLibrary_OpenShared_Decorate(libName);
3982
}
3983
if (0 == slOpenResult) {
3984
result = (void *)handle;
3985
}
3986
}
3987
#if defined(WIN32)
3988
}
3989
if (NULL != libNameConverted) {
3990
j9mem_free_memory(libNameConverted);
3991
}
3992
#endif /* defined(WIN32) */
3993
3994
#if JAVA_SPEC_VERSION >= 17
3995
if ((NULL == result) && throwOnFailure) {
3996
JNIEnv *env = NULL;
3997
JavaVM *vm = (JavaVM *)javaVM;
3998
(*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_2);
3999
if (NULL != env) {
4000
char errMsg[512];
4001
jio_snprintf(errMsg, sizeof(errMsg), "Failed to load library \"%s\"", libName);
4002
errMsg[sizeof(errMsg) - 1] = '\0';
4003
throwNewUnsatisfiedLinkError(env, errMsg);
4004
}
4005
}
4006
#endif /* JAVA_SPEC_VERSION >= 17 */
4007
4008
Trc_SC_LoadLibrary_Exit(result);
4009
4010
return result;
4011
}
4012
4013
4014
/**
4015
* void* JNICALL JVM_FindLibraryEntry(UDATA handle, char *functionName)
4016
* Returns a pointer to a function specified by the string
4017
* functionName within a given library specified by handle.
4018
*
4019
* @param handle the DLL's handle.
4020
* @param functionName null terminated function name.
4021
*
4022
* @returns a pointer to the given function.
4023
*
4024
* DLL: jvm
4025
*/
4026
4027
/* NOTE THIS IS NOT REQUIRED FOR 1.4 */
4028
4029
void* JNICALL
4030
JVM_FindLibraryEntry(void* handle, const char *functionName)
4031
{
4032
void* result;
4033
4034
Trc_SC_FindLibraryEntry_Entry(handle, functionName);
4035
4036
#if defined(WIN32)
4037
result = GetProcAddress ((HINSTANCE)handle, (LPCSTR)functionName);
4038
#elif defined(J9UNIX) || defined(J9ZOS390) /* defined(WIN32) */
4039
result = (void*)dlsym( (void*)handle, (char *)functionName );
4040
#else /* defined(WIN32) */
4041
#error "Please implement jvm.c:JVM_FindLibraryEntry(void* handle, const char *functionName)"
4042
#endif /* defined(WIN32) */
4043
4044
Trc_SC_FindLibraryEntry_Exit(result);
4045
4046
return result;
4047
}
4048
4049
4050
/**
4051
* JVM_SetLength
4052
*/
4053
jint JNICALL
4054
JVM_SetLength(jint fd, jlong length)
4055
{
4056
jint result;
4057
4058
Trc_SC_SetLength_Entry(fd, length);
4059
4060
if (fd == -1) {
4061
Trc_SC_SetLength_bad_descriptor();
4062
return -1;
4063
}
4064
4065
#if defined(WIN32_IBMC)
4066
printf("_JVM_SetLength@12 called but not yet implemented. Exiting.");
4067
exit(43);
4068
#elif defined(WIN32) /* defined(WIN32_IBMC) */
4069
result = _chsize(fd, (long)length);
4070
#elif defined(J9UNIX) && !defined(J9ZTPF) && !defined(OSX) /* defined(WIN32_IBMC) */
4071
result = ftruncate64(fd, length);
4072
#elif defined(J9ZOS390) || defined(J9ZTPF) || defined(OSX) /* defined(WIN32_IBMC) */
4073
/* ftruncate64 is unsupported on OSX. */
4074
result = ftruncate(fd, length);
4075
#else /* defined(WIN32_IBMC) */
4076
#error "Please provide an implementation of jvm.c:JVM_SetLength(jint fd, jlong length)"
4077
#endif /* defined(WIN32_IBMC) */
4078
4079
Trc_SC_SetLength_Exit(result);
4080
4081
return result;
4082
}
4083
4084
4085
/**
4086
* JVM_Write
4087
*/
4088
jint JNICALL
4089
JVM_Write(jint descriptor, const char* buffer, jint length)
4090
{
4091
PORT_ACCESS_FROM_JAVAVM(BFUjavaVM);
4092
jint result = 0;
4093
4094
Trc_SC_Write_Entry(descriptor, buffer, length);
4095
4096
if (descriptor == -1) {
4097
Trc_SC_Write_bad_descriptor();
4098
return JVM_IO_ERR;
4099
}
4100
4101
#ifndef J9ZOS390
4102
/* This code SHOULD be for Windows only, but is safe everywhere except z/OS
4103
* (see CMVC 99667 for the fun details of z/OS and POSIX File-handles):
4104
* Map stdout, stderr to the port library as using the
4105
* C library causes CR/LF translation and CR LF turns into CR CR LF.
4106
*/
4107
if ( (descriptor == 1) || (descriptor == 2) ) {
4108
IDATA retval = j9file_write(descriptor, (char *)buffer, length);
4109
if(retval<0) {
4110
result = -1; /* callers seem to expect -1 on failure */
4111
} else {
4112
result = (jint)retval;
4113
Assert_SC_true(retval == (IDATA)result);
4114
}
4115
} else
4116
#endif
4117
{
4118
/* CMVC 178203 - Restart system calls interrupted by EINTR */
4119
do {
4120
result = write(descriptor, buffer, length);
4121
} while ((-1 == result) && (EINTR == errno));
4122
}
4123
4124
Trc_SC_Write_Exit(result);
4125
4126
return result;
4127
}
4128
4129
4130
/**
4131
* JVM_Close
4132
*/
4133
jint JNICALL
4134
JVM_Close(jint descriptor)
4135
{
4136
jint result = 0;
4137
4138
Trc_SC_Close_Entry(descriptor);
4139
4140
if (descriptor == -1) {
4141
Trc_SC_Close_bad_descriptor();
4142
return JVM_IO_ERR;
4143
}
4144
4145
/* Ignore close of stdin, when
4146
* JVM_Read/Write mapped to use the port library
4147
* api/java_io/FileInputStream/index.html#CtorFD
4148
* also ignore close of stdout and stderr */
4149
4150
if (descriptor >= 0 && descriptor <= 2) {
4151
Trc_SC_Close_std_descriptor();
4152
return 0;
4153
}
4154
4155
result = close(descriptor);
4156
4157
Trc_SC_Close_Exit(result);
4158
4159
return result;
4160
}
4161
4162
4163
/**
4164
* JVM_Available
4165
*/
4166
jint JNICALL
4167
JVM_Available(jint descriptor, jlong* bytes)
4168
{
4169
jlong curr = 0;
4170
jlong end = 0;
4171
4172
/* On OSX, stat64 and fstat64 are deprecated.
4173
* Thus, stat and fstat are used on OSX.
4174
*/
4175
#if defined(J9UNIX) && !defined(J9ZTPF) && !defined(OSX)
4176
struct stat64 tempStat;
4177
#endif /* defined(J9UNIX) && !defined(J9ZTPF) && !defined(OSX) */
4178
#if defined(J9ZOS390) || defined(J9ZTPF) || defined(OSX)
4179
struct stat tempStat;
4180
#endif /* defined(J9ZOS390) || defined(J9ZTPF) || defined(OSX) */
4181
#if defined(LINUX)
4182
loff_t longResult = 0;
4183
#endif
4184
4185
Trc_SC_Available_Entry(descriptor, bytes);
4186
4187
if (descriptor == -1) {
4188
Trc_SC_Available_bad_descriptor();
4189
*bytes = 0;
4190
return JNI_FALSE;
4191
}
4192
4193
#if defined(WIN32) && !defined(__IBMC__)
4194
curr = _lseeki64(descriptor, 0, SEEK_CUR);
4195
if (curr==-1L) {
4196
if (descriptor == 0) {
4197
/* Failed on stdin, check input queue. */
4198
DWORD result = 0;
4199
if (GetNumberOfConsoleInputEvents(GetStdHandle(STD_INPUT_HANDLE), &result)) {
4200
*bytes = result;
4201
} else {
4202
*bytes = 0;
4203
}
4204
Trc_SC_Available_Exit(1, *bytes);
4205
return 1;
4206
}
4207
Trc_SC_Available_lseek_failed(descriptor);
4208
return 0; /* Returning zero causes JNU_ThrowIOExceptionWithLastError() */
4209
}
4210
end = _lseeki64(descriptor, 0, SEEK_END);
4211
_lseeki64(descriptor, curr, SEEK_SET);
4212
#else
4213
if (J9FSTAT(descriptor, &tempStat) == -1) {
4214
Trc_SC_Available_fstat_failed(descriptor, errno);
4215
*bytes = 0;
4216
return 0;
4217
}
4218
else if (S_ISFIFO(tempStat.st_mode) || S_ISSOCK(tempStat.st_mode) || S_ISCHR(tempStat.st_mode)) {
4219
/*
4220
arg3 is the third argument to ioctl. The type of this argument is dependent upon the information
4221
being requested. FIONREAD specifies that the argument be a pointer to an int
4222
*/
4223
int arg3FIONREAD = 0;
4224
4225
#if defined(J9ZOS390)
4226
/* CMVC 100066: FIONREAD on z/OS only works for sockets so we need to use fstat, instead */
4227
if (!S_ISSOCK(tempStat.st_mode)) {
4228
/* we already performed the stat, so just return the st_size */
4229
*bytes = tempStat.st_size;
4230
Trc_SC_Available_Exit(1, *bytes);
4231
return 1;
4232
}
4233
#endif
4234
if (ioctl(descriptor, FIONREAD, &(arg3FIONREAD)) == -1) {
4235
if (descriptor == 0) {
4236
/* Failed on stdin, just return st_size. */
4237
*bytes = tempStat.st_size;
4238
Trc_SC_Available_Exit(1, *bytes);
4239
return 1;
4240
}
4241
#if (defined(LINUX) && !defined(J9ZTPF)) || defined(AIXPPC) || defined(J9ZOS390)
4242
else {
4243
struct pollfd pollOne;
4244
int ret = 0;
4245
pollOne.fd = descriptor;
4246
pollOne.events = POLLRDNORM | POLLRDBAND | POLLPRI;
4247
pollOne.revents = 0;
4248
if (-1 != poll(&pollOne, 1, 0)) {
4249
/* poll succeeded (-1 is failure) */
4250
if(0 != (pollOne.events & pollOne.revents)) {
4251
/* if the one descriptor we were looking at returns a modified revents
4252
which matches a read operation, return at least one byte readable */
4253
*bytes = 1;
4254
Trc_SC_Available_Exit(1, *bytes);
4255
return 1;
4256
} else {
4257
/* none of the events are ready so this is 0 bytes readable */
4258
*bytes = 0;
4259
Trc_SC_Available_Exit(1, *bytes);
4260
return 1;
4261
}
4262
} else {
4263
/* poll failed so use a poll failure trace point and return failure */
4264
Trc_SC_Available_poll_failed(descriptor, errno);
4265
*bytes = 0;
4266
return 0;
4267
}
4268
}
4269
#endif
4270
Trc_SC_Available_ioctl_failed(descriptor, errno);
4271
*bytes = 0;
4272
return 0;
4273
}
4274
4275
*bytes = (jlong) arg3FIONREAD;
4276
Trc_SC_Available_Exit(1, *bytes);
4277
return 1;
4278
}
4279
#if defined(LINUX) && !defined(J9VM_ENV_DATA64)
4280
#if __GLIBC_PREREQ(2,4)
4281
/* glibc 2.4 (sles 10) and on provide lseek64() */
4282
curr = lseek64(descriptor, 0, SEEK_CUR);
4283
#else
4284
/* CMVC 104382: Linux lseek uses native word size off_t so we need to use the 64-bit _llseek on 32-bit Linux. AIX and z/OS use 64-bit API implicitly when we define _LARGE_FILES. */
4285
curr = _llseek(descriptor, 0, 0, &longResult, SEEK_CUR);
4286
if (0 == curr) {
4287
/* the call was successful so set the result to what we read */
4288
curr = (jlong) longResult;
4289
}
4290
#endif
4291
#else /* defined(LINUX) && !defined(J9VM_ENV_DATA64) */
4292
curr = lseek(descriptor, 0, SEEK_CUR);
4293
#endif /*!defined (LINUX) || defined(J9VM_ENV_DATA64) */
4294
if (curr==-1L) {
4295
if (descriptor == 0) {
4296
/* Failed on stdin, just return 0. */
4297
*bytes = 0;
4298
Trc_SC_Available_Exit(1, *bytes);
4299
return 1;
4300
}
4301
Trc_SC_Available_lseek_failed(descriptor);
4302
return 0; /* Returning zero causes JNU_ThrowIOExceptionWithLastError() */
4303
}
4304
4305
end = tempStat.st_size; /* size from previous fstat */
4306
#endif
4307
4308
*bytes = (end-curr);
4309
4310
Trc_SC_Available_Exit(1, *bytes);
4311
4312
return 1;
4313
}
4314
4315
4316
4317
/**
4318
* JVM_Lseek
4319
*/
4320
jlong JNICALL
4321
JVM_Lseek(jint descriptor, jlong bytesToSeek, jint origin)
4322
{
4323
jlong result = 0;
4324
#if defined (LINUX)
4325
loff_t longResult = 0;
4326
#endif
4327
4328
Trc_SC_Lseek_Entry(descriptor, bytesToSeek, origin);
4329
4330
if (descriptor == -1) {
4331
Trc_SC_Lseek_bad_descriptor();
4332
return JVM_IO_ERR;
4333
}
4334
4335
#if defined(WIN32)
4336
#ifdef __IBMC__
4337
result = lseek(descriptor, (long) bytesToSeek, origin);
4338
#else
4339
result = _lseeki64(descriptor, bytesToSeek, origin);
4340
#endif
4341
#elif defined(J9UNIX) || defined(J9ZOS390) /* defined(WIN32) */
4342
#if defined(LINUX) && !defined(J9VM_ENV_DATA64)
4343
4344
#if __GLIBC_PREREQ(2,4)
4345
/* glibc 2.4 (sles 10) and on provide lseek64() */
4346
result = lseek64(descriptor, bytesToSeek, origin);
4347
#else
4348
/* CMVC 104382: Linux lseek uses native word size off_t so we need to use the 64-bit _llseek on 32-bit Linux. AIX and z/OS use 64-bit API implicitly when we define _LARGE_FILES. */
4349
result = _llseek(descriptor, (unsigned long) ((bytesToSeek >> 32) & 0xFFFFFFFF), (unsigned long) (bytesToSeek & 0xFFFFFFFF), &longResult, origin);
4350
if (0 == result) {
4351
/* the call was successful so set the result to what we read */
4352
result = (jlong) longResult;
4353
}
4354
#endif
4355
4356
#else /* defined(LINUX) && !defined(J9VM_ENV_DATA64) */
4357
result = lseek(descriptor, (off_t) bytesToSeek, origin);
4358
#endif /* !defined(LINUX) ||defined(J9VM_ENV_DATA64) */
4359
#else /* defined(WIN32) */
4360
#error No JVM_Lseek provided
4361
#endif /* defined(WIN32) */
4362
4363
Trc_SC_Lseek_Exit(result);
4364
4365
return result;
4366
}
4367
4368
4369
/**
4370
* JVM_Read
4371
*/
4372
jint JNICALL
4373
JVM_Read(jint descriptor, char *buffer, jint bytesToRead)
4374
{
4375
PORT_ACCESS_FROM_JAVAVM(BFUjavaVM);
4376
jint result = 0;
4377
4378
Trc_SC_Read_Entry(descriptor, buffer, bytesToRead);
4379
4380
if (descriptor == -1) {
4381
Trc_SC_Read_bad_descriptor();
4382
return -1;
4383
}
4384
4385
#ifndef J9ZOS390
4386
/* This code SHOULD be for Windows only, but is safe everywhere except z/OS
4387
* (see CMVC 99667 for the fun details of z/OS and POSIX File-handles):
4388
* Map stdin to the port library, so we avoid any CR/LF translation.
4389
* See JVM_WRITE
4390
*/
4391
if (descriptor == 0) {
4392
IDATA charsRead = j9tty_get_chars(buffer, bytesToRead);
4393
result = (jint)charsRead;
4394
Assert_SC_true(charsRead == (IDATA)result);
4395
} else
4396
#endif
4397
{
4398
/* CMVC 178203 - Restart system calls interrupted by EINTR */
4399
do {
4400
result = read(descriptor, buffer, bytesToRead);
4401
} while ((-1 == result) && (EINTR == errno));
4402
}
4403
4404
Trc_SC_Read_Exit(result, errno);
4405
4406
return result;
4407
}
4408
4409
4410
/**
4411
* JVM_Open method
4412
*/
4413
jint JNICALL
4414
JVM_Open(const char* filename, jint flags, jint mode)
4415
{
4416
int errorVal = 0;
4417
jint returnVal = 0;
4418
4419
/* On OSX, stat64 and fstat64 are deprecated.
4420
* Thus, stat and fstat are used on OSX.
4421
*/
4422
#if defined(J9UNIX) && !defined(J9ZTPF) && !defined(OSX)
4423
struct stat64 tempStat;
4424
int doUnlink = 0;
4425
#endif /* defined(J9UNIX) && !defined(J9ZTPF) && !defined(OSX) */
4426
#if defined(J9ZOS390) || defined(J9ZTPF) || defined(OSX)
4427
struct stat tempStat;
4428
int doUnlink = 0;
4429
#endif /* defined(J9ZOS390) || defined(J9ZTPF) || defined(OSX) */
4430
4431
Trc_SC_Open_Entry(filename, flags, mode);
4432
4433
#define JVM_EEXIST -100
4434
4435
#ifdef WIN32
4436
#ifdef __IBMC__
4437
#define EXTRA_OPEN_FLAGS O_NOINHERIT | O_BINARY
4438
#else
4439
#define EXTRA_OPEN_FLAGS _O_NOINHERIT | _O_BINARY
4440
#endif
4441
#endif
4442
4443
#if defined(J9UNIX) || defined(J9ZOS390)
4444
#if defined(OSX) || defined(J9ZTPF)
4445
#define EXTRA_OPEN_FLAGS 0
4446
#else
4447
#define EXTRA_OPEN_FLAGS O_LARGEFILE
4448
#endif /* defined(OSX) || defined(J9ZTPF) */
4449
4450
#ifndef O_DSYNC
4451
#define O_DSYNC O_SYNC
4452
#endif
4453
4454
doUnlink = (flags & O_TEMPORARY);
4455
#if !defined(J9ZTPF)
4456
flags &= (O_CREAT | O_APPEND | O_RDONLY | O_RDWR | O_TRUNC | O_WRONLY | O_EXCL | O_NOCTTY | O_NONBLOCK | O_NDELAY | O_SYNC | O_DSYNC);
4457
#else /* !defined(J9ZTPF) */
4458
flags &= (O_CREAT | O_APPEND | O_RDONLY | O_RDWR | O_TRUNC | O_WRONLY | O_EXCL | O_NOCTTY | O_NONBLOCK | O_SYNC | O_DSYNC);
4459
#endif /* !defined(J9ZTPF) */
4460
#endif /* defined(J9UNIX) || defined(J9ZOS390) */
4461
4462
/* For some reason, although JVM_NativePath is called on the filenames, some of them seem to
4463
get mangled between JVM_NativePath being called and JVM_open being called */
4464
filename = JVM_NativePath((char *)filename);
4465
4466
#if defined(J9UNIX) || defined(J9ZOS390)
4467
do {
4468
errorVal = 0;
4469
#endif /* defined(J9UNIX) || defined(J9ZOS390) */
4470
4471
#ifdef J9OS_I5
4472
returnVal = Xj9Open_JDK6((char *)filename, (flags | EXTRA_OPEN_FLAGS), mode);
4473
#else
4474
returnVal = open(filename, (flags | EXTRA_OPEN_FLAGS), mode);
4475
#endif
4476
if (-1 == returnVal) {
4477
errorVal = errno;
4478
}
4479
4480
#if defined(J9UNIX) || defined(J9ZOS390)
4481
/* Unix open() call does not reject directories, so extra checks required */
4482
if ((returnVal>=0) && (J9FSTAT(returnVal, &tempStat)==-1)) {
4483
Trc_SC_Open_fstat64(filename);
4484
close(returnVal);
4485
return -1;
4486
}
4487
if ((returnVal>=0) && S_ISDIR(tempStat.st_mode)) {
4488
char buf[1];
4489
4490
Trc_SC_Open_isDirectory(filename);
4491
4492
/* force errno to be EISDIR in case JVM_GetLastErrorString is called */
4493
errno = EISDIR;
4494
4495
close(returnVal);
4496
return -1;
4497
}
4498
4499
/* On unices, open() may return EAGAIN or EINTR, and should then be re-invoked */
4500
}
4501
while ((-1 == returnVal) && ((EAGAIN == errorVal) || (EINTR == errorVal)));
4502
4503
/* Unix does not have an O_TEMPORARY flag. Unlink if Sovereign O_TEMPORARY flag passed in. */
4504
if ((returnVal>=0) && doUnlink)
4505
unlink(filename);
4506
#endif /* defined(J9UNIX) || defined(J9ZOS390) */
4507
4508
if (returnVal<0) {
4509
Trc_SC_Open_error(filename, errorVal);
4510
} else {
4511
Trc_SC_Open_Exit(filename, returnVal);
4512
}
4513
4514
if (returnVal>=0)
4515
return returnVal;
4516
else if (EEXIST == errorVal)
4517
return JVM_EEXIST;
4518
else
4519
return -1;
4520
}
4521
4522
4523
/**
4524
* JVM_Sync
4525
*/
4526
jint JNICALL
4527
JVM_Sync(jint descriptor)
4528
{
4529
jint result;
4530
4531
Trc_SC_Sync_Entry(descriptor);
4532
4533
if (descriptor == -1) {
4534
Trc_SC_Sync_bad_descriptor();
4535
return -1;
4536
}
4537
4538
#if defined(WIN32)
4539
#ifdef WIN32_IBMC
4540
printf("_JVM_Sync@4 called but not yet implemented. Exiting.\n");
4541
exit(44);
4542
#else
4543
result = _commit(descriptor);
4544
#endif
4545
#elif defined(J9UNIX) || defined(J9ZOS390) /* defined(WIN32) */
4546
result = fsync(descriptor);
4547
#else /* defined(WIN32) */
4548
#error No JVM_Sync implementation
4549
#endif /* defined(WIN32) */
4550
4551
Trc_SC_Sync_Exit(result);
4552
4553
return result;
4554
}
4555
4556
4557
/**
4558
* Change a pathname into platform specific format and do some canonicalization such as
4559
* removing redundant separators. Claims to modify the pathname in-place.
4560
* arg1 = char* = pathname
4561
* rtn = char* = ?
4562
*/
4563
char* JNICALL
4564
JVM_NativePath(char* path)
4565
{
4566
char * pathIndex;
4567
size_t length = strlen(path);
4568
4569
Trc_SC_NativePath_Entry(path);
4570
4571
if (jclSeparator == '/') {
4572
Trc_SC_NativePath_Exit(path);
4573
return path; /* Do not do POSIX platforms */
4574
}
4575
4576
/* Convert all separators to the same type */
4577
pathIndex = path;
4578
while (*pathIndex != '\0') {
4579
if ((*pathIndex == '\\' || *pathIndex == '/') && (*pathIndex != jclSeparator))
4580
*pathIndex = jclSeparator;
4581
pathIndex++;
4582
}
4583
4584
/* Remove duplicate initial separators */
4585
pathIndex = path;
4586
while ((*pathIndex != '\0') && (*pathIndex == jclSeparator)) {
4587
pathIndex++;
4588
}
4589
if ((pathIndex > path) && (length > (size_t)(pathIndex - path)) && (*(pathIndex + 1) == ':')) {
4590
/* For Example '////c:\*' */
4591
size_t newlen = length - (pathIndex - path);
4592
memmove(path, pathIndex, newlen);
4593
path[newlen] = '\0';
4594
} else {
4595
if ((pathIndex - path > 3) && (length > (size_t)(pathIndex - path))) {
4596
/* For Example '////serverName\*' */
4597
size_t newlen = length - (pathIndex - path) + 2;
4598
memmove(path, pathIndex - 2, newlen);
4599
path[newlen] = '\0';
4600
}
4601
}
4602
4603
Trc_SC_NativePath_Exit(path);
4604
return path;
4605
}
4606
4607
/**
4608
* Check if a signal is used for shutdown. SIGHUP,
4609
* SIGINT and SIGTERM are characterized as shutdown signals.
4610
* Terminator.setup() registers handlers for these signals
4611
* during startup.
4612
*
4613
* @param sigNum Integer value of the signal
4614
*
4615
* @returns TRUE if the signal is used for shutdown
4616
* FALSE if the signal is not used for shutdown
4617
*/
4618
static BOOLEAN
4619
isSignalUsedForShutdown(jint sigNum)
4620
{
4621
return
4622
#if defined(SIGHUP)
4623
(SIGHUP == sigNum) ||
4624
#endif /* defined(SIGHUP) */
4625
#if defined(SIGINT)
4626
(SIGINT == sigNum) ||
4627
#endif /* defined(SIGINT) */
4628
#if defined(SIGTERM)
4629
(SIGTERM == sigNum) ||
4630
#endif /* defined(SIGTERM) */
4631
FALSE;
4632
}
4633
4634
/**
4635
* Check if a signal is reserved by the VM. This function is invoked from
4636
* JVM_*Signal functions. This function only includes signals which
4637
* are listed in jvm.c::signalMap. If the signal is not listed in
4638
* jvm.c::signalMap, then a sun.misc.Signal instance can't be created
4639
* for a signal value. The native JVM_*Signal functions can't be invoked
4640
* in the absence of a sun.misc.Signal instance.
4641
*
4642
* Synchronous signals are handled by the VM via omrsig_protect: SIGFPE,
4643
* SIGILL, SIGSEGV, SIGBUS and SIGTRAP. On Windows, SIGBREAK is reserved
4644
* by the VM to trigger dumps. On Unix/Linux platforms, SIGQUIT is
4645
* reserved by the VM to trigger dumps. SIGABRT is reserved by the JVM
4646
* for abnormal termination. SIGCHLD is reserved for internal control.
4647
* On zOS, SIGUSR1 is reserved by the JVM. SIGRECONFIG is reserved to
4648
* detect any change in the number of CPUs, processing capacity, or
4649
* physical memory.
4650
*
4651
* @param sigNum Integer value of the signal
4652
*
4653
* @returns TRUE if the signal is reserved by the VM
4654
* FALSE if the signal is not reserved by the VM
4655
*/
4656
static BOOLEAN
4657
isSignalReservedByJVM(jint sigNum)
4658
{
4659
return
4660
#if defined(SIGFPE)
4661
(SIGFPE == sigNum) ||
4662
#endif /* defined(SIGFPE) */
4663
#if defined(SIGILL)
4664
(SIGILL == sigNum) ||
4665
#endif /* defined(SIGILL) */
4666
#if defined(SIGSEGV)
4667
(SIGSEGV == sigNum) ||
4668
#endif /* defined(SIGSEGV) */
4669
#if defined(SIGBUS)
4670
(SIGBUS == sigNum) ||
4671
#endif /* defined(SIGBUS) */
4672
#if defined(SIGTRAP)
4673
(SIGTRAP == sigNum) ||
4674
#endif /* defined(SIGTRAP) */
4675
#if defined(SIGQUIT)
4676
(SIGQUIT == sigNum) ||
4677
#endif /* defined(SIGQUIT) */
4678
#if defined(SIGBREAK)
4679
(SIGBREAK == sigNum) ||
4680
#endif /* defined(SIGBREAK) */
4681
FALSE;
4682
}
4683
4684
/**
4685
* Raise a signal to the calling process or thread.
4686
*
4687
* isSignalReservedByJVM function lists the signals reserved by the JVM.
4688
* Do not raise a signal if it is reserved by the JVM and not registered
4689
* via JVM_RegisterSignal.
4690
*
4691
* isSignalUsedForShutdown lists all signals characterized as shutdown signals.
4692
* Do not raise a shutdown signal if the -Xrs or the -Xrs:async cmdnline option
4693
* is specified. If a shutdown signal is ignored by the OS, do not raise that
4694
* shutdown signal. Only raise a shutdown signal if the previous two conditions
4695
* are false.
4696
*
4697
* @param sigNum Integer value of the signal to be sent to the
4698
* calling process or thread
4699
*
4700
* @returns JNI_TRUE if the signal is successfully raised/sent
4701
* JNI_FALSE if the signal is not sent
4702
*/
4703
jboolean JNICALL
4704
JVM_RaiseSignal(jint sigNum)
4705
{
4706
jboolean rc = JNI_FALSE;
4707
J9JavaVM *javaVM = (J9JavaVM *)BFUjavaVM;
4708
BOOLEAN isShutdownSignal = isSignalUsedForShutdown(sigNum);
4709
BOOLEAN isSignalIgnored = FALSE;
4710
int32_t isSignalIgnoredError = 0;
4711
uint32_t portlibSignalFlag = 0;
4712
4713
PORT_ACCESS_FROM_JAVAVM(javaVM);
4714
4715
Trc_SC_RaiseSignal_Entry(sigNum);
4716
4717
portlibSignalFlag = j9sig_map_os_signal_to_portlib_signal(sigNum);
4718
if (0 != portlibSignalFlag) {
4719
isSignalIgnoredError = j9sig_is_signal_ignored(portlibSignalFlag, &isSignalIgnored);
4720
}
4721
4722
if (isSignalReservedByJVM(sigNum)) {
4723
/* Don't raise a signal if it is reserved by the JVM, and not
4724
* registered via JVM_RegisterSignal.
4725
*/
4726
} else if (J9_ARE_ALL_BITS_SET(javaVM->sigFlags, J9_SIG_XRS_ASYNC) && isShutdownSignal) {
4727
/* Ignore shutdown signals if -Xrs or -Xrs:async is specified.
4728
* If -Xrs:sync is specified, then raise shutdown signals.
4729
*/
4730
} else if (isShutdownSignal && ((0 == isSignalIgnoredError) && isSignalIgnored)) {
4731
/* Ignore shutdown signal if it is ignored by the OS. */
4732
} else {
4733
raise(sigNum);
4734
rc = JNI_TRUE;
4735
}
4736
4737
Trc_SC_RaiseSignal_Exit(rc);
4738
4739
return rc;
4740
}
4741
4742
/**
4743
* Register a Java SignalHandler for a signal.
4744
*
4745
* isSignalReservedByJVM function lists the signals reserved by the JVM.
4746
* This function shouldn't override handlers for signals that are reserved
4747
* by the JVM. A user is allowed to register a native handler for the
4748
* reserved signals if -Xrs cmdline option is specified. This function
4749
* shouldn't register a Java SignalHandler for the reserved signals.
4750
*
4751
* isSignalUsedForShutdown lists all signals characterized as shutdown signals.
4752
* This function shouldn't register a handler for shutdown signals if
4753
* the -Xrs or the -Xrs:async cmdnline option is specified. If a shutdown
4754
* signal is ignored by the OS, this function shouldn't register a handler
4755
* for that shutdown signal. Only register a handler for shutdown signals if
4756
* the previous two conditions are false.
4757
*
4758
* If handler has the special value of J9_PRE_DEFINED_HANDLER_CHECK (2),
4759
* then the predefinedHandlerWrapper is registered with asynchSignalReporterThread
4760
* in OMR. mainASynchSignalHandler notifies asynchSignalReporterThread whenever a
4761
* signal is received. If the old OS handler is a main signal handler, then a
4762
* Java signal handler was previously registered with the signal. In this case,
4763
* J9_USE_OLD_JAVA_SIGNAL_HANDLER must be returned. sun.misc.Signal.handle(...) or
4764
* jdk.internal.misc.Signal.handle(...) will return the old Java signal handler if
4765
* JVM_RegisterSignal returns J9_USE_OLD_JAVA_SIGNAL_HANDLER. Otherwise, an instance
4766
* of NativeHandler is returned with oldHandler's address stored in
4767
* NativeHandler.handler.
4768
*
4769
* Java 8 - NativeHandler is sun.misc.NativeSignalHandler
4770
* Java 9 - NativeHandler is jdk.internal.misc.Signal.NativeHandler
4771
*
4772
* @param sigNum Integer value of the signal to be sent to the
4773
* calling process or thread
4774
* @param handler New handler to be associated to the signal
4775
*
4776
* @returns address of the old signal handler on success
4777
* J9_SIG_ERR (-1) in case of error
4778
*/
4779
void* JNICALL
4780
JVM_RegisterSignal(jint sigNum, void *handler)
4781
{
4782
void *oldHandler = (void *)J9_SIG_ERR;
4783
J9JavaVM *javaVM = (J9JavaVM *)BFUjavaVM;
4784
J9InternalVMFunctions *vmFuncs = javaVM->internalVMFunctions;
4785
J9VMThread *currentThread = vmFuncs->currentVMThread(javaVM);
4786
BOOLEAN isShutdownSignal = isSignalUsedForShutdown(sigNum);
4787
BOOLEAN isSignalIgnored = FALSE;
4788
int32_t isSignalIgnoredError = 0;
4789
uint32_t portlibSignalFlag = 0;
4790
4791
PORT_ACCESS_FROM_JAVAVM(javaVM);
4792
4793
Trc_SC_RegisterSignal_Entry(currentThread, sigNum, handler);
4794
4795
portlibSignalFlag = j9sig_map_os_signal_to_portlib_signal(sigNum);
4796
if (0 != portlibSignalFlag) {
4797
isSignalIgnoredError = j9sig_is_signal_ignored(portlibSignalFlag, &isSignalIgnored);
4798
}
4799
4800
if (isSignalReservedByJVM(sigNum)) {
4801
/* Return error if signal is reserved by the JVM. oldHandler is initialized to
4802
* J9_SIG_ERR.
4803
*/
4804
goto exit;
4805
} else if (J9_ARE_ANY_BITS_SET(javaVM->sigFlags, J9_SIG_XRS_ASYNC) && isShutdownSignal) {
4806
/* Don't register a handler for shutdown signals if -Xrs or -Xrs:async is specified.
4807
* If -Xrs:sync is specified, then register a handler for shutdown signals. oldHandler
4808
* is initialized to J9_SIG_ERR.
4809
*/
4810
goto exit;
4811
} else if (isShutdownSignal && ((0 == isSignalIgnoredError) && isSignalIgnored)) {
4812
/* Ignore shutdown signal if it is ignored by the OS. */
4813
oldHandler = (void *)J9_SIG_IGNORED;
4814
goto exit;
4815
} else {
4816
/* Register the signal. */
4817
IDATA isHandlerRegistered = 0;
4818
if ((void *)J9_PRE_DEFINED_HANDLER_CHECK == handler) {
4819
isHandlerRegistered = vmFuncs->registerPredefinedHandler(javaVM, sigNum, &oldHandler);
4820
} else {
4821
isHandlerRegistered = vmFuncs->registerOSHandler(javaVM, sigNum, handler, &oldHandler);
4822
}
4823
if (0 != isHandlerRegistered) {
4824
Trc_SC_RegisterSignal_FailedToRegisterHandler(currentThread, sigNum, handler, oldHandler);
4825
}
4826
}
4827
4828
/* If oldHandler is a main handler, then a Java signal handler was previously registered with
4829
* the signal. sun.misc.Signal.handle(...) or jdk.internal.misc.Signal.handle(...) will return
4830
* the old Java signal handler if JVM_RegisterSignal returns J9_USE_OLD_JAVA_SIGNAL_HANDLER.
4831
* Otherwise, an instance of NativeHandler is returned with the oldHandler's address stored in
4832
* NativeHandler.handler. In Java 8, NativeHandler.handle() will invoke JVM_RegisterSignal using
4833
* NativeHandler.handler, which represents the address of the native signal handler function. In
4834
* Java 9, NativeHandler.handle() will throw UnsupportedOperationException.
4835
*/
4836
if (j9sig_is_main_signal_handler(oldHandler)) {
4837
oldHandler = (void *)J9_USE_OLD_JAVA_SIGNAL_HANDLER;
4838
}
4839
4840
exit:
4841
Trc_SC_RegisterSignal_Exit(currentThread, oldHandler);
4842
return oldHandler;
4843
}
4844
4845
4846
/**
4847
* Return the integer value of the signal given the name of the
4848
* signal.
4849
*
4850
* @param sigName Name of the signal
4851
*
4852
* @returns Integer value of the signal on success
4853
* J9_SIG_ERR (-1) on failure
4854
*/
4855
jint JNICALL
4856
JVM_FindSignal(const char *sigName)
4857
{
4858
const J9SignalMapping *mapping = NULL;
4859
jint signalValue = J9_SIG_ERR;
4860
BOOLEAN nameHasSigPrefix = FALSE;
4861
const char *fullSigName = sigName;
4862
#if !defined(WIN32)
4863
char nameWithSIGPrefix[J9_SIGNAME_BUFFER_LENGTH] = {0};
4864
#endif /* !defined(WIN32) */
4865
4866
Trc_SC_FindSignal_Entry(sigName);
4867
4868
if (NULL != sigName) {
4869
size_t sigPrefixLength = sizeof(J9_SIG_PREFIX) - 1;
4870
4871
#if !defined(WIN32)
4872
if (0 != strncmp(sigName, J9_SIG_PREFIX, sigPrefixLength)) {
4873
/* nameWithSIGPrefix is a char buffer of length J9_SIGNAME_BUFFER_LENGTH.
4874
* We are concatenating SIG + sigName, and storing the new string in
4875
* nameWithSIGPrefix. We want to make sure that the concatenated string
4876
* fits inside nameWithSIGPrefix. We also know that all known signal names
4877
* have less than J9_SIGNAME_BUFFER_LENGTH chars. If the concatenated
4878
* string doesn't fit inside nameWithSIGPrefix, then we can consider signal
4879
* name to be unknown. In sigNameLength, +1 is for the NULL terminator.
4880
*/
4881
size_t sigNameLength = sigPrefixLength + strlen(sigName) + 1;
4882
if (sigNameLength <= J9_SIGNAME_BUFFER_LENGTH) {
4883
strcpy(nameWithSIGPrefix, J9_SIG_PREFIX);
4884
strcat(nameWithSIGPrefix, sigName);
4885
fullSigName = nameWithSIGPrefix;
4886
} else {
4887
goto exit;
4888
}
4889
}
4890
#endif /* !defined(WIN32) */
4891
4892
for (mapping = signalMap; NULL != mapping->signalName; mapping++) {
4893
if (0 == strcmp(fullSigName, mapping->signalName)) {
4894
signalValue = mapping->signalValue;
4895
break;
4896
}
4897
}
4898
}
4899
4900
#if !defined(WIN32)
4901
exit:
4902
#endif /* !defined(WIN32) */
4903
Trc_SC_FindSignal_Exit(signalValue);
4904
return signalValue;
4905
}
4906
4907
4908
4909
4910
/**
4911
* Gets last O/S or C error
4912
*/
4913
jint JNICALL
4914
JVM_GetLastErrorString(char* buffer, jint length)
4915
{
4916
int savedErrno = errno;
4917
#ifdef WIN32
4918
DWORD errorCode = GetLastError();
4919
#endif
4920
jint retVal = 0;
4921
4922
Trc_SC_GetLastErrorString_Entry(buffer, length);
4923
4924
memset(buffer, 0, length);
4925
4926
#ifdef WIN32
4927
if (errorCode) {
4928
retVal = formatErrorMessage(errorCode, buffer, length);
4929
} else
4930
#endif
4931
if (savedErrno) {
4932
PORT_ACCESS_FROM_JAVAVM(BFUjavaVM);
4933
I_32 sigRC;
4934
UDATA fnRC;
4935
4936
sigRC = j9sig_protect(protectedStrerror, (void *) (IDATA) savedErrno, strerrorSignalHandler, NULL, J9PORT_SIG_FLAG_SIGALLSYNC | J9PORT_SIG_FLAG_MAY_RETURN, &fnRC);
4937
if (sigRC == 0) {
4938
strncat(buffer, (char *) fnRC, (length-1));
4939
/* casting to jint is safe since we know that the result is <= length */
4940
retVal = (jint)strlen(buffer);
4941
}
4942
}
4943
4944
Trc_SC_GetLastErrorString_Exit(retVal, buffer);
4945
4946
return retVal;
4947
}
4948
4949
4950
4951
/**
4952
* jobject JVM_CurrentClassLoader(JNIEnv *)
4953
*/
4954
jobject JNICALL
4955
JVM_CurrentClassLoader(JNIEnv *env)
4956
{
4957
jobject result;
4958
4959
Trc_SC_CurrentClassLoader_Entry(env);
4960
4961
result = (*env)->CallStaticObjectMethod(env, jlClass, currentClassLoaderMID);
4962
4963
/* CMVC 95169: ensure that the result is a well defined error value if an exception occurred */
4964
if ((*env)->ExceptionCheck(env)) {
4965
result = NULL;
4966
}
4967
4968
Trc_SC_CurrentClassLoader_Exit(env, result);
4969
4970
return result;
4971
}
4972
4973
4974
/**
4975
* jclass JVM_CurrentLoadedClass(JNIEnv *)
4976
*/
4977
jclass JNICALL
4978
JVM_CurrentLoadedClass(JNIEnv *env)
4979
{
4980
jobject result;
4981
4982
Trc_SC_CurrentLoadedClass_Entry(env);
4983
4984
result = (*env)->CallStaticObjectMethod(env, jlClass, currentLoadedClassMID);
4985
4986
/* CMVC 95169: ensure that the result is a well defined error value if an exception occurred */
4987
if ((*env)->ExceptionCheck(env)) {
4988
result = NULL;
4989
}
4990
4991
Trc_SC_CurrentLoadedClass_Exit(env, result);
4992
4993
return result;
4994
}
4995
4996
4997
4998
4999
/**
5000
* jint JVM_ClassLoaderDepth(JNIEnv *)
5001
*/
5002
jint JNICALL
5003
JVM_ClassLoaderDepth(JNIEnv *env)
5004
{
5005
jint result;
5006
5007
Trc_SC_ClassLoaderDepth_Entry(env);
5008
5009
result = (*env)->CallStaticIntMethod(env, jlClass, classLoaderDepthMID);
5010
5011
/* CMVC 95169: ensure that the result is a well defined error value if an exception occurred */
5012
if ((*env)->ExceptionCheck(env)) {
5013
result = -1;
5014
}
5015
5016
Trc_SC_ClassLoaderDepth_Exit(env, result);
5017
5018
return result;
5019
}
5020
5021
5022
/**
5023
* jint JVM_ClassDepth(JNIEnv *, jstring)
5024
*/
5025
jint JNICALL
5026
JVM_ClassDepth(JNIEnv *env, jstring name)
5027
{
5028
jint result;
5029
5030
Trc_SC_ClassDepth_Entry(env, name);
5031
5032
result = (*env)->CallStaticIntMethod(env, jlClass, classDepthMID, name);
5033
5034
/* CMVC 95169: ensure that the result is a well defined error value if an exception occurred */
5035
if ((*env)->ExceptionCheck(env)) {
5036
result = -1;
5037
}
5038
5039
Trc_SC_ClassDepth_Exit(env, result);
5040
5041
return result;
5042
}
5043
5044
5045
/**
5046
* Method stub for method not yet implemented.
5047
*/
5048
void JNICALL
5049
JVM_TraceInstructions(jboolean on)
5050
{
5051
Trc_SC_TraceInstructions(on);
5052
}
5053
5054
5055
/**
5056
* Method stub for method not yet implemented.
5057
*/
5058
void JNICALL
5059
JVM_TraceMethodCalls(jboolean on)
5060
{
5061
Trc_SC_TraceMethodCalls(on);
5062
}
5063
5064
5065
5066
5067
5068
5069
/**
5070
* Destroy the monitor
5071
*
5072
* @param mon pointer of the monitor
5073
*/
5074
void JNICALL
5075
JVM_RawMonitorDestroy(void* mon)
5076
{
5077
5078
Trc_SC_RawMonitorDestroy_Entry(mon);
5079
5080
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
5081
omrthread_monitor_destroy((omrthread_monitor_t) mon);
5082
#else
5083
f_monitorDestroy((omrthread_monitor_t) mon);
5084
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
5085
5086
Trc_SC_RawMonitorDestroy_Exit();
5087
}
5088
5089
5090
/**
5091
* Monitor enter
5092
*
5093
* @param mon pointer of the monitor
5094
* @return 0
5095
*/
5096
jint JNICALL
5097
JVM_RawMonitorEnter(void* mon)
5098
{
5099
Trc_SC_RawMonitorEnter_Entry(mon);
5100
5101
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
5102
omrthread_monitor_enter((omrthread_monitor_t)mon);
5103
#else
5104
f_monitorEnter((omrthread_monitor_t)mon);
5105
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
5106
5107
Trc_SC_RawMonitorEnter_Exit();
5108
5109
return 0;
5110
}
5111
5112
5113
/**
5114
* Monitor exit
5115
*
5116
* @param mon pointer of the monitor
5117
*/
5118
void JNICALL JVM_RawMonitorExit(void* mon) {
5119
5120
Trc_SC_RawMonitorExit_Entry(mon);
5121
5122
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
5123
omrthread_monitor_exit((omrthread_monitor_t)mon);
5124
#else
5125
f_monitorExit((omrthread_monitor_t)mon);
5126
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
5127
5128
Trc_SC_RawMonitorExit_Exit();
5129
}
5130
5131
5132
/**
5133
* Create a new monitor
5134
*
5135
* @return pointer of the monitor
5136
*/
5137
void* JNICALL
5138
JVM_RawMonitorCreate(void)
5139
{
5140
omrthread_monitor_t newMonitor;
5141
5142
Trc_SC_RawMonitorCreate_Entry();
5143
5144
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
5145
if(omrthread_monitor_init_with_name(&newMonitor, 0, "JVM_RawMonitor"))
5146
#else
5147
if(f_monitorInit(&newMonitor, 0, "JVM_RawMonitor"))
5148
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
5149
{
5150
Trc_SC_RawMonitorCreate_Error();
5151
printf("error initializing raw monitor\n");
5152
exit(1);
5153
}
5154
5155
Trc_SC_RawMonitorCreate_Exit(newMonitor);
5156
return (void *) newMonitor;
5157
}
5158
5159
5160
/**
5161
* JVM_MonitorWait
5162
*/
5163
void JNICALL JVM_MonitorWait(JNIEnv *env, jobject anObject, jlong timeout) {
5164
Trc_SC_MonitorWait_Entry(env, anObject, timeout);
5165
5166
(*env)->CallVoidMethod(env, anObject, waitMID, timeout);
5167
5168
Trc_SC_MonitorWait_Exit(env);
5169
}
5170
5171
5172
/**
5173
* JVM_MonitorNotify
5174
*/
5175
void JNICALL JVM_MonitorNotify(JNIEnv *env, jobject anObject) {
5176
Trc_SC_MonitorNotify_Entry(env, anObject);
5177
5178
(*env)->CallVoidMethod(env, anObject, notifyMID);
5179
5180
Trc_SC_MonitorNotify_Exit(env);
5181
}
5182
5183
5184
/**
5185
* JVM_MonitorNotifyAll
5186
*/
5187
void JNICALL JVM_MonitorNotifyAll(JNIEnv *env, jobject anObject) {
5188
Trc_SC_MonitorNotifyAll_Entry(env, anObject);
5189
5190
(*env)->CallVoidMethod(env, anObject, notifyAllMID);
5191
5192
Trc_SC_MonitorNotifyAll_Exit(env);
5193
5194
}
5195
5196
5197
/**
5198
* JVM_Accept
5199
*/
5200
jint JNICALL
5201
JVM_Accept(jint descriptor, struct sockaddr* address, int* length)
5202
{
5203
jint retVal;
5204
5205
Trc_SC_Accept_Entry(descriptor, address, length);
5206
5207
#if defined(AIXPPC)
5208
{
5209
int returnVal=0;
5210
fd_set fdset;
5211
struct timeval tval;
5212
socklen_t socklen = (socklen_t)*length;
5213
5214
tval.tv_sec = 1;
5215
tval.tv_usec = 0;
5216
5217
do {
5218
FD_ZERO(&fdset);
5219
FD_SET((u_int)descriptor, &fdset);
5220
5221
returnVal = select(descriptor+1, &fdset, 0, 0, &tval);
5222
} while(returnVal == 0);
5223
5224
do {
5225
retVal = accept(descriptor, address, &socklen);
5226
} while ((-1 == retVal) && (EINTR == errno));
5227
5228
*length = (int)socklen;
5229
}
5230
#elif defined (WIN32)
5231
{
5232
SOCKET socketResult = accept(descriptor, address, length);
5233
retVal = (jint)socketResult;
5234
Assert_SC_true(socketResult == (SOCKET)retVal);
5235
}
5236
#else
5237
{
5238
socklen_t socklen = (socklen_t)*length;
5239
do {
5240
retVal = accept(descriptor, address, &socklen);
5241
} while ((-1 == retVal) && (EINTR == errno));
5242
*length = (int)socklen;
5243
}
5244
#endif
5245
5246
Trc_SC_Accept_Exit(retVal, *length);
5247
5248
return retVal;
5249
}
5250
5251
5252
/**
5253
* JVM_Connect
5254
*/
5255
jint JNICALL
5256
JVM_Connect(jint descriptor, const struct sockaddr*address, int length)
5257
{
5258
jint retVal;
5259
5260
Trc_SC_Connect_Entry(descriptor, address, length);
5261
5262
#if defined (WIN32)
5263
retVal = connect(descriptor, address, length);
5264
#else /* defined (WIN32) */
5265
do {
5266
retVal = connect(descriptor, address, length);
5267
} while ((-1 == retVal) && (EINTR == errno));
5268
#endif /* defined (WIN32) */
5269
5270
Trc_SC_Connect_Exit(retVal);
5271
5272
return retVal;
5273
}
5274
5275
5276
/**
5277
* JVM_CurrentTimeMillis
5278
*/
5279
jlong JNICALL
5280
JVM_CurrentTimeMillis(JNIEnv *env, jint unused1)
5281
{
5282
jlong result;
5283
5284
if (env != NULL) {
5285
PORT_ACCESS_FROM_ENV(env);
5286
5287
Trc_SC_CurrentTimeMillis_Entry(env, unused1);
5288
5289
result = (jlong) j9time_current_time_millis();
5290
5291
Trc_SC_CurrentTimeMillis_Exit(env, result);
5292
} else {
5293
PORT_ACCESS_FROM_JAVAVM(BFUjavaVM);
5294
5295
result = (jlong) j9time_current_time_millis();
5296
}
5297
5298
return result;
5299
}
5300
5301
5302
5303
/**
5304
* Initialized in port library startup.
5305
*/
5306
jint JNICALL
5307
JVM_InitializeSocketLibrary(void)
5308
{
5309
Trc_SC_InitializeSocketLibrary();
5310
return 0;
5311
}
5312
5313
5314
/**
5315
* JVM_Listen
5316
*/
5317
jint JNICALL JVM_Listen(jint descriptor, jint count) {
5318
jint retVal;
5319
5320
Trc_SC_Listen_Entry(descriptor, count);
5321
5322
retVal = listen(descriptor, count);
5323
5324
Trc_SC_Listen_Exit(retVal);
5325
5326
return retVal;
5327
}
5328
5329
5330
/**
5331
* JVM_Recv
5332
*/
5333
jint JNICALL
5334
JVM_Recv(jint descriptor, char* buffer, jint length, jint flags)
5335
{
5336
jint retVal;
5337
5338
#ifdef AIXPPC
5339
int returnVal=0;
5340
fd_set fdset;
5341
struct timeval tval;
5342
#endif
5343
5344
Trc_SC_Recv_Entry(descriptor, buffer, length, flags);
5345
5346
#ifdef AIXPPC
5347
tval.tv_sec = 1;
5348
tval.tv_usec = 0;
5349
5350
do {
5351
FD_ZERO(&fdset);
5352
FD_SET((u_int)descriptor, &fdset);
5353
5354
returnVal = select(descriptor+1, &fdset, 0, 0, &tval);
5355
} while(returnVal == 0);
5356
#endif
5357
5358
#ifdef WIN32
5359
retVal = recv(descriptor, buffer, (int)length, flags);
5360
#else
5361
do {
5362
retVal = recv(descriptor, buffer, (size_t)length, flags);
5363
} while ((-1 == retVal) && (EINTR == errno));
5364
#endif
5365
5366
Trc_SC_Recv_Exit(retVal);
5367
5368
return retVal;
5369
}
5370
5371
5372
/**
5373
* JVM_RecvFrom
5374
*/
5375
jint JNICALL
5376
JVM_RecvFrom(jint descriptor, char* buffer, jint length, jint flags, struct sockaddr* fromAddr, int* fromLength)
5377
{
5378
jint retVal;
5379
5380
Trc_SC_RecvFrom_Entry(descriptor, buffer, length, flags, fromAddr, fromLength);
5381
5382
#if defined (WIN32)
5383
retVal = recvfrom(descriptor, buffer, length, flags, fromAddr, fromLength);
5384
#else
5385
{
5386
socklen_t address_len = (socklen_t)*fromLength;
5387
do {
5388
retVal = recvfrom(descriptor, buffer, (size_t)length, flags, fromAddr, &address_len);
5389
} while ((-1 == retVal) && (EINTR == errno));
5390
*fromLength = (int)address_len;
5391
}
5392
#endif
5393
5394
Trc_SC_RecvFrom_Exit(retVal, *fromLength);
5395
5396
return retVal;
5397
}
5398
5399
5400
/**
5401
* JVM_Send
5402
*/
5403
jint JNICALL
5404
JVM_Send(jint descriptor, const char* buffer, jint numBytes, jint flags)
5405
{
5406
jint retVal;
5407
5408
Trc_SC_Send_Entry(descriptor, buffer, numBytes, flags);
5409
5410
#if defined (WIN32)
5411
retVal = send(descriptor, buffer, numBytes, flags);
5412
#else /* defined (WIN32) */
5413
do {
5414
retVal = send(descriptor, buffer, numBytes, flags);
5415
} while ((-1 == retVal) && (EINTR == errno));
5416
#endif /* defined (WIN32) */
5417
5418
Trc_SC_Send_Exit(retVal);
5419
5420
return retVal;
5421
}
5422
5423
5424
/**
5425
* JVM_SendTo
5426
*/
5427
jint JNICALL JVM_SendTo(jint descriptor, const char* buffer, jint length, jint flags, const struct sockaddr* toAddr, int toLength) {
5428
jint retVal;
5429
5430
Trc_SC_SendTo_Entry(descriptor, buffer, length, flags, toAddr, toLength);
5431
5432
#if defined (WIN32)
5433
retVal = sendto(descriptor, buffer, length, flags, toAddr, toLength);
5434
#else /* defined (WIN32) */
5435
do {
5436
retVal = sendto(descriptor, buffer, length, flags, toAddr, toLength);
5437
} while ((-1 == retVal) && (EINTR == errno));
5438
#endif /* defined (WIN32) */
5439
5440
Trc_SC_SendTo_Exit(retVal);
5441
5442
return retVal;
5443
}
5444
5445
5446
/**
5447
* JVM_Socket
5448
*/
5449
jint JNICALL
5450
JVM_Socket(jint domain, jint type, jint protocol)
5451
{
5452
jint result;
5453
5454
Trc_SC_Socket_Entry(domain, type, protocol);
5455
5456
#ifdef WIN32
5457
{
5458
SOCKET socketResult = socket(domain, type, protocol);
5459
SetHandleInformation((HANDLE)socketResult, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
5460
result = (jint)socketResult;
5461
Assert_SC_true(socketResult == (SOCKET)result);
5462
}
5463
#else
5464
result = socket(domain, type, protocol);
5465
#endif
5466
5467
Trc_SC_Socket_Exit(result);
5468
5469
return result;
5470
}
5471
5472
5473
/**
5474
* JVM_SocketAvailable
5475
* Note: Java 9 and beyond don't use this JVM method.
5476
*
5477
* @param descriptor socket file descriptor
5478
* @param result the number of bytes that can be read without blocking
5479
*
5480
* @return result of this JVM method, 0 for failure, 1 (or non-zero value) for success
5481
*/
5482
jint JNICALL
5483
JVM_SocketAvailable(jint descriptor, jint* result)
5484
{
5485
jint retVal = 0;
5486
5487
Trc_SC_SocketAvailable_Entry(descriptor, result);
5488
5489
#ifdef WIN32
5490
/* Windows JCL native doesn't invoke this JVM method */
5491
Assert_SC_unreachable();
5492
#endif
5493
#if defined(J9UNIX) || defined(J9ZOS390)
5494
if (0 <= descriptor) {
5495
do {
5496
retVal = ioctl(descriptor, FIONREAD, result);
5497
} while ((-1 == retVal) && (EINTR == errno));
5498
5499
if (0 <= retVal) {
5500
/* ioctl succeeded, return 1 to indicate that this JVM method succeeds */
5501
retVal = 1;
5502
} else {
5503
/* ioctl failed, return 0 to indicate that this JVM method fails */
5504
retVal = 0;
5505
}
5506
}
5507
#endif /* defined(J9UNIX) || defined(J9ZOS390) */
5508
5509
Trc_SC_SocketAvailable_Exit(retVal, *result);
5510
5511
return retVal;
5512
}
5513
5514
5515
/**
5516
* JVM_SocketClose
5517
*/
5518
jint JNICALL
5519
JVM_SocketClose(jint descriptor)
5520
{
5521
jint retVal;
5522
5523
Trc_SC_SocketClose_Entry(descriptor);
5524
5525
if (descriptor<=0) {
5526
Trc_SC_SocketClose_bad_descriptor();
5527
return 1;
5528
}
5529
5530
#if defined(WIN32)
5531
(void)shutdown(descriptor, SD_SEND);
5532
(void)closesocket(descriptor);
5533
retVal = 1; /* Always return TRUE */
5534
#else
5535
do {
5536
retVal = close(descriptor);
5537
} while ((-1 == retVal) && (EINTR == errno));
5538
#endif
5539
5540
Trc_SC_SocketClose_Exit(retVal);
5541
5542
return retVal;
5543
}
5544
5545
5546
/**
5547
* JVM_Timeout
5548
*/
5549
jint JNICALL
5550
JVM_Timeout(jint descriptor, jint timeout)
5551
{
5552
jint result = 0;
5553
struct timeval tval;
5554
#ifdef WIN32
5555
struct fd_set fdset;
5556
#endif
5557
5558
#if defined(J9UNIX) || defined(J9ZOS390)
5559
jint returnVal = 0;
5560
jint crazyCntr = 10;
5561
fd_set fdset;
5562
#endif /* defined(J9UNIX) || defined(J9ZOS390) */
5563
5564
Trc_SC_Timeout_Entry(descriptor, timeout);
5565
5566
tval.tv_sec = timeout / 1000;
5567
tval.tv_usec = (timeout % 1000) * 1000;
5568
FD_ZERO(&fdset);
5569
FD_SET((u_int)descriptor, &fdset);
5570
#if defined(WIN32)
5571
result = select(0, &fdset, 0, 0, &tval);
5572
#elif defined(J9ZTPF) /* defined(WIN32) */
5573
if (-1 == timeout) {
5574
result = select(0, &fdset, 0, 0, NULL);
5575
} else {
5576
result = select(0, &fdset, 0, 0, &tval);
5577
}
5578
#elif defined(J9UNIX) || defined(J9ZOS390) /* defined(WIN32) */
5579
do {
5580
crazyCntr--;
5581
returnVal = select(descriptor+1, &fdset, 0, 0, &tval);
5582
if (returnVal==1 && !FD_ISSET((u_int)descriptor, &fdset)) {
5583
result = 0;
5584
break;
5585
}
5586
if (!(returnVal<0 && errno==EINTR)) {
5587
result = returnVal;
5588
break;
5589
}
5590
} while (crazyCntr);
5591
#endif /* defined(WIN32) */
5592
5593
Trc_SC_Timeout_Exit(result);
5594
5595
return result;
5596
}
5597
5598
5599
/**
5600
* @return Is 8 byte compare and swap directly supported?
5601
*
5602
* @note In 1.4, this indicates whether or not JVM_FieldCX8 is supported.
5603
* @note In 1.5, this indicates whether a fast implementation of sun.misc.Unsafe.compareAndSwapLong() is supported.
5604
*
5605
* @note even though this may answer false on 32-bit platforms, JVM_CX8Field and
5606
* \compareAndSwapLong are supported, albeit in an inefficient manner.
5607
*/
5608
jboolean JNICALL
5609
JVM_SupportsCX8(void)
5610
{
5611
Trc_SC_SupportsCX8();
5612
5613
return JNI_TRUE;
5614
}
5615
5616
5617
/**
5618
* Perform an atomic compare and swap on a volatile long field.
5619
*
5620
* @arg[in] env the JNI environment
5621
* @arg[in] obj the jobject to which the instance field belongs, or the jclass to which the static field belongs
5622
* @arg[in] field the field to perform the compare and swap on
5623
* @arg[in] oldval if the current value in field is not oldval, it is unchanged
5624
* @arg[in] newval if the current value in field is oldval, newval is atomically stored into the field
5625
*
5626
* @return JNI_TRUE if newval was stored into the field, or JNI_FALSE if the fields value was not oldval
5627
*
5628
* @note The field must be volatile.
5629
* @note If obj is null this function produces undefined behaviour.
5630
*
5631
* @note This function is used in 1.4 if JVM_SupportsCX8 returns true.
5632
* @note In 1.5 it is unused.
5633
*/
5634
jboolean JNICALL
5635
JVM_CX8Field(JNIEnv* env, jobject obj, jfieldID field, jlong oldval, jlong newval)
5636
{
5637
jboolean result = JNI_FALSE;
5638
5639
Trc_SC_CX8Field_Entry(env, obj, field, oldval, newval);
5640
exit(230);
5641
5642
return result;
5643
}
5644
5645
5646
/**
5647
* Method stub for method not yet implemented. Required for 1.4 support.
5648
*/
5649
void JNICALL
5650
JVM_RegisterUnsafeMethods(JNIEnv* env, jclass unsafeClz)
5651
{
5652
5653
Trc_SC_RegisterUnsafeMethods(env);
5654
5655
}
5656
5657
5658
jint JNICALL
5659
JVM_ActiveProcessorCount(void)
5660
{
5661
PORT_ACCESS_FROM_JAVAVM(BFUjavaVM);
5662
jint num;
5663
5664
Trc_SC_ActiveProcessorCount_Entry();
5665
/*
5666
* This is used by Runtime.availableProcessors().
5667
* Runtime.availableProcessors() by specification returns a number greater or equal to 1.
5668
* RTC 112959: [was 209402] Liberty JAX-RS Default Executor poor performance. Match reference implementation behaviour
5669
* to return the bound CPUs rather than physical CPUs.
5670
*
5671
* This implementation should be kept consistent with jvmtiGetAvailableProcessors
5672
*/
5673
num = (jint)j9sysinfo_get_number_CPUs_by_type(J9PORT_CPU_TARGET);
5674
if (num < 1) {
5675
num = 1;
5676
}
5677
5678
Trc_SC_ActiveProcessorCount_Exit(num);
5679
5680
return num;
5681
}
5682
5683
J9Class* java_lang_Class_vmRef(JNIEnv* env, jobject clazz);
5684
5685
/**
5686
* JVM_GetClassName / JVM_InitClassName
5687
*
5688
* The name was changed from JVM_GetClassName to JVM_InitClassName
5689
* in interface version 6.
5690
*/
5691
jstring JNICALL
5692
#if JAVA_SPEC_VERSION < 11
5693
JVM_GetClassName
5694
#else /* JAVA_SPEC_VERSION < 11 */
5695
JVM_InitClassName
5696
#endif /* JAVA_SPEC_VERSION < 11 */
5697
(JNIEnv *env, jclass theClass)
5698
{
5699
J9JavaVM* vm = ((J9VMThread*)env)->javaVM;
5700
jstring result;
5701
5702
Trc_SC_GetClassName_Entry(env, theClass);
5703
5704
#ifdef J9VM_IVE_RAW_BUILD /* J9VM_IVE_RAW_BUILD is not enabled by default */
5705
{
5706
J9Class* ramClass = java_lang_Class_vmRef(env, theClass);
5707
J9ROMClass* romClass = ramClass->romClass;
5708
PORT_ACCESS_FROM_JAVAVM(vm);
5709
5710
if (J9ROMCLASS_IS_ARRAY(romClass)) {
5711
J9ArrayClass* arrayClass = (J9ArrayClass*) ramClass;
5712
J9ArrayClass* elementClass = (J9ArrayClass*)arrayClass->leafComponentType;
5713
UDATA arity = arrayClass->arity;
5714
UDATA nameLength, prefixSkip;
5715
J9UTF8* nameUTF;
5716
char* name;
5717
UDATA finalLength;
5718
5719
if (J9ROMCLASS_IS_PRIMITIVE_TYPE(elementClass->romClass)) {
5720
nameUTF = J9ROMCLASS_CLASSNAME(elementClass->arrayClass->romClass);
5721
arity -= 1;
5722
nameLength = arity; /* The name will have a [ in it already */
5723
prefixSkip = arity;
5724
} else {
5725
nameUTF = J9ROMCLASS_CLASSNAME(elementClass->romClass);
5726
nameLength = arity + 2; /* The semi colon and the L */
5727
prefixSkip = arity + 1;
5728
}
5729
5730
finalLength = nameLength + J9UTF8_LENGTH(nameUTF) + 1;
5731
name = (char*)j9mem_allocate_memory(nameLength + J9UTF8_LENGTH(nameUTF) + 1, OMRMEM_CATEGORY_VM);
5732
if (NULL != name) {
5733
memset(name,'[', nameLength);
5734
memcpy(name+nameLength, J9UTF8_DATA(nameUTF), J9UTF8_LENGTH(nameUTF));
5735
name[J9UTF8_LENGTH(nameUTF)] = 0;
5736
}
5737
return NULL;
5738
} else {
5739
J9UTF8* nameUTF = J9ROMCLASS_CLASSNAME(ramClass->romClass);
5740
jobject result = NULL;
5741
5742
char* name = (char*)j9mem_allocate_memory(J9UTF8_LENGTH(nameUTF) + 1, OMRMEM_CATEGORY_VM);
5743
if (NULL != name) {
5744
memcpy(name, J9UTF8_DATA(nameUTF), J9UTF8_LENGTH(nameUTF));
5745
name[J9UTF8_LENGTH(nameUTF)] = 0;
5746
}
5747
5748
result = (*env)->NewStringUTF(env, name);
5749
j9mem_free_memory(name);
5750
#if JAVA_SPEC_VERSION >= 11
5751
// JVM_InitClassName is expected to also cache the result in the 'name' field
5752
(*env)->SetObjectField(env, theClass, classNameFID, result);
5753
if ((*env)->ExceptionCheck(env)) {
5754
result = NULL;
5755
}
5756
#endif /* JAVA_SPEC_VERSION >= 11 */
5757
return result;
5758
}
5759
}
5760
#endif /* J9VM_IVE_RAW_BUILD */
5761
5762
result = (*env)->CallObjectMethod(env, theClass, getNameMID);
5763
5764
/* CMVC 95169: ensure that the result is a well defined error value if an exception occurred */
5765
if ((*env)->ExceptionCheck(env)) {
5766
result = NULL;
5767
}
5768
5769
Trc_SC_GetClassName_Exit(env, result);
5770
5771
return result;
5772
}
5773
5774
5775
jclass JNICALL
5776
JVM_FindClassFromCaller(JNIEnv* env, const char* arg1, jboolean arg2, jobject arg3, jclass arg4)
5777
{
5778
Assert_SC_true(!"JVM_FindClassFromCaller unimplemented");
5779
return NULL;
5780
}
5781
5782
jintArray JNICALL
5783
JVM_GetResourceLookupCache(JNIEnv *env, jobject loader, const char *resource_name) {
5784
return NULL;
5785
}
5786
5787
jobjectArray JNICALL
5788
JVM_GetResourceLookupCacheURLs(JNIEnv *env, jobject loader) {
5789
return NULL;
5790
}
5791
5792
jboolean JVM_KnownToNotExist(JNIEnv *env, jobject loader, const char *classname) {
5793
return JNI_FALSE;
5794
}
5795
5796
5797
#if JAVA_SPEC_VERSION < 17
5798
/**
5799
* Return the JVM_INTERFACE_VERSION. This function should not lock, gc or throw exception.
5800
* @return JVM_INTERFACE_VERSION, JDK8 - 4, JDK11+ - 6.
5801
*/
5802
jint JNICALL
5803
JVM_GetInterfaceVersion(void)
5804
{
5805
jint result = 4; /* JDK8 */
5806
5807
Trc_SC_GetInterfaceVersion_Entry();
5808
if (J2SE_CURRENT_VERSION >= J2SE_V11) {
5809
result = 6;
5810
}
5811
Trc_SC_GetInterfaceVersion_Exit(result);
5812
5813
return result;
5814
}
5815
#endif /* JAVA_SPEC_VERSION < 17 */
5816
5817
5818
/* jclass parameter 2 is apparently not used */
5819
5820
jint JNICALL
5821
JVM_Sleep(JNIEnv* env, jclass thread, jlong timeout)
5822
{
5823
Trc_SC_Sleep_Entry(env, thread, timeout);
5824
5825
(*env)->CallStaticVoidMethod(env, jlThread, sleepMID, timeout);
5826
5827
Trc_SC_Sleep_Exit(env);
5828
5829
return 0;
5830
}
5831
5832
5833
5834
jint JNICALL
5835
JVM_UcsOpen(const jchar* filename, jint flags, jint mode)
5836
{
5837
#ifdef WIN32
5838
WCHAR *prefixStr;
5839
DWORD prefixLen ;
5840
5841
DWORD fullPathLen, rc;
5842
WCHAR* longFilename;
5843
DWORD newFlags, disposition, attributes;
5844
HANDLE hFile;
5845
jint returnVal;
5846
int isUNC = FALSE;
5847
int isDosDevices = FALSE;
5848
5849
if (filename==NULL) {
5850
Trc_SC_UcsOpen_nullName();
5851
return -1;
5852
}
5853
5854
Trc_SC_UcsOpen_Entry(filename, flags, mode);
5855
5856
if (filename[0] == L'\\' && filename[1] == L'\\') {
5857
/* found a UNC path */
5858
if (filename[2] == L'?') {
5859
prefixStr = L"";
5860
prefixLen = 0;
5861
} else if (filename[2] == L'.' && filename[3] == L'\\') {
5862
isDosDevices = TRUE;
5863
prefixStr = L"";
5864
prefixLen = 0;
5865
} else {
5866
isUNC = TRUE;
5867
prefixStr = L"\\\\?\\UNC";
5868
prefixLen = (sizeof(L"\\\\?\\UNC") / sizeof(WCHAR)) - 1;
5869
}
5870
} else {
5871
prefixStr = L"\\\\?\\";
5872
prefixLen = (sizeof(L"\\\\?\\") / sizeof(WCHAR)) - 1;
5873
}
5874
5875
/* Query size of full path name and allocate space accordingly */
5876
fullPathLen = GetFullPathNameW(filename, 0, NULL, NULL);
5877
/*[CMVC 74127] Workaround for 1 character filenames on Windows 2000 */
5878
if (filename[0] == L'\0' || filename[1] == L'\0') fullPathLen += 3;
5879
/*[CMVC 77501] Workaround for "\\.\" - reported length is off by 4 characters */
5880
if (isDosDevices) fullPathLen += 4;
5881
longFilename = malloc(sizeof(WCHAR) * (prefixLen+fullPathLen));
5882
5883
/* Prefix "\\?\" to allow for very long filenames */
5884
wcscpy(longFilename, prefixStr);
5885
5886
/* Finally append full path name */
5887
if (isUNC) prefixLen--;
5888
rc = GetFullPathNameW(filename, fullPathLen, &longFilename[prefixLen], NULL);
5889
if (!rc || rc >= fullPathLen) {
5890
Trc_SC_UcsOpen_GetFullPathNameW(rc);
5891
return -1;
5892
}
5893
5894
if (isUNC) longFilename[prefixLen] = L'C';
5895
5896
if (!flags || (flags & O_RDONLY) || (flags == O_TEMPORARY))
5897
newFlags = GENERIC_READ;
5898
else if (flags & O_WRONLY)
5899
newFlags = GENERIC_WRITE;
5900
else if (flags & O_RDWR)
5901
newFlags = (GENERIC_READ | GENERIC_WRITE);
5902
5903
if (flags & O_TRUNC)
5904
disposition = CREATE_ALWAYS;
5905
else if (flags & O_CREAT)
5906
disposition = OPEN_ALWAYS;
5907
else
5908
disposition = OPEN_EXISTING;
5909
5910
if (flags & (O_SYNC | O_DSYNC))
5911
attributes = FILE_FLAG_WRITE_THROUGH;
5912
else
5913
attributes = FILE_ATTRIBUTE_NORMAL;
5914
5915
if (flags & O_TEMPORARY)
5916
attributes |= FILE_FLAG_DELETE_ON_CLOSE;
5917
5918
hFile = CreateFileW(longFilename, newFlags, mode, NULL, disposition, attributes, NULL);
5919
returnVal = _open_osfhandle((UDATA)hFile, flags);
5920
5921
if (returnVal<0) {
5922
Trc_SC_UcsOpen_error(returnVal);
5923
} else {
5924
Trc_SC_UcsOpen_Exit(returnVal);
5925
}
5926
5927
free(longFilename);
5928
5929
if (returnVal>=0)
5930
return returnVal;
5931
else if (errno==EEXIST)
5932
return JVM_EEXIST;
5933
else
5934
return -1;
5935
#else
5936
printf("JVM_UcsOpen is only supported on Win32 platforms\n");
5937
return -1;
5938
#endif
5939
}
5940
5941
5942
5943
5944
5945
5946
/**
5947
* jclass JVM_ConstantPoolGetClassAt(JNIEnv *, jobject, jobject, jint)
5948
*/
5949
jclass JNICALL
5950
JVM_ConstantPoolGetClassAt(JNIEnv *env, jobject anObject, jobject constantPool, jint index)
5951
{
5952
Trc_SC_ConstantPoolGetClassAt(env);
5953
exit(207);
5954
}
5955
5956
5957
/**
5958
* jclass JVM_ConstantPoolGetClassAtIfLoaded(JNIEnv *, jobject, jobject, jint)
5959
*/
5960
jclass JNICALL
5961
JVM_ConstantPoolGetClassAtIfLoaded(JNIEnv *env, jobject anObject, jobject constantPool, jint index)
5962
{
5963
Trc_SC_ConstantPoolGetClassAtIfLoaded(env);
5964
exit(208);
5965
}
5966
5967
5968
/**
5969
* jdouble JVM_ConstantPoolGetDoubleAt(JNIEnv *, jobject, jobject, jint)
5970
*/
5971
jdouble JNICALL
5972
JVM_ConstantPoolGetDoubleAt(JNIEnv *env, jobject anObject, jobject constantPool, jint index)
5973
{
5974
Trc_SC_ConstantPoolGetDoubleAt(env);
5975
exit(217);
5976
}
5977
5978
5979
/**
5980
* jobject JVM_ConstantPoolGetFieldAt(JNIEnv *, jobject, jobject, jint)
5981
*/
5982
jobject JNICALL
5983
JVM_ConstantPoolGetFieldAt(JNIEnv *env, jobject anObject, jobject constantPool, jint index)
5984
{
5985
Trc_SC_ConstantPoolGetFieldAt(env);
5986
exit(211);
5987
}
5988
5989
5990
/**
5991
* jobject JVM_ConstantPoolGetFieldAtIfLoaded(JNIEnv *, jobject, jobject, jint)
5992
*/
5993
jobject JNICALL
5994
JVM_ConstantPoolGetFieldAtIfLoaded(JNIEnv *env, jobject anObject, jobject constantPool, jint index)
5995
{
5996
Trc_SC_ConstantPoolGetFieldAtIfLoaded(env);
5997
exit(212);
5998
}
5999
6000
6001
/**
6002
* jfloat JVM_ConstantPoolGetFloatAt(JNIEnv *, jobject, jobject, jint)
6003
*/
6004
jfloat JNICALL
6005
JVM_ConstantPoolGetFloatAt(JNIEnv *env, jobject anObject, jobject constantPool, jint index)
6006
{
6007
Trc_SC_ConstantPoolGetFloatAt(env);
6008
exit(216);
6009
}
6010
6011
6012
/**
6013
* jint JVM_ConstantPoolGetIntAt(JNIEnv *, jobject, jobject, jint)
6014
*/
6015
jint JNICALL
6016
JVM_ConstantPoolGetIntAt(JNIEnv *env, jobject anObject, jobject constantPool, jint index)
6017
{
6018
Trc_SC_ConstantPoolGetIntAt(env);
6019
exit(214);
6020
}
6021
6022
6023
/**
6024
* jlong JVM_ConstantPoolGetLongAt(JNIEnv *, jobject, jobject, jint)
6025
*/
6026
jlong JNICALL
6027
JVM_ConstantPoolGetLongAt(JNIEnv *env, jobject anObject, jobject constantPool, jint index)
6028
{
6029
Trc_SC_ConstantPoolGetLongAt(env);
6030
exit(215);
6031
}
6032
6033
6034
/**
6035
* jobjectArray JVM_ConstantPoolGetMemberRefInfoAt(JNIEnv *, jobject, jobject, jint)
6036
*/
6037
jobjectArray JNICALL
6038
JVM_ConstantPoolGetMemberRefInfoAt(JNIEnv *env, jobject anObject, jobject constantPool, jint index)
6039
{
6040
Trc_SC_ConstantPoolGetMemberRefInfoAt(env);
6041
exit(213);
6042
}
6043
6044
6045
/**
6046
* jobject JVM_ConstantPoolGetMethodAt(JNIEnv *, jobject, jobject, jint)
6047
*/
6048
jobject JNICALL
6049
JVM_ConstantPoolGetMethodAt(JNIEnv *env, jobject anObject, jobject constantPool, jint index)
6050
{
6051
Trc_SC_ConstantPoolGetMethodAt(env);
6052
exit(209);
6053
}
6054
6055
6056
/**
6057
* jobject JVM_ConstantPoolGetMethodAtIfLoaded(JNIEnv *, jobject, jobject, jint)
6058
*/
6059
jobject JNICALL
6060
JVM_ConstantPoolGetMethodAtIfLoaded(JNIEnv *env, jobject anObject, jobject constantPool, jint index)
6061
{
6062
Trc_SC_ConstantPoolGetMethodAtIfLoaded(env);
6063
exit(210);
6064
}
6065
6066
6067
/**
6068
* jint JVM_ConstantPoolGetSize(JNIEnv *, jobject, jobject)
6069
*/
6070
jint JNICALL
6071
JVM_ConstantPoolGetSize(JNIEnv *env, jobject anObject, jobject constantPool)
6072
{
6073
Trc_SC_ConstantPoolGetSize(env);
6074
exit(206);
6075
}
6076
6077
6078
/**
6079
* jstring JVM_ConstantPoolGetStringAt(JNIEnv *, jobject, jobject, jint)
6080
*/
6081
jstring JNICALL
6082
JVM_ConstantPoolGetStringAt(JNIEnv *env, jobject anObject, jobject constantPool, jint index)
6083
{
6084
Trc_SC_ConstantPoolGetStringAt(env);
6085
exit(218);
6086
}
6087
6088
6089
/**
6090
* jstring JVM_ConstantPoolGetUTF8At(JNIEnv *, jstring)
6091
*/
6092
jstring JNICALL
6093
JVM_ConstantPoolGetUTF8At(JNIEnv *env, jobject anObject, jobject constantPool, jint index)
6094
{
6095
Trc_SC_ConstantPoolGetUTF8At(env);
6096
exit(219);
6097
}
6098
6099
6100
/**
6101
* jclass JVM_DefineClassWithSource(JNIEnv *, const char *, jobject, const jbyte *, jsize, jobject, const char *)
6102
*/
6103
jclass JNICALL
6104
JVM_DefineClassWithSource(JNIEnv *env, const char * className, jobject classLoader, const jbyte * classArray, jsize length, jobject domain, const char * source)
6105
{
6106
J9VMThread* currentThread = (J9VMThread*) env;
6107
J9JavaVM* vm = currentThread->javaVM;
6108
J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
6109
J9ClassLoader* vmLoader;
6110
j9object_t loaderObject;
6111
jstring classNameString = (*env)->NewStringUTF(env,className);
6112
6113
vmFuncs->internalEnterVMFromJNI(currentThread);
6114
6115
loaderObject = J9_JNI_UNWRAP_REFERENCE(classLoader);
6116
vmLoader = J9VMJAVALANGCLASSLOADER_VMREF(currentThread, loaderObject);
6117
if (NULL == vmLoader) {
6118
vmLoader = vmFuncs->internalAllocateClassLoader(vm, loaderObject);
6119
if (NULL == vmLoader) {
6120
vmFuncs->internalExitVMToJNI(currentThread);
6121
return NULL;
6122
}
6123
}
6124
vmFuncs->internalExitVMToJNI(currentThread);
6125
6126
return jvmDefineClassHelper(env, classLoader, classNameString, (jbyte*)classArray, 0, length, domain, 0);
6127
}
6128
6129
6130
/**
6131
* jobjectArray JVM_DumpThreads(JNIEnv *, jclass, jobjectArray)
6132
*/
6133
jobjectArray JNICALL
6134
JVM_DumpThreads(JNIEnv *env, jclass thread, jobjectArray threadArray)
6135
{
6136
Trc_SC_DumpThreads(env);
6137
exit(224);
6138
}
6139
6140
6141
/**
6142
* jobjectArray JVM_GetAllThreads(JNIEnv *, jclass)
6143
*/
6144
jobjectArray JNICALL
6145
JVM_GetAllThreads(JNIEnv *env, jclass aClass)
6146
{
6147
Trc_SC_GetAllThreads(env);
6148
exit(223);
6149
}
6150
6151
6152
/**
6153
* jbyteArray JVM_GetClassAnnotations(JNIEnv *, jclass)
6154
*/
6155
jbyteArray JNICALL
6156
JVM_GetClassAnnotations(JNIEnv *env, jclass target)
6157
{
6158
Trc_SC_GetClassAnnotations(env);
6159
exit(221);
6160
}
6161
6162
6163
/**
6164
* jobject JVM_GetClassConstantPool(JNIEnv *, jclass)
6165
*/
6166
jobject JNICALL
6167
JVM_GetClassConstantPool(JNIEnv *env, jclass target)
6168
{
6169
Trc_SC_GetClassConstantPool(env);
6170
exit(205);
6171
}
6172
6173
6174
/**
6175
* jstring JVM_GetClassSignature(JNIEnv *, jclass)
6176
*/
6177
jstring JNICALL
6178
JVM_GetClassSignature(JNIEnv *env, jclass target)
6179
{
6180
Trc_SC_GetClassSignature(env);
6181
exit(220);
6182
}
6183
6184
6185
/**
6186
* jobjectArray JVM_GetEnclosingMethodInfo(JNIEnv *, jclass)
6187
*/
6188
jobjectArray JNICALL
6189
JVM_GetEnclosingMethodInfo(JNIEnv *env, jclass theClass)
6190
{
6191
Trc_SC_GetEnclosingMethodInfo(env);
6192
exit(204);
6193
}
6194
6195
static jint JNICALL
6196
managementVMIVersion(JNIEnv *env)
6197
{
6198
return JNI_VERSION_1_8;
6199
}
6200
6201
typedef struct ManagementVMI {
6202
void * unused1;
6203
void * unused2;
6204
jint (JNICALL *getManagementVMIVersion)(JNIEnv *env);
6205
} ManagementVMI;
6206
6207
static ManagementVMI globalManagementVMI = {NULL, NULL, &managementVMIVersion};
6208
6209
/**
6210
* void* JVM_GetManagement(jint)
6211
*/
6212
void* JNICALL
6213
JVM_GetManagement(jint version)
6214
{
6215
Trc_SC_GetManagement();
6216
return &globalManagementVMI;
6217
}
6218
6219
6220
/**
6221
* jlong JVM_NanoTime(JNIEnv *, jclass)
6222
*/
6223
jlong JNICALL
6224
JVM_NanoTime(JNIEnv *env, jclass aClass)
6225
{
6226
jlong ticks, freq;
6227
6228
PORT_ACCESS_FROM_JAVAVM(BFUjavaVM);
6229
6230
Trc_SC_NanoTime(env);
6231
6232
ticks = j9time_hires_clock();
6233
freq = j9time_hires_frequency();
6234
6235
/* freq is "ticks per s" */
6236
if ( freq == 1000000000L ) {
6237
return ticks;
6238
} else if ( freq < 1000000000L ) {
6239
return ticks * (1000000000L / freq);
6240
} else {
6241
return ticks / (freq / 1000000000L);
6242
}
6243
}
6244
6245
6246
6247
struct J9PortLibrary*
6248
JNICALL JVM_GetPortLibrary(void)
6249
{
6250
return &j9portLibrary;
6251
}
6252
6253
6254
jint JNICALL
6255
JVM_ExpandFdTable(jint fd)
6256
{
6257
return 0;
6258
}
6259
6260
6261
6262
void JNICALL
6263
JVM_ZipHook(JNIEnv *env, const char* filename, jint newState)
6264
{
6265
#ifdef J9VM_OPT_ZIP_SUPPORT
6266
VMI_ACCESS_FROM_ENV(env);
6267
J9JavaVM *vm = (J9JavaVM*)((J9VMThread*)env)->javaVM;
6268
J9HookInterface ** hook = (*VMI)->GetZipFunctions(VMI)->zip_getZipHookInterface(VMI);
6269
6270
if (hook != NULL) {
6271
UDATA state;
6272
6273
switch (newState) {
6274
case JVM_ZIP_HOOK_STATE_OPEN :
6275
state = J9ZIP_STATE_OPEN;
6276
break;
6277
case JVM_ZIP_HOOK_STATE_CLOSED :
6278
state = J9ZIP_STATE_CLOSED;
6279
break;
6280
case JVM_ZIP_HOOK_STATE_RESET :
6281
state = J9ZIP_STATE_RESET;
6282
break;
6283
default :
6284
state = 0;
6285
}
6286
/* Can't use hook trigger macros as can't include vmzipcachehook_internal.h */
6287
if (state) {
6288
struct J9VMZipLoadEvent eventData;
6289
6290
eventData.portlib = vm->portLibrary;
6291
eventData.userData = vm;
6292
eventData.zipfile = NULL;
6293
eventData.newState = state;
6294
eventData.cpPath = (U_8*)filename;
6295
eventData.returnCode = 0;
6296
6297
(*hook)->J9HookDispatch(hook, J9HOOK_VM_ZIP_LOAD, &eventData);
6298
}
6299
}
6300
#endif /* J9VM_OPT_ZIP_SUPPORT */
6301
}
6302
6303
6304
void * JNICALL
6305
JVM_RawAllocate(size_t size, const char * callsite)
6306
{
6307
return j9portLibrary.omrPortLibrary.mem_allocate_memory(&j9portLibrary.omrPortLibrary, (UDATA) size, (char *) ((callsite == NULL) ? J9_GET_CALLSITE() : callsite), J9MEM_CATEGORY_SUN_JCL);
6308
}
6309
6310
void * JNICALL
6311
JVM_RawRealloc(void * ptr, size_t size, const char * callsite)
6312
{
6313
return j9portLibrary.omrPortLibrary.mem_reallocate_memory(&j9portLibrary.omrPortLibrary, ptr, (UDATA) size, callsite, J9MEM_CATEGORY_SUN_JCL);
6314
}
6315
6316
void * JNICALL
6317
JVM_RawCalloc(size_t nmemb, size_t size, const char * callsite)
6318
{
6319
size_t byteSize = nmemb * size;
6320
void * mem = JVM_RawAllocate(byteSize, callsite);
6321
6322
if (mem != NULL) {
6323
memset(mem, 0, byteSize);
6324
}
6325
6326
return mem;
6327
}
6328
6329
void * JNICALL
6330
JVM_RawAllocateInCategory(size_t size, const char * callsite, jint category)
6331
{
6332
return j9portLibrary.omrPortLibrary.mem_allocate_memory(&j9portLibrary.omrPortLibrary, (UDATA) size, (char *) ((callsite == NULL) ? J9_GET_CALLSITE() : callsite), category);
6333
}
6334
6335
void * JNICALL
6336
JVM_RawReallocInCategory(void * ptr, size_t size, const char * callsite, jint category)
6337
{
6338
return j9portLibrary.omrPortLibrary.mem_reallocate_memory(&j9portLibrary.omrPortLibrary, ptr, (UDATA) size, callsite, category);
6339
}
6340
6341
void * JNICALL
6342
JVM_RawCallocInCategory(size_t nmemb, size_t size, const char * callsite, jint category)
6343
{
6344
size_t byteSize = nmemb * size;
6345
void * mem = JVM_RawAllocateInCategory(byteSize, callsite, category);
6346
6347
if (mem != NULL) {
6348
memset(mem, 0, byteSize);
6349
}
6350
6351
return mem;
6352
}
6353
6354
void JNICALL
6355
JVM_RawFree(void * ptr)
6356
{
6357
j9portLibrary.omrPortLibrary.mem_free_memory(&j9portLibrary.omrPortLibrary, ptr);
6358
}
6359
6360
6361
/**
6362
* JVM_IsNaN
6363
*/
6364
jboolean JNICALL
6365
JVM_IsNaN(jdouble dbl)
6366
{
6367
Trc_SC_IsNaN(*(jlong*)&dbl);
6368
return IS_NAN_DBL(dbl);
6369
}
6370
6371
6372
/*
6373
* Called before class library initialization to allow the JVM interface layer to
6374
* perform any necessary initialization.
6375
*
6376
* @note Java 7 and beyond uses J9HOOK_VM_INITIALIZE_REQUIRED_CLASSES_DONE instead
6377
* however, this function must be retained in order to satisfy the redirector.
6378
*/
6379
jint JNICALL
6380
JVM_Startup(JavaVM* vm, JNIEnv* env)
6381
{
6382
return JNI_OK;
6383
}
6384
6385
#if defined(J9ZOS390)
6386
/**
6387
* @return TRUE if we were able to set omrthread_global("thread_weight") with
6388
* a thread weight value. FALSE otherwise.
6389
*/
6390
static BOOLEAN
6391
setZOSThrWeight(void)
6392
{
6393
BOOLEAN success = FALSE;
6394
const UDATA jvmZOSTW = checkZOSThrWeightEnvVar();
6395
6396
if (ZOS_THR_WEIGHT_NOT_FOUND != jvmZOSTW) {
6397
omrthread_t thandle = NULL;
6398
IDATA trc = 0;
6399
6400
/* Attach so that we can use omrthread_global() below */
6401
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
6402
trc = omrthread_attach_ex(&thandle, J9THREAD_ATTR_DEFAULT);
6403
#else
6404
trc = f_threadAttachEx(&thandle, J9THREAD_ATTR_DEFAULT);
6405
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
6406
6407
if (0 == trc) {
6408
UDATA * gtw = NULL;
6409
6410
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
6411
gtw = omrthread_global("thread_weight");
6412
#else
6413
gtw = f_threadGlobal("thread_weight");
6414
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
6415
6416
if (NULL != gtw) {
6417
if (ZOS_THR_WEIGHT_HEAVY == jvmZOSTW) {
6418
*gtw = (UDATA)"heavy";
6419
} else {
6420
*gtw = (UDATA)"medium";
6421
}
6422
success = TRUE;
6423
}
6424
6425
#if CALL_BUNDLED_FUNCTIONS_DIRECTLY
6426
omrthread_detach(thandle);
6427
#else
6428
f_threadDetach(thandle);
6429
#endif /* CALL_BUNDLED_FUNCTIONS_DIRECTLY */
6430
}
6431
} else {
6432
success = TRUE;
6433
}
6434
6435
return success;
6436
}
6437
6438
/**
6439
* @return ZOS_THR_WEIGHT_HEAVY or ZOS_THR_WEIGHT_MEDIUM if the customer is
6440
* explicitly requesting heavy or medium weight threads via the
6441
* JAVA_THREAD_MODEL env var. Otherwise, it returns
6442
* ZOS_THR_WEIGHT_NOT_FOUND.
6443
*/
6444
static UDATA
6445
checkZOSThrWeightEnvVar(void)
6446
{
6447
UDATA retVal = ZOS_THR_WEIGHT_NOT_FOUND;
6448
#pragma convlit(suspend)
6449
#undef getenv
6450
const char * const val = getenv("JAVA_THREAD_MODEL");
6451
6452
if (NULL != val) {
6453
/*
6454
* If the customer did not request heavy weight, assume medium.
6455
* Note that the goal here is not to properly parse the env
6456
* var. This is done in threadParseArguments() and it will flag
6457
* if the customer attempts to pass a bad value in the env var.
6458
*/
6459
if (0 == strcmp(val, "HEAVY")) {
6460
#pragma convlit(resume)
6461
retVal = ZOS_THR_WEIGHT_HEAVY;
6462
} else {
6463
retVal = ZOS_THR_WEIGHT_MEDIUM;
6464
}
6465
}
6466
6467
return retVal;
6468
}
6469
#endif /* defined(J9ZOS390) */
6470
6471
void JNICALL
6472
JVM_BeforeHalt()
6473
{
6474
/* To be implemented via https://github.com/eclipse-openj9/openj9/issues/1459 */
6475
}
6476
6477