Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/java/lang/ClassLoader.c
38829 views
1
/*
2
* Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
#include <stdlib.h>
27
#include <assert.h>
28
29
#include "jni.h"
30
#include "jni_util.h"
31
#include "jlong.h"
32
#include "jvm.h"
33
#include "java_lang_ClassLoader.h"
34
#include "java_lang_ClassLoader_NativeLibrary.h"
35
#include <string.h>
36
37
/* defined in libverify.so/verify.dll (src file common/check_format.c) */
38
extern jboolean VerifyClassname(char *utf_name, jboolean arrayAllowed);
39
extern jboolean VerifyFixClassname(char *utf_name);
40
41
static JNINativeMethod methods[] = {
42
{"retrieveDirectives", "()Ljava/lang/AssertionStatusDirectives;", (void *)&JVM_AssertionStatusDirectives}
43
};
44
45
JNIEXPORT void JNICALL
46
Java_java_lang_ClassLoader_registerNatives(JNIEnv *env, jclass cls)
47
{
48
(*env)->RegisterNatives(env, cls, methods,
49
sizeof(methods)/sizeof(JNINativeMethod));
50
}
51
52
/* Convert java string to UTF char*. Use local buffer if possible,
53
otherwise malloc new memory. Returns null IFF malloc failed. */
54
char*
55
getUTF(JNIEnv *env, jstring str, char* localBuf, int bufSize)
56
{
57
char* utfStr = NULL;
58
59
int len = (*env)->GetStringUTFLength(env, str);
60
int unicode_len = (*env)->GetStringLength(env, str);
61
if (len >= bufSize) {
62
utfStr = malloc(len + 1);
63
if (utfStr == NULL) {
64
JNU_ThrowOutOfMemoryError(env, NULL);
65
return NULL;
66
}
67
} else {
68
utfStr = localBuf;
69
}
70
(*env)->GetStringUTFRegion(env, str, 0, unicode_len, utfStr);
71
72
return utfStr;
73
}
74
75
// The existence or signature of this method is not guaranteed since it
76
// supports a private method. This method will be changed in 1.7.
77
JNIEXPORT jclass JNICALL
78
Java_java_lang_ClassLoader_defineClass0(JNIEnv *env,
79
jobject loader,
80
jstring name,
81
jbyteArray data,
82
jint offset,
83
jint length,
84
jobject pd)
85
{
86
return Java_java_lang_ClassLoader_defineClass1(env, loader, name, data, offset,
87
length, pd, NULL);
88
}
89
90
JNIEXPORT jclass JNICALL
91
Java_java_lang_ClassLoader_defineClass1(JNIEnv *env,
92
jobject loader,
93
jstring name,
94
jbyteArray data,
95
jint offset,
96
jint length,
97
jobject pd,
98
jstring source)
99
{
100
jbyte *body;
101
char *utfName;
102
jclass result = 0;
103
char buf[128];
104
char* utfSource;
105
char sourceBuf[1024];
106
107
if (data == NULL) {
108
JNU_ThrowNullPointerException(env, 0);
109
return 0;
110
}
111
112
/* Work around 4153825. malloc crashes on Solaris when passed a
113
* negative size.
114
*/
115
if (length < 0) {
116
JNU_ThrowArrayIndexOutOfBoundsException(env, 0);
117
return 0;
118
}
119
120
body = (jbyte *)malloc(length);
121
122
if (body == 0) {
123
JNU_ThrowOutOfMemoryError(env, 0);
124
return 0;
125
}
126
127
(*env)->GetByteArrayRegion(env, data, offset, length, body);
128
129
if ((*env)->ExceptionOccurred(env))
130
goto free_body;
131
132
if (name != NULL) {
133
utfName = getUTF(env, name, buf, sizeof(buf));
134
if (utfName == NULL) {
135
goto free_body;
136
}
137
VerifyFixClassname(utfName);
138
} else {
139
utfName = NULL;
140
}
141
142
if (source != NULL) {
143
utfSource = getUTF(env, source, sourceBuf, sizeof(sourceBuf));
144
if (utfSource == NULL) {
145
goto free_utfName;
146
}
147
} else {
148
utfSource = NULL;
149
}
150
result = JVM_DefineClassWithSource(env, utfName, loader, body, length, pd, utfSource);
151
152
if (utfSource && utfSource != sourceBuf)
153
free(utfSource);
154
155
free_utfName:
156
if (utfName && utfName != buf)
157
free(utfName);
158
159
free_body:
160
free(body);
161
return result;
162
}
163
164
JNIEXPORT jclass JNICALL
165
Java_java_lang_ClassLoader_defineClass2(JNIEnv *env,
166
jobject loader,
167
jstring name,
168
jobject data,
169
jint offset,
170
jint length,
171
jobject pd,
172
jstring source)
173
{
174
jbyte *body;
175
char *utfName;
176
jclass result = 0;
177
char buf[128];
178
char* utfSource;
179
char sourceBuf[1024];
180
181
assert(data != NULL); // caller fails if data is null.
182
assert(length >= 0); // caller passes ByteBuffer.remaining() for length, so never neg.
183
// caller passes ByteBuffer.position() for offset, and capacity() >= position() + remaining()
184
assert((*env)->GetDirectBufferCapacity(env, data) >= (offset + length));
185
186
body = (*env)->GetDirectBufferAddress(env, data);
187
188
if (body == 0) {
189
JNU_ThrowNullPointerException(env, 0);
190
return 0;
191
}
192
193
body += offset;
194
195
if (name != NULL) {
196
utfName = getUTF(env, name, buf, sizeof(buf));
197
if (utfName == NULL) {
198
JNU_ThrowOutOfMemoryError(env, NULL);
199
return result;
200
}
201
VerifyFixClassname(utfName);
202
} else {
203
utfName = NULL;
204
}
205
206
if (source != NULL) {
207
utfSource = getUTF(env, source, sourceBuf, sizeof(sourceBuf));
208
if (utfSource == NULL) {
209
JNU_ThrowOutOfMemoryError(env, NULL);
210
goto free_utfName;
211
}
212
} else {
213
utfSource = NULL;
214
}
215
result = JVM_DefineClassWithSource(env, utfName, loader, body, length, pd, utfSource);
216
217
if (utfSource && utfSource != sourceBuf)
218
free(utfSource);
219
220
free_utfName:
221
if (utfName && utfName != buf)
222
free(utfName);
223
224
return result;
225
}
226
227
JNIEXPORT void JNICALL
228
Java_java_lang_ClassLoader_resolveClass0(JNIEnv *env, jobject this,
229
jclass cls)
230
{
231
if (cls == NULL) {
232
JNU_ThrowNullPointerException(env, 0);
233
return;
234
}
235
236
JVM_ResolveClass(env, cls);
237
}
238
239
/*
240
* Returns NULL if class not found.
241
*/
242
JNIEXPORT jclass JNICALL
243
Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv *env, jobject loader,
244
jstring classname)
245
{
246
char *clname;
247
jclass cls = 0;
248
char buf[128];
249
250
if (classname == NULL) {
251
return 0;
252
}
253
254
clname = getUTF(env, classname, buf, sizeof(buf));
255
if (clname == NULL) {
256
JNU_ThrowOutOfMemoryError(env, NULL);
257
return NULL;
258
}
259
VerifyFixClassname(clname);
260
261
if (!VerifyClassname(clname, JNI_TRUE)) { /* expects slashed name */
262
goto done;
263
}
264
265
cls = JVM_FindClassFromBootLoader(env, clname);
266
267
done:
268
if (clname != buf) {
269
free(clname);
270
}
271
272
return cls;
273
}
274
275
JNIEXPORT jclass JNICALL
276
Java_java_lang_ClassLoader_findLoadedClass0(JNIEnv *env, jobject loader,
277
jstring name)
278
{
279
if (name == NULL) {
280
return 0;
281
} else {
282
return JVM_FindLoadedClass(env, loader, name);
283
}
284
}
285
286
static jfieldID handleID;
287
static jfieldID jniVersionID;
288
static jfieldID loadedID;
289
static void *procHandle;
290
291
static jboolean initIDs(JNIEnv *env)
292
{
293
if (handleID == 0) {
294
jclass this =
295
(*env)->FindClass(env, "java/lang/ClassLoader$NativeLibrary");
296
if (this == 0)
297
return JNI_FALSE;
298
handleID = (*env)->GetFieldID(env, this, "handle", "J");
299
if (handleID == 0)
300
return JNI_FALSE;
301
jniVersionID = (*env)->GetFieldID(env, this, "jniVersion", "I");
302
if (jniVersionID == 0)
303
return JNI_FALSE;
304
loadedID = (*env)->GetFieldID(env, this, "loaded", "Z");
305
if (loadedID == 0)
306
return JNI_FALSE;
307
procHandle = getProcessHandle();
308
}
309
return JNI_TRUE;
310
}
311
312
typedef jint (JNICALL *JNI_OnLoad_t)(JavaVM *, void *);
313
typedef void (JNICALL *JNI_OnUnload_t)(JavaVM *, void *);
314
315
/*
316
* Support for finding JNI_On(Un)Load_<lib_name> if it exists.
317
* If cname == NULL then just find normal JNI_On(Un)Load entry point
318
*/
319
static void *findJniFunction(JNIEnv *env, void *handle,
320
const char *cname, jboolean isLoad) {
321
const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS;
322
const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS;
323
const char **syms;
324
int symsLen;
325
void *entryName = NULL;
326
char *jniFunctionName;
327
int i;
328
int len;
329
330
// Check for JNI_On(Un)Load<_libname> function
331
if (isLoad) {
332
syms = onLoadSymbols;
333
symsLen = sizeof(onLoadSymbols) / sizeof(char *);
334
} else {
335
syms = onUnloadSymbols;
336
symsLen = sizeof(onUnloadSymbols) / sizeof(char *);
337
}
338
for (i = 0; i < symsLen; i++) {
339
// cname + sym + '_' + '\0'
340
if ((len = (cname != NULL ? strlen(cname) : 0) + strlen(syms[i]) + 2) >
341
FILENAME_MAX) {
342
goto done;
343
}
344
jniFunctionName = malloc(len);
345
if (jniFunctionName == NULL) {
346
JNU_ThrowOutOfMemoryError(env, NULL);
347
goto done;
348
}
349
buildJniFunctionName(syms[i], cname, jniFunctionName);
350
entryName = JVM_FindLibraryEntry(handle, jniFunctionName);
351
free(jniFunctionName);
352
if(entryName) {
353
break;
354
}
355
}
356
357
done:
358
return entryName;
359
}
360
361
/*
362
* Class: java_lang_ClassLoader_NativeLibrary
363
* Method: load
364
* Signature: (Ljava/lang/String;Z)V
365
*/
366
JNIEXPORT void JNICALL
367
Java_java_lang_ClassLoader_00024NativeLibrary_load
368
(JNIEnv *env, jobject this, jstring name, jboolean isBuiltin)
369
{
370
const char *cname;
371
jint jniVersion;
372
jthrowable cause;
373
void * handle;
374
375
if (!initIDs(env))
376
return;
377
378
cname = JNU_GetStringPlatformChars(env, name, 0);
379
if (cname == 0)
380
return;
381
handle = isBuiltin ? procHandle : JVM_LoadLibrary(cname);
382
if (handle) {
383
JNI_OnLoad_t JNI_OnLoad;
384
JNI_OnLoad = (JNI_OnLoad_t)findJniFunction(env, handle,
385
isBuiltin ? cname : NULL,
386
JNI_TRUE);
387
if (JNI_OnLoad) {
388
JavaVM *jvm;
389
(*env)->GetJavaVM(env, &jvm);
390
jniVersion = (*JNI_OnLoad)(jvm, NULL);
391
} else {
392
jniVersion = 0x00010001;
393
}
394
395
cause = (*env)->ExceptionOccurred(env);
396
if (cause) {
397
(*env)->ExceptionClear(env);
398
(*env)->Throw(env, cause);
399
if (!isBuiltin) {
400
JVM_UnloadLibrary(handle);
401
}
402
goto done;
403
}
404
405
if (!JVM_IsSupportedJNIVersion(jniVersion) ||
406
(isBuiltin && jniVersion < JNI_VERSION_1_8)) {
407
char msg[256];
408
jio_snprintf(msg, sizeof(msg),
409
"unsupported JNI version 0x%08X required by %s",
410
jniVersion, cname);
411
JNU_ThrowByName(env, "java/lang/UnsatisfiedLinkError", msg);
412
if (!isBuiltin) {
413
JVM_UnloadLibrary(handle);
414
}
415
goto done;
416
}
417
(*env)->SetIntField(env, this, jniVersionID, jniVersion);
418
} else {
419
cause = (*env)->ExceptionOccurred(env);
420
if (cause) {
421
(*env)->ExceptionClear(env);
422
(*env)->SetLongField(env, this, handleID, (jlong)0);
423
(*env)->Throw(env, cause);
424
}
425
goto done;
426
}
427
(*env)->SetLongField(env, this, handleID, ptr_to_jlong(handle));
428
(*env)->SetBooleanField(env, this, loadedID, JNI_TRUE);
429
430
done:
431
JNU_ReleaseStringPlatformChars(env, name, cname);
432
}
433
434
/*
435
* Class: java_lang_ClassLoader_NativeLibrary
436
* Method: unload
437
* Signature: (Z)V
438
*/
439
JNIEXPORT void JNICALL
440
Java_java_lang_ClassLoader_00024NativeLibrary_unload
441
(JNIEnv *env, jobject this, jstring name, jboolean isBuiltin)
442
{
443
const char *onUnloadSymbols[] = JNI_ONUNLOAD_SYMBOLS;
444
void *handle;
445
JNI_OnUnload_t JNI_OnUnload;
446
const char *cname;
447
448
if (!initIDs(env))
449
return;
450
cname = JNU_GetStringPlatformChars(env, name, 0);
451
if (cname == NULL) {
452
return;
453
}
454
handle = jlong_to_ptr((*env)->GetLongField(env, this, handleID));
455
JNI_OnUnload = (JNI_OnUnload_t )findJniFunction(env, handle,
456
isBuiltin ? cname : NULL,
457
JNI_FALSE);
458
if (JNI_OnUnload) {
459
JavaVM *jvm;
460
(*env)->GetJavaVM(env, &jvm);
461
(*JNI_OnUnload)(jvm, NULL);
462
}
463
if (!isBuiltin) {
464
JVM_UnloadLibrary(handle);
465
}
466
JNU_ReleaseStringPlatformChars(env, name, cname);
467
}
468
469
/*
470
* Class: java_lang_ClassLoader_NativeLibrary
471
* Method: find
472
* Signature: (Ljava/lang/String;)J
473
*/
474
JNIEXPORT jlong JNICALL
475
Java_java_lang_ClassLoader_00024NativeLibrary_find
476
(JNIEnv *env, jobject this, jstring name)
477
{
478
jlong handle;
479
const char *cname;
480
jlong res;
481
482
if (!initIDs(env))
483
return jlong_zero;
484
485
handle = (*env)->GetLongField(env, this, handleID);
486
cname = (*env)->GetStringUTFChars(env, name, 0);
487
if (cname == 0)
488
return jlong_zero;
489
res = ptr_to_jlong(JVM_FindLibraryEntry(jlong_to_ptr(handle), cname));
490
(*env)->ReleaseStringUTFChars(env, name, cname);
491
return res;
492
}
493
/*
494
* Class: java_lang_ClassLoader
495
* Method: findBuiltinLib
496
* Signature: (Ljava/lang/String;)Ljava/lang/String;
497
*/
498
JNIEXPORT jstring JNICALL
499
Java_java_lang_ClassLoader_findBuiltinLib
500
(JNIEnv *env, jclass cls, jstring name)
501
{
502
const char *cname;
503
char *libName;
504
int prefixLen = (int) strlen(JNI_LIB_PREFIX);
505
int suffixLen = (int) strlen(JNI_LIB_SUFFIX);
506
int len;
507
jstring lib;
508
void *ret;
509
const char *onLoadSymbols[] = JNI_ONLOAD_SYMBOLS;
510
511
if (name == NULL) {
512
JNU_ThrowInternalError(env, "NULL filename for native library");
513
return NULL;
514
}
515
procHandle = getProcessHandle();
516
cname = JNU_GetStringPlatformChars(env, name, 0);
517
if (cname == NULL) {
518
return NULL;
519
}
520
// Copy name Skipping PREFIX
521
len = strlen(cname);
522
if (len <= (prefixLen+suffixLen)) {
523
JNU_ReleaseStringPlatformChars(env, name, cname);
524
return NULL;
525
}
526
libName = malloc(len + 1); //+1 for null if prefix+suffix == 0
527
if (libName == NULL) {
528
JNU_ReleaseStringPlatformChars(env, name, cname);
529
JNU_ThrowOutOfMemoryError(env, NULL);
530
return NULL;
531
}
532
if (len > prefixLen) {
533
strcpy(libName, cname+prefixLen);
534
}
535
JNU_ReleaseStringPlatformChars(env, name, cname);
536
537
// Strip SUFFIX
538
libName[strlen(libName)-suffixLen] = '\0';
539
540
// Check for JNI_OnLoad_libname function
541
ret = findJniFunction(env, procHandle, libName, JNI_TRUE);
542
if (ret != NULL) {
543
lib = JNU_NewStringPlatform(env, libName);
544
free(libName);
545
return lib;
546
}
547
free(libName);
548
return NULL;
549
}
550
551