Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/share/jni/ExceptionCheckingJniEnv.cpp
41162 views
1
/*
2
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
3
* Copyright (c) 2018, 2019, Google and/or its affiliates. All rights reserved.
4
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5
*
6
* This code is free software; you can redistribute it and/or modify it
7
* under the terms of the GNU General Public License version 2 only, as
8
* published by the Free Software Foundation.
9
*
10
* This code is distributed in the hope that it will be useful, but WITHOUT
11
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13
* version 2 for more details (a copy is included in the LICENSE file that
14
* accompanied this code).
15
*
16
* You should have received a copy of the GNU General Public License version
17
* 2 along with this work; if not, write to the Free Software Foundation,
18
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19
*
20
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21
* or visit www.oracle.com if you need additional information or have any
22
* questions.
23
*/
24
25
#include <stdint.h>
26
#include <stdlib.h>
27
#include <string.h>
28
29
#include "ExceptionCheckingJniEnv.hpp"
30
#include "nsk_tools.h"
31
32
namespace {
33
34
static const char* get_dirname(const char* fullname) {
35
const char* p;
36
const char* base = fullname;;
37
38
if (fullname == NULL) {
39
return NULL;
40
}
41
42
for (p = fullname; *p != '\0'; p++) {
43
if (*p == '/' || *p == '\\') {
44
base = p + 1;
45
}
46
}
47
return base;
48
}
49
50
template<class T = void*>
51
class JNIVerifier {
52
public:
53
JNIVerifier(ExceptionCheckingJniEnv *env, const char* base_message,
54
int line, const char* file)
55
: _env(env), _base_message(base_message), _error_message(NULL),
56
_line(line), _file(get_dirname(file)) {
57
}
58
59
// Until C++11 is supported, we have to write multiple template constructors.
60
template <typename U>
61
JNIVerifier(ExceptionCheckingJniEnv *env, const char* base_message,
62
U parameter,
63
int line, const char* file)
64
: _env(env), _base_message(base_message), _error_message(NULL),
65
_line(line), _file(get_dirname(file)) {
66
PrintPreCall(parameter);
67
}
68
69
template <typename U, typename V>
70
JNIVerifier(ExceptionCheckingJniEnv *env, const char* base_message,
71
U parameter1,
72
V parameter2,
73
int line, const char* file)
74
: _env(env), _base_message(base_message), _error_message(NULL),
75
_line(line), _file(get_dirname(file)) {
76
PrintPreCall(parameter1, parameter2);
77
}
78
79
template <typename U, typename V, typename W>
80
JNIVerifier(ExceptionCheckingJniEnv *env, const char* base_message,
81
U parameter1, V parameter2, W parameter3,
82
int line, const char* file)
83
: _env(env), _base_message(base_message), _error_message(NULL),
84
_line(line), _file(get_dirname(file)) {
85
PrintPreCall(parameter1, parameter2, parameter3);
86
}
87
88
~JNIVerifier() {
89
PrintPostCall();
90
91
JNIEnv* jni_env = _env->GetJNIEnv();
92
if (jni_env->ExceptionCheck() && !_error_message) {
93
_error_message = "internal error";
94
}
95
96
if (_error_message != NULL) {
97
GenerateErrorMessage();
98
}
99
}
100
101
int DecimalToAsciiRec(char *str, int line) {
102
if (line == 0) {
103
return 0;
104
}
105
106
int remainder = line % 10;
107
long quotient = line / 10;
108
109
int pos = DecimalToAsciiRec(str, quotient);
110
str[pos] = '0' + remainder;
111
return pos + 1;
112
}
113
114
// Implementing a simple version of sprintf for "%d"...
115
void DecimalToAscii(char *str, int line) {
116
if (line == 0) {
117
str[0] = '0';
118
str[1] = '\0';
119
return;
120
}
121
122
// Special case for INT32_MIN because otherwise the *1 below will overflow
123
// and it won't work. Let us just be simple here due to this being for
124
// tests.
125
if (line == INT32_MIN) {
126
strcat(str, "-2147483648");
127
return;
128
}
129
130
if (line < 0) {
131
*str = '-';
132
line *= -1;
133
str++;
134
}
135
136
str[DecimalToAsciiRec(str, line)] = '\0';
137
}
138
139
void GenerateErrorMessage() {
140
// This is error prone, but:
141
// - Seems like we cannot use std::string (due to windows/solaris not
142
// building when used, seemingly due to exception libraries not linking).
143
// - Seems like we cannot use sprintf due to VS2013 (JDK-8213622).
144
//
145
// We are aiming to do:
146
// snprintf(full_message, len, "JNI method %s : %s from %s : %d", _base_message, _error_message,
147
// _file, _line);
148
// but will use strlen + memcpy instead.
149
const char* pre_message = "JNI method ";
150
const char* between_msg = " : ";
151
const char* from_msg = " from ";
152
153
const char* file_name = _file ? _file : "Unknown File";
154
const char* strs[] = {
155
pre_message,
156
_base_message,
157
between_msg,
158
_error_message,
159
from_msg,
160
file_name,
161
between_msg,
162
};
163
164
size_t msg_number = sizeof(strs) / sizeof(strs[0]);
165
size_t len = 0;
166
for (size_t i = 0; i < msg_number; i++) {
167
len += strlen(strs[i]);
168
}
169
170
// 32-bit signed means 11 characters due to the '-'.
171
const int MAX_INTEGER_DIGITS = 11;
172
// Add for the line number and 1 for the '\0'.
173
len += MAX_INTEGER_DIGITS + 1;
174
175
char* full_message = (char*) malloc(len);
176
if (full_message == NULL) {
177
_env->HandleError(_error_message);
178
return;
179
}
180
181
// Now we construct the string using strcat to not use sprintf/std::string
182
// instead of:
183
// snprintf(full_message, len, "JNI method %s : %s from %s:%d", _base_message,
184
// _error_message, _file, _line);
185
full_message[0] = '\0';
186
for (size_t i = 0; i < msg_number; i++) {
187
strcat(full_message, strs[i]);
188
}
189
190
// Add line number to end of the string.
191
DecimalToAscii(full_message + strlen(full_message), _line);
192
193
if (strlen(full_message) >= len) {
194
_env->GetJNIEnv()->FatalError("Final length of message is not what was expected");
195
}
196
197
_env->HandleError(full_message);
198
free(full_message);
199
}
200
201
T ResultNotNull(T ptr) {
202
if (ptr == NULL) {
203
_error_message = "Return is NULL";
204
}
205
return ptr;
206
}
207
208
T ResultIsZero(T value) {
209
if (value != 0) {
210
_error_message = "Return is not zero";
211
}
212
return value;
213
}
214
215
void PrintPreCallHeader() {
216
if (!nsk_getVerboseMode()) {
217
return;
218
}
219
220
fprintf(stdout, ">> Calling JNI method %s from %s:%d\n",
221
_base_message, _file, _line);
222
fprintf(stdout, ">> Calling with these parameter(s):\n");
223
}
224
225
// Until we can actually link with C++ more uniformely across architectures,
226
// we have to do this...
227
template<class U>
228
void PrintParameter(U* ptr) {
229
fprintf(stdout, "\t%p\n", ptr);
230
}
231
232
void PrintParameter(int value) {
233
fprintf(stdout, "\t%d\n", value);
234
}
235
236
// Until C++11 is supported, we have to write multiple PrintPreCall.
237
template<class U>
238
void PrintPreCall(U first_parameter) {
239
if (!nsk_getVerboseMode()) {
240
return;
241
}
242
243
PrintPreCallHeader();
244
PrintParameter(first_parameter);
245
}
246
247
template<class U, class V>
248
void PrintPreCall(U parameter1, V parameter2) {
249
if (!nsk_getVerboseMode()) {
250
return;
251
}
252
253
PrintPreCallHeader();
254
PrintParameter(parameter1);
255
PrintParameter(parameter2);
256
}
257
258
template<class U, class V, class W>
259
void PrintPreCall(U parameter1, V parameter2, W parameter3) {
260
if (!nsk_getVerboseMode()) {
261
return;
262
}
263
264
PrintPreCallHeader();
265
PrintParameter(parameter1);
266
PrintParameter(parameter2);
267
PrintParameter(parameter3);
268
}
269
270
void PrintPostCall() {
271
if (!nsk_getVerboseMode()) {
272
return;
273
}
274
275
fprintf(stderr, "<< Called JNI method %s from %s:%d\n",
276
_base_message, _file, _line);
277
}
278
279
private:
280
ExceptionCheckingJniEnv* _env;
281
const char* const _base_message;
282
const char* _error_message;
283
int _line;
284
const char* const _file;
285
};
286
287
}
288
289
jclass ExceptionCheckingJniEnv::FindClass(const char *class_name,
290
int line, const char* file_name) {
291
JNIVerifier<jclass> marker(this, "FindClass", class_name, line, file_name);
292
return marker.ResultNotNull(_jni_env->FindClass(class_name));
293
}
294
295
jint ExceptionCheckingJniEnv::RegisterNatives(jclass clazz,
296
const JNINativeMethod *methods,
297
jint nMethods,
298
int line,
299
const char* file_name) {
300
JNIVerifier<jint> marker(this, "RegisterNatives", methods, nMethods, line, file_name);
301
return marker.ResultIsZero(_jni_env->RegisterNatives(clazz, methods, nMethods));
302
}
303
304
jclass ExceptionCheckingJniEnv::GetObjectClass(jobject obj, int line,
305
const char* file_name) {
306
JNIVerifier<jclass> marker(this, "GetObjectClass", obj, line, file_name);
307
return marker.ResultNotNull(_jni_env->GetObjectClass(obj));
308
}
309
310
jfieldID ExceptionCheckingJniEnv::GetStaticFieldID(jclass klass, const char *name,
311
const char* type,
312
int line, const char* file_name) {
313
JNIVerifier<jfieldID> marker(this, "GetStaticFieldID", klass, name, type,
314
line, file_name);
315
return marker.ResultNotNull(_jni_env->GetStaticFieldID(klass, name, type));
316
}
317
318
jfieldID ExceptionCheckingJniEnv::GetFieldID(jclass klass, const char *name,
319
const char* type,
320
int line, const char* file_name) {
321
JNIVerifier<jfieldID> marker(this, "GetFieldID", klass, name, type, line, file_name);
322
return marker.ResultNotNull(_jni_env->GetFieldID(klass, name, type));
323
}
324
325
jobject ExceptionCheckingJniEnv::GetStaticObjectField(jclass klass, jfieldID field,
326
int line, const char* file_name) {
327
JNIVerifier<jobject> marker(this, "GetStaticObjectField", klass, field,
328
line, file_name);
329
return marker.ResultNotNull(_jni_env->GetStaticObjectField(klass, field));
330
}
331
332
jobject ExceptionCheckingJniEnv::GetObjectField(jobject obj, jfieldID field,
333
int line, const char* file_name) {
334
JNIVerifier<jobject> marker(this, "GetObjectField", obj, field, line, file_name);
335
return marker.ResultNotNull(_jni_env->GetObjectField(obj, field));
336
}
337
338
void ExceptionCheckingJniEnv::SetObjectField(jobject obj, jfieldID field, jobject value,
339
int line, const char* file_name) {
340
JNIVerifier<> marker(this, "SetObjectField", obj, field, value, line, file_name);
341
_jni_env->SetObjectField(obj, field, value);
342
}
343
344
jobject ExceptionCheckingJniEnv::NewGlobalRef(jobject obj, int line, const char* file_name) {
345
JNIVerifier<jobject> marker(this, "NewGlobalRef", obj, line, file_name);
346
return marker.ResultNotNull(_jni_env->NewGlobalRef(obj));
347
}
348
349
void ExceptionCheckingJniEnv::DeleteGlobalRef(jobject obj, int line, const char* file_name) {
350
JNIVerifier<> marker(this, "DeleteGlobalRef", obj, line, file_name);
351
_jni_env->DeleteGlobalRef(obj);
352
}
353
354
jobject ExceptionCheckingJniEnv::NewLocalRef(jobject obj, int line, const char* file_name) {
355
JNIVerifier<jobject> marker(this, "NewLocalRef", obj, line, file_name);
356
return marker.ResultNotNull(_jni_env->NewLocalRef(obj));
357
}
358
359
void ExceptionCheckingJniEnv::DeleteLocalRef(jobject obj, int line, const char* file_name) {
360
JNIVerifier<> marker(this, "DeleteLocalRef", obj, line, file_name);
361
_jni_env->DeleteLocalRef(obj);
362
}
363
364
jweak ExceptionCheckingJniEnv::NewWeakGlobalRef(jobject obj, int line, const char* file_name) {
365
JNIVerifier<jweak> marker(this, "NewWeakGlobalRef", obj, line, file_name);
366
return marker.ResultNotNull(_jni_env->NewWeakGlobalRef(obj));
367
}
368
369
void ExceptionCheckingJniEnv::DeleteWeakGlobalRef(jweak weak_ref, int line, const char* file_name) {
370
JNIVerifier<> marker(this, "DeleteWeakGlobalRef", weak_ref, line, file_name);
371
_jni_env->DeleteWeakGlobalRef(weak_ref);
372
}
373
374
jsize ExceptionCheckingJniEnv::GetArrayLength(jarray array, int line, const char* file_name) {
375
JNIVerifier<> marker(this, "GetArrayLength", array, line, file_name);
376
return _jni_env->GetArrayLength(array);
377
}
378
379
jsize ExceptionCheckingJniEnv::GetStringLength(jstring str, int line, const char* file_name) {
380
JNIVerifier<> marker(this, "GetStringLength", str, line, file_name);
381
return _jni_env->GetStringLength(str);
382
}
383
384
void* ExceptionCheckingJniEnv::GetPrimitiveArrayCritical(jarray array, jboolean* is_copy,
385
int line, const char* file_name) {
386
JNIVerifier<> marker(this, "GetPrimitiveArrayCritical", array, is_copy, line, file_name);
387
return marker.ResultNotNull(_jni_env->GetPrimitiveArrayCritical(array, is_copy));
388
}
389
390
void ExceptionCheckingJniEnv::ReleasePrimitiveArrayCritical(jarray array, void* carray, jint mode,
391
int line, const char* file_name) {
392
JNIVerifier<> marker(this, "ReleasePrimitiveArrayCritical", array, carray, mode,
393
line, file_name);
394
_jni_env->ReleasePrimitiveArrayCritical(array, carray, mode);
395
}
396
397
const jchar* ExceptionCheckingJniEnv::GetStringCritical(jstring str, jboolean* is_copy,
398
int line, const char* file_name) {
399
JNIVerifier<const jchar*> marker(this, "GetPrimitiveArrayCritical", str, is_copy,
400
line, file_name);
401
return marker.ResultNotNull(_jni_env->GetStringCritical(str, is_copy));
402
}
403
404
void ExceptionCheckingJniEnv::ReleaseStringCritical(jstring str, const jchar* carray,
405
int line, const char* file_name) {
406
JNIVerifier<> marker(this, "ReleaseStringCritical", str, carray, line, file_name);
407
_jni_env->ReleaseStringCritical(str, carray);
408
}
409
410
jbyte* ExceptionCheckingJniEnv::GetByteArrayElements(jbyteArray array, jboolean* is_copy,
411
int line, const char* file_name) {
412
JNIVerifier<jbyte*> marker(this, "GetByteArrayElements", array, is_copy, line, file_name);
413
return marker.ResultNotNull(_jni_env->GetByteArrayElements(array, is_copy));
414
}
415
416
void ExceptionCheckingJniEnv::ReleaseByteArrayElements(jbyteArray array, jbyte* byte_array, jint mode,
417
int line, const char* file_name) {
418
JNIVerifier<> marker(this, "ReleaseByteArrayElements", array, byte_array, mode,
419
line, file_name);
420
_jni_env->ReleaseByteArrayElements(array, byte_array, mode);
421
}
422
423
jmethodID ExceptionCheckingJniEnv::GetMethodID(jclass klass, const char* name, const char* sig,
424
int line, const char* file_name) {
425
JNIVerifier<jmethodID> marker(this, "GetMethodID", klass, name, sig, line, file_name);
426
return marker.ResultNotNull(_jni_env->GetMethodID(klass, name, sig));
427
}
428
429
jmethodID ExceptionCheckingJniEnv::GetStaticMethodID(jclass klass, const char* name, const char* sig,
430
int line, const char* file_name) {
431
JNIVerifier<jmethodID> marker(this, "GetStaticMethodID", klass, name, sig, line, file_name);
432
return marker.ResultNotNull(_jni_env->GetStaticMethodID(klass, name, sig));
433
}
434
435
jboolean ExceptionCheckingJniEnv::IsSameObject(jobject ref1, jobject ref2, int line, const char* file_name) {
436
JNIVerifier<> marker(this, "IsSameObject", ref1, ref2, line, file_name);
437
return _jni_env->IsSameObject(ref1, ref2);
438
}
439
440
jobject ExceptionCheckingJniEnv::NewObject(jclass klass, jmethodID methodID,
441
int line, const char* file_name, ...) {
442
// In the case of NewObject, we miss the extra arguments passed to NewObject sadly.
443
JNIVerifier<jobject> marker(this, "NewObject", klass, methodID, line, file_name);
444
445
va_list args;
446
va_start(args, file_name);
447
jobject result = marker.ResultNotNull(_jni_env->NewObjectV(klass, methodID, args));
448
va_end(args);
449
return result;
450
}
451
452
jobject ExceptionCheckingJniEnv::CallObjectMethod(jobject obj, jmethodID methodID, int line,
453
const char* file_name, ...) {
454
JNIVerifier<> marker(this, "CallObjectMethod", obj, methodID, line, file_name);
455
456
va_list args;
457
va_start(args, file_name);
458
jobject result = _jni_env->CallObjectMethodV(obj, methodID, args);
459
va_end(args);
460
return result;
461
}
462
463
void ExceptionCheckingJniEnv::CallVoidMethod(jobject obj, jmethodID methodID, int line,
464
const char* file_name, ...) {
465
JNIVerifier<> marker(this, "CallVoidMethod", obj, methodID, line, file_name);
466
467
va_list args;
468
va_start(args, file_name);
469
_jni_env->CallVoidMethodV(obj, methodID, args);
470
va_end(args);
471
}
472
473