Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/jdk17u
Path: blob/master/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp
66644 views
1
/*
2
* Copyright (c) 2016, 2022, 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.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
#include "precompiled.hpp"
26
#include "classfile/javaClasses.inline.hpp"
27
#include "classfile/modules.hpp"
28
#include "classfile/symbolTable.hpp"
29
#include "classfile/vmClasses.hpp"
30
#include "classfile/vmSymbols.hpp"
31
#include "jfr/jni/jfrJavaCall.hpp"
32
#include "jfr/jni/jfrJavaSupport.hpp"
33
#include "jfr/support/jfrThreadId.hpp"
34
#include "logging/log.hpp"
35
#include "memory/resourceArea.hpp"
36
#include "oops/instanceOop.hpp"
37
#include "oops/klass.inline.hpp"
38
#include "oops/oop.inline.hpp"
39
#include "oops/objArrayKlass.hpp"
40
#include "oops/objArrayOop.inline.hpp"
41
#include "runtime/handles.inline.hpp"
42
#include "runtime/fieldDescriptor.inline.hpp"
43
#include "runtime/java.hpp"
44
#include "runtime/jniHandles.inline.hpp"
45
#include "runtime/semaphore.inline.hpp"
46
#include "runtime/synchronizer.hpp"
47
#include "runtime/thread.inline.hpp"
48
#include "runtime/threadSMR.hpp"
49
#include "utilities/growableArray.hpp"
50
#include "classfile/vmSymbols.hpp"
51
52
#ifdef ASSERT
53
void JfrJavaSupport::check_java_thread_in_vm(JavaThread* t) {
54
assert(t != NULL, "invariant");
55
assert(t->thread_state() == _thread_in_vm, "invariant");
56
}
57
58
void JfrJavaSupport::check_java_thread_in_native(JavaThread* t) {
59
assert(t != NULL, "invariant");
60
assert(t->thread_state() == _thread_in_native, "invariant");
61
}
62
63
static void check_new_unstarted_java_thread(JavaThread* t) {
64
assert(t != NULL, "invariant");
65
assert(t->thread_state() == _thread_new, "invariant");
66
}
67
#endif
68
69
/*
70
* Handles and references
71
*/
72
jobject JfrJavaSupport::local_jni_handle(const oop obj, JavaThread* t) {
73
DEBUG_ONLY(check_java_thread_in_vm(t));
74
return t->active_handles()->allocate_handle(obj);
75
}
76
77
jobject JfrJavaSupport::local_jni_handle(const jobject handle, JavaThread* t) {
78
DEBUG_ONLY(check_java_thread_in_vm(t));
79
const oop obj = JNIHandles::resolve(handle);
80
return obj == NULL ? NULL : local_jni_handle(obj, t);
81
}
82
83
void JfrJavaSupport::destroy_local_jni_handle(jobject handle) {
84
JNIHandles::destroy_local(handle);
85
}
86
87
jobject JfrJavaSupport::global_jni_handle(const oop obj, JavaThread* t) {
88
DEBUG_ONLY(check_java_thread_in_vm(t));
89
HandleMark hm(t);
90
return JNIHandles::make_global(Handle(t, obj));
91
}
92
93
jobject JfrJavaSupport::global_jni_handle(const jobject handle, JavaThread* t) {
94
const oop obj = JNIHandles::resolve(handle);
95
return obj == NULL ? NULL : global_jni_handle(obj, t);
96
}
97
98
void JfrJavaSupport::destroy_global_jni_handle(jobject handle) {
99
JNIHandles::destroy_global(handle);
100
}
101
102
jweak JfrJavaSupport::global_weak_jni_handle(const oop obj, JavaThread* t) {
103
DEBUG_ONLY(check_java_thread_in_vm(t));
104
HandleMark hm(t);
105
return JNIHandles::make_weak_global(Handle(t, obj));
106
}
107
108
jweak JfrJavaSupport::global_weak_jni_handle(const jobject handle, JavaThread* t) {
109
const oop obj = JNIHandles::resolve(handle);
110
return obj == NULL ? NULL : global_weak_jni_handle(obj, t);
111
}
112
113
void JfrJavaSupport::destroy_global_weak_jni_handle(jweak handle) {
114
JNIHandles::destroy_weak_global(handle);
115
}
116
117
oop JfrJavaSupport::resolve_non_null(jobject obj) {
118
return JNIHandles::resolve_non_null(obj);
119
}
120
121
/*
122
* Method invocation
123
*/
124
void JfrJavaSupport::call_static(JfrJavaArguments* args, TRAPS) {
125
JfrJavaCall::call_static(args, THREAD);
126
}
127
128
void JfrJavaSupport::call_special(JfrJavaArguments* args, TRAPS) {
129
JfrJavaCall::call_special(args, THREAD);
130
}
131
132
void JfrJavaSupport::call_virtual(JfrJavaArguments* args, TRAPS) {
133
JfrJavaCall::call_virtual(args, THREAD);
134
}
135
136
void JfrJavaSupport::notify_all(jobject object, TRAPS) {
137
assert(object != NULL, "invariant");
138
DEBUG_ONLY(check_java_thread_in_vm(THREAD));
139
HandleMark hm(THREAD);
140
Handle h_obj(THREAD, resolve_non_null(object));
141
assert(h_obj.not_null(), "invariant");
142
ObjectSynchronizer::jni_enter(h_obj, THREAD);
143
ObjectSynchronizer::notifyall(h_obj, THREAD);
144
ObjectSynchronizer::jni_exit(h_obj(), THREAD);
145
DEBUG_ONLY(check_java_thread_in_vm(THREAD));
146
}
147
148
/*
149
* Object construction
150
*/
151
static void object_construction(JfrJavaArguments* args, JavaValue* result, InstanceKlass* klass, TRAPS) {
152
assert(args != NULL, "invariant");
153
assert(result != NULL, "invariant");
154
assert(klass != NULL, "invariant");
155
assert(klass->is_initialized(), "invariant");
156
157
HandleMark hm(THREAD);
158
instanceOop obj = klass->allocate_instance(CHECK);
159
instanceHandle h_obj(THREAD, obj);
160
assert(h_obj.not_null(), "invariant");
161
args->set_receiver(h_obj);
162
result->set_type(T_VOID); // constructor result type
163
JfrJavaSupport::call_special(args, CHECK);
164
result->set_type(T_OBJECT); // set back to original result type
165
result->set_oop(h_obj());
166
}
167
168
static void array_construction(JfrJavaArguments* args, JavaValue* result, InstanceKlass* klass, int array_length, TRAPS) {
169
assert(args != NULL, "invariant");
170
assert(result != NULL, "invariant");
171
assert(klass != NULL, "invariant");
172
assert(klass->is_initialized(), "invariant");
173
174
Klass* const ak = klass->array_klass(THREAD);
175
ObjArrayKlass::cast(ak)->initialize(THREAD);
176
HandleMark hm(THREAD);
177
objArrayOop arr = ObjArrayKlass::cast(ak)->allocate(array_length, CHECK);
178
result->set_oop(arr);
179
}
180
181
static void create_object(JfrJavaArguments* args, JavaValue* result, TRAPS) {
182
assert(args != NULL, "invariant");
183
assert(result != NULL, "invariant");
184
assert(result->get_type() == T_OBJECT, "invariant");
185
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
186
187
InstanceKlass* const klass = static_cast<InstanceKlass*>(args->klass());
188
klass->initialize(CHECK);
189
190
const int array_length = args->array_length();
191
192
if (array_length >= 0) {
193
array_construction(args, result, klass, array_length, CHECK);
194
} else {
195
object_construction(args, result, klass, THREAD);
196
}
197
}
198
199
static void handle_result(JavaValue* result, bool global_ref, JavaThread* t) {
200
assert(result != NULL, "invariant");
201
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(t));
202
const oop result_oop = result->get_oop();
203
if (result_oop == NULL) {
204
return;
205
}
206
result->set_jobject(global_ref ?
207
JfrJavaSupport::global_jni_handle(result_oop, t) :
208
JfrJavaSupport::local_jni_handle(result_oop, t));
209
}
210
211
void JfrJavaSupport::new_object(JfrJavaArguments* args, TRAPS) {
212
assert(args != NULL, "invariant");
213
DEBUG_ONLY(check_java_thread_in_vm(THREAD));
214
create_object(args, args->result(), THREAD);
215
}
216
217
void JfrJavaSupport::new_object_local_ref(JfrJavaArguments* args, TRAPS) {
218
assert(args != NULL, "invariant");
219
DEBUG_ONLY(check_java_thread_in_vm(THREAD));
220
JavaValue* const result = args->result();
221
assert(result != NULL, "invariant");
222
create_object(args, result, CHECK);
223
handle_result(result, false, THREAD);
224
}
225
226
void JfrJavaSupport::new_object_global_ref(JfrJavaArguments* args, TRAPS) {
227
assert(args != NULL, "invariant");
228
DEBUG_ONLY(check_java_thread_in_vm(THREAD));
229
JavaValue* const result = args->result();
230
assert(result != NULL, "invariant");
231
create_object(args, result, CHECK);
232
handle_result(result, true, THREAD);
233
}
234
235
jstring JfrJavaSupport::new_string(const char* c_str, TRAPS) {
236
assert(c_str != NULL, "invariant");
237
DEBUG_ONLY(check_java_thread_in_vm(THREAD));
238
const oop result = java_lang_String::create_oop_from_str(c_str, THREAD);
239
return (jstring)local_jni_handle(result, THREAD);
240
}
241
242
jobjectArray JfrJavaSupport::new_string_array(int length, TRAPS) {
243
DEBUG_ONLY(check_java_thread_in_vm(THREAD));
244
JavaValue result(T_OBJECT);
245
JfrJavaArguments args(&result, "java/lang/String", "<init>", "()V", CHECK_NULL);
246
args.set_array_length(length);
247
new_object_local_ref(&args, THREAD);
248
return (jobjectArray)args.result()->get_jobject();
249
}
250
251
jobject JfrJavaSupport::new_java_lang_Boolean(bool value, TRAPS) {
252
DEBUG_ONLY(check_java_thread_in_vm(THREAD));
253
JavaValue result(T_OBJECT);
254
JfrJavaArguments args(&result, "java/lang/Boolean", "<init>", "(Z)V", CHECK_NULL);
255
args.push_int(value ? (jint)JNI_TRUE : (jint)JNI_FALSE);
256
new_object_local_ref(&args, THREAD);
257
return args.result()->get_jobject();
258
}
259
260
jobject JfrJavaSupport::new_java_lang_Integer(jint value, TRAPS) {
261
DEBUG_ONLY(check_java_thread_in_vm(THREAD));
262
JavaValue result(T_OBJECT);
263
JfrJavaArguments args(&result, "java/lang/Integer", "<init>", "(I)V", CHECK_NULL);
264
args.push_int(value);
265
new_object_local_ref(&args, THREAD);
266
return args.result()->get_jobject();
267
}
268
269
jobject JfrJavaSupport::new_java_lang_Long(jlong value, TRAPS) {
270
DEBUG_ONLY(check_java_thread_in_vm(THREAD));
271
JavaValue result(T_OBJECT);
272
JfrJavaArguments args(&result, "java/lang/Long", "<init>", "(J)V", CHECK_NULL);
273
args.push_long(value);
274
new_object_local_ref(&args, THREAD);
275
return args.result()->get_jobject();
276
}
277
278
void JfrJavaSupport::set_array_element(jobjectArray arr, jobject element, int index, JavaThread* t) {
279
assert(arr != NULL, "invariant");
280
DEBUG_ONLY(check_java_thread_in_vm(t));
281
HandleMark hm(t);
282
objArrayHandle a(t, (objArrayOop)resolve_non_null(arr));
283
a->obj_at_put(index, resolve_non_null(element));
284
}
285
286
/*
287
* Field access
288
*/
289
static void write_int_field(const Handle& h_oop, fieldDescriptor* fd, jint value) {
290
assert(h_oop.not_null(), "invariant");
291
assert(fd != NULL, "invariant");
292
h_oop->int_field_put(fd->offset(), value);
293
}
294
295
static void write_float_field(const Handle& h_oop, fieldDescriptor* fd, jfloat value) {
296
assert(h_oop.not_null(), "invariant");
297
assert(fd != NULL, "invariant");
298
h_oop->float_field_put(fd->offset(), value);
299
}
300
301
static void write_double_field(const Handle& h_oop, fieldDescriptor* fd, jdouble value) {
302
assert(h_oop.not_null(), "invariant");
303
assert(fd != NULL, "invariant");
304
h_oop->double_field_put(fd->offset(), value);
305
}
306
307
static void write_long_field(const Handle& h_oop, fieldDescriptor* fd, jlong value) {
308
assert(h_oop.not_null(), "invariant");
309
assert(fd != NULL, "invariant");
310
h_oop->long_field_put(fd->offset(), value);
311
}
312
313
static void write_oop_field(const Handle& h_oop, fieldDescriptor* fd, const oop value) {
314
assert(h_oop.not_null(), "invariant");
315
assert(fd != NULL, "invariant");
316
h_oop->obj_field_put(fd->offset(), value);
317
}
318
319
static void write_specialized_field(JfrJavaArguments* args, const Handle& h_oop, fieldDescriptor* fd, bool static_field) {
320
assert(args != NULL, "invariant");
321
assert(h_oop.not_null(), "invariant");
322
assert(fd != NULL, "invariant");
323
assert(fd->offset() > 0, "invariant");
324
assert(args->length() >= 1, "invariant");
325
326
// attempt must set a real value
327
assert(args->param(1).get_type() != T_VOID, "invariant");
328
329
switch(fd->field_type()) {
330
case T_BOOLEAN:
331
case T_CHAR:
332
case T_SHORT:
333
case T_INT:
334
write_int_field(h_oop, fd, args->param(1).get_jint());
335
break;
336
case T_FLOAT:
337
write_float_field(h_oop, fd, args->param(1).get_jfloat());
338
break;
339
case T_DOUBLE:
340
write_double_field(h_oop, fd, args->param(1).get_jdouble());
341
break;
342
case T_LONG:
343
write_long_field(h_oop, fd, args->param(1).get_jlong());
344
break;
345
case T_OBJECT:
346
write_oop_field(h_oop, fd, args->param(1).get_oop());
347
break;
348
case T_ADDRESS:
349
write_oop_field(h_oop, fd, JfrJavaSupport::resolve_non_null(args->param(1).get_jobject()));
350
break;
351
default:
352
ShouldNotReachHere();
353
}
354
}
355
356
static void read_specialized_field(JavaValue* result, const Handle& h_oop, fieldDescriptor* fd) {
357
assert(result != NULL, "invariant");
358
assert(h_oop.not_null(), "invariant");
359
assert(fd != NULL, "invariant");
360
assert(fd->offset() > 0, "invariant");
361
362
switch(fd->field_type()) {
363
case T_BOOLEAN:
364
case T_CHAR:
365
case T_SHORT:
366
case T_INT:
367
result->set_jint(h_oop->int_field(fd->offset()));
368
break;
369
case T_FLOAT:
370
result->set_jfloat(h_oop->float_field(fd->offset()));
371
break;
372
case T_DOUBLE:
373
result->set_jdouble(h_oop->double_field(fd->offset()));
374
break;
375
case T_LONG:
376
result->set_jlong(h_oop->long_field(fd->offset()));
377
break;
378
case T_OBJECT:
379
result->set_oop(h_oop->obj_field(fd->offset()));
380
break;
381
default:
382
ShouldNotReachHere();
383
}
384
}
385
386
static bool find_field(InstanceKlass* ik,
387
Symbol* name_symbol,
388
Symbol* signature_symbol,
389
fieldDescriptor* fd,
390
bool is_static = false,
391
bool allow_super = false) {
392
if (allow_super || is_static) {
393
return ik->find_field(name_symbol, signature_symbol, is_static, fd) != NULL;
394
}
395
return ik->find_local_field(name_symbol, signature_symbol, fd);
396
}
397
398
static void lookup_field(JfrJavaArguments* args, InstanceKlass* klass, fieldDescriptor* fd, bool static_field) {
399
assert(args != NULL, "invariant");
400
assert(klass != NULL, "invariant");
401
assert(klass->is_initialized(), "invariant");
402
assert(fd != NULL, "invariant");
403
find_field(klass, args->name(), args->signature(), fd, static_field, true);
404
}
405
406
static void read_field(JfrJavaArguments* args, JavaValue* result, TRAPS) {
407
assert(args != NULL, "invariant");
408
assert(result != NULL, "invariant");
409
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
410
411
InstanceKlass* const klass = static_cast<InstanceKlass*>(args->klass());
412
klass->initialize(CHECK);
413
const bool static_field = !args->has_receiver();
414
fieldDescriptor fd;
415
lookup_field(args, klass, &fd, static_field);
416
assert(fd.offset() > 0, "invariant");
417
418
HandleMark hm(THREAD);
419
Handle h_oop(static_field ? Handle(THREAD, klass->java_mirror()) : Handle(THREAD, args->receiver()));
420
read_specialized_field(result, h_oop, &fd);
421
}
422
423
static void write_field(JfrJavaArguments* args, JavaValue* result, TRAPS) {
424
assert(args != NULL, "invariant");
425
assert(result != NULL, "invariant");
426
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
427
428
InstanceKlass* const klass = static_cast<InstanceKlass*>(args->klass());
429
klass->initialize(CHECK);
430
431
const bool static_field = !args->has_receiver();
432
fieldDescriptor fd;
433
lookup_field(args, klass, &fd, static_field);
434
assert(fd.offset() > 0, "invariant");
435
436
HandleMark hm(THREAD);
437
Handle h_oop(static_field ? Handle(THREAD, klass->java_mirror()) : Handle(THREAD, args->receiver()));
438
write_specialized_field(args, h_oop, &fd, static_field);
439
}
440
441
void JfrJavaSupport::set_field(JfrJavaArguments* args, TRAPS) {
442
assert(args != NULL, "invariant");
443
write_field(args, args->result(), THREAD);
444
}
445
446
void JfrJavaSupport::get_field(JfrJavaArguments* args, TRAPS) {
447
assert(args != NULL, "invariant");
448
read_field(args, args->result(), THREAD);
449
}
450
451
void JfrJavaSupport::get_field_local_ref(JfrJavaArguments* args, TRAPS) {
452
assert(args != NULL, "invariant");
453
DEBUG_ONLY(check_java_thread_in_vm(THREAD));
454
455
JavaValue* const result = args->result();
456
assert(result != NULL, "invariant");
457
assert(result->get_type() == T_OBJECT, "invariant");
458
459
read_field(args, result, CHECK);
460
const oop obj = result->get_oop();
461
462
if (obj != NULL) {
463
result->set_jobject(local_jni_handle(obj, THREAD));
464
}
465
}
466
467
void JfrJavaSupport::get_field_global_ref(JfrJavaArguments* args, TRAPS) {
468
assert(args != NULL, "invariant");
469
DEBUG_ONLY(check_java_thread_in_vm(THREAD));
470
471
JavaValue* const result = args->result();
472
assert(result != NULL, "invariant");
473
assert(result->get_type() == T_OBJECT, "invariant");
474
read_field(args, result, CHECK);
475
const oop obj = result->get_oop();
476
if (obj != NULL) {
477
result->set_jobject(global_jni_handle(obj, THREAD));
478
}
479
}
480
481
/*
482
* Misc
483
*/
484
Klass* JfrJavaSupport::klass(const jobject handle) {
485
const oop obj = resolve_non_null(handle);
486
assert(obj != NULL, "invariant");
487
return obj->klass();
488
}
489
490
static char* allocate_string(bool c_heap, int length, JavaThread* jt) {
491
return c_heap ? NEW_C_HEAP_ARRAY(char, length, mtTracing) :
492
NEW_RESOURCE_ARRAY_IN_THREAD(jt, char, length);
493
}
494
495
const char* JfrJavaSupport::c_str(oop string, JavaThread* t, bool c_heap /* false */) {
496
DEBUG_ONLY(check_java_thread_in_vm(t));
497
char* str = NULL;
498
const typeArrayOop value = java_lang_String::value(string);
499
if (value != NULL) {
500
const int length = java_lang_String::utf8_length(string, value);
501
str = allocate_string(c_heap, length + 1, t);
502
if (str == NULL) {
503
JfrJavaSupport::throw_out_of_memory_error("Unable to allocate native memory", t);
504
return NULL;
505
}
506
java_lang_String::as_utf8_string(string, value, str, length + 1);
507
}
508
return str;
509
}
510
511
const char* JfrJavaSupport::c_str(jstring string, JavaThread* t, bool c_heap /* false */) {
512
DEBUG_ONLY(check_java_thread_in_vm(t));
513
return string != NULL ? c_str(resolve_non_null(string), t, c_heap) : NULL;
514
}
515
516
/*
517
* Exceptions and errors
518
*/
519
static void create_and_throw(Symbol* name, const char* message, TRAPS) {
520
assert(name != NULL, "invariant");
521
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
522
assert(!HAS_PENDING_EXCEPTION, "invariant");
523
THROW_MSG(name, message);
524
}
525
526
void JfrJavaSupport::throw_illegal_state_exception(const char* message, TRAPS) {
527
create_and_throw(vmSymbols::java_lang_IllegalStateException(), message, THREAD);
528
}
529
530
void JfrJavaSupport::throw_internal_error(const char* message, TRAPS) {
531
create_and_throw(vmSymbols::java_lang_InternalError(), message, THREAD);
532
}
533
534
void JfrJavaSupport::throw_illegal_argument_exception(const char* message, TRAPS) {
535
create_and_throw(vmSymbols::java_lang_IllegalArgumentException(), message, THREAD);
536
}
537
538
void JfrJavaSupport::throw_out_of_memory_error(const char* message, TRAPS) {
539
create_and_throw(vmSymbols::java_lang_OutOfMemoryError(), message, THREAD);
540
}
541
542
void JfrJavaSupport::throw_class_format_error(const char* message, TRAPS) {
543
create_and_throw(vmSymbols::java_lang_ClassFormatError(), message, THREAD);
544
}
545
546
void JfrJavaSupport::throw_runtime_exception(const char* message, TRAPS) {
547
create_and_throw(vmSymbols::java_lang_RuntimeException(), message, THREAD);
548
}
549
550
void JfrJavaSupport::abort(jstring errorMsg, JavaThread* t) {
551
DEBUG_ONLY(check_java_thread_in_vm(t));
552
ResourceMark rm(t);
553
abort(c_str(errorMsg, t));
554
}
555
556
void JfrJavaSupport::abort(const char* error_msg, bool dump_core /* true */) {
557
if (error_msg != nullptr) {
558
log_error(jfr, system)("%s", error_msg);
559
}
560
log_error(jfr, system)("%s", "An irrecoverable error in Jfr. Shutting down VM...");
561
vm_abort(dump_core);
562
}
563
564
JfrJavaSupport::CAUSE JfrJavaSupport::_cause = JfrJavaSupport::VM_ERROR;
565
void JfrJavaSupport::set_cause(jthrowable throwable, JavaThread* t) {
566
DEBUG_ONLY(check_java_thread_in_vm(t));
567
568
HandleMark hm(t);
569
Handle ex(t, JNIHandles::resolve_external_guard(throwable));
570
571
if (ex.is_null()) {
572
return;
573
}
574
575
if (ex->is_a(vmClasses::OutOfMemoryError_klass())) {
576
_cause = OUT_OF_MEMORY;
577
return;
578
}
579
if (ex->is_a(vmClasses::StackOverflowError_klass())) {
580
_cause = STACK_OVERFLOW;
581
return;
582
}
583
if (ex->is_a(vmClasses::Error_klass())) {
584
_cause = VM_ERROR;
585
return;
586
}
587
if (ex->is_a(vmClasses::RuntimeException_klass())) {
588
_cause = RUNTIME_EXCEPTION;
589
return;
590
}
591
if (ex->is_a(vmClasses::Exception_klass())) {
592
_cause = UNKNOWN;
593
return;
594
}
595
}
596
597
void JfrJavaSupport::uncaught_exception(jthrowable throwable, JavaThread* t) {
598
DEBUG_ONLY(check_java_thread_in_vm(t));
599
assert(throwable != NULL, "invariant");
600
set_cause(throwable, t);
601
}
602
603
JfrJavaSupport::CAUSE JfrJavaSupport::cause() {
604
return _cause;
605
}
606
607
const char* const JDK_JFR_MODULE_NAME = "jdk.jfr";
608
const char* const JDK_JFR_PACKAGE_NAME = "jdk/jfr";
609
610
static bool is_jdk_jfr_module_in_readability_graph() {
611
// take one of the packages in the module to be located and query for its definition.
612
TempNewSymbol pkg_sym = SymbolTable::new_symbol(JDK_JFR_PACKAGE_NAME);
613
return Modules::is_package_defined(pkg_sym, Handle());
614
}
615
616
static void print_module_resolution_error(outputStream* stream) {
617
assert(stream != NULL, "invariant");
618
stream->print_cr("Module %s not found.", JDK_JFR_MODULE_NAME);
619
stream->print_cr("Flight Recorder can not be enabled.");
620
}
621
622
bool JfrJavaSupport::is_jdk_jfr_module_available() {
623
return is_jdk_jfr_module_in_readability_graph();
624
}
625
626
bool JfrJavaSupport::is_jdk_jfr_module_available(outputStream* stream, TRAPS) {
627
if (!JfrJavaSupport::is_jdk_jfr_module_available()) {
628
if (stream != NULL) {
629
print_module_resolution_error(stream);
630
}
631
return false;
632
}
633
return true;
634
}
635
636
class ThreadExclusionListAccess : public StackObj {
637
private:
638
static Semaphore _mutex_semaphore;
639
public:
640
ThreadExclusionListAccess() { _mutex_semaphore.wait(); }
641
~ThreadExclusionListAccess() { _mutex_semaphore.signal(); }
642
};
643
644
Semaphore ThreadExclusionListAccess::_mutex_semaphore(1);
645
static GrowableArray<jweak>* exclusion_list = NULL;
646
647
static bool equals(const jweak excluded_thread, Handle target_thread) {
648
return JfrJavaSupport::resolve_non_null(excluded_thread) == target_thread();
649
}
650
651
static int find_exclusion_thread_idx(Handle thread) {
652
if (exclusion_list != NULL) {
653
for (int i = 0; i < exclusion_list->length(); ++i) {
654
if (equals(exclusion_list->at(i), thread)) {
655
return i;
656
}
657
}
658
}
659
return -1;
660
}
661
662
static Handle as_handle(jobject thread) {
663
return Handle(Thread::current(), JfrJavaSupport::resolve_non_null(thread));
664
}
665
666
static bool thread_is_not_excluded(Handle thread) {
667
return -1 == find_exclusion_thread_idx(thread);
668
}
669
670
static bool thread_is_not_excluded(jobject thread) {
671
return thread_is_not_excluded(as_handle(thread));
672
}
673
674
static bool is_thread_excluded(jobject thread) {
675
return !thread_is_not_excluded(thread);
676
}
677
678
#ifdef ASSERT
679
static bool is_thread_excluded(Handle thread) {
680
return !thread_is_not_excluded(thread);
681
}
682
#endif // ASSERT
683
684
static int add_thread_to_exclusion_list(jobject thread) {
685
ThreadExclusionListAccess lock;
686
if (exclusion_list == NULL) {
687
exclusion_list = new (ResourceObj::C_HEAP, mtTracing) GrowableArray<jweak>(10, mtTracing);
688
}
689
assert(exclusion_list != NULL, "invariant");
690
assert(thread_is_not_excluded(thread), "invariant");
691
jweak ref = JfrJavaSupport::global_weak_jni_handle(thread, JavaThread::current());
692
const int idx = exclusion_list->append(ref);
693
assert(is_thread_excluded(thread), "invariant");
694
return idx;
695
}
696
697
static void remove_thread_from_exclusion_list(Handle thread) {
698
assert(exclusion_list != NULL, "invariant");
699
assert(is_thread_excluded(thread), "invariant");
700
assert(exclusion_list != NULL, "invariant");
701
const int idx = find_exclusion_thread_idx(thread);
702
assert(idx >= 0, "invariant");
703
assert(idx < exclusion_list->length(), "invariant");
704
JfrJavaSupport::destroy_global_weak_jni_handle(exclusion_list->at(idx));
705
exclusion_list->delete_at(idx);
706
assert(thread_is_not_excluded(thread), "invariant");
707
if (0 == exclusion_list->length()) {
708
delete exclusion_list;
709
exclusion_list = NULL;
710
}
711
}
712
713
static void remove_thread_from_exclusion_list(jobject thread) {
714
ThreadExclusionListAccess lock;
715
remove_thread_from_exclusion_list(as_handle(thread));
716
}
717
718
// includes removal
719
static bool check_exclusion_state_on_thread_start(JavaThread* jt) {
720
Handle h_obj(jt, jt->threadObj());
721
ThreadExclusionListAccess lock;
722
if (thread_is_not_excluded(h_obj)) {
723
return false;
724
}
725
remove_thread_from_exclusion_list(h_obj);
726
return true;
727
}
728
729
static JavaThread* get_native(jobject thread) {
730
ThreadsListHandle tlh;
731
JavaThread* native_thread = NULL;
732
(void)tlh.cv_internal_thread_to_JavaThread(thread, &native_thread, NULL);
733
return native_thread;
734
}
735
736
jlong JfrJavaSupport::jfr_thread_id(jobject thread) {
737
JavaThread* native_thread = get_native(thread);
738
return native_thread != NULL ? JFR_THREAD_ID(native_thread) : 0;
739
}
740
741
void JfrJavaSupport::exclude(jobject thread) {
742
JavaThread* native_thread = get_native(thread);
743
if (native_thread != NULL) {
744
JfrThreadLocal::exclude(native_thread);
745
} else {
746
// not started yet, track the thread oop
747
add_thread_to_exclusion_list(thread);
748
}
749
}
750
751
void JfrJavaSupport::include(jobject thread) {
752
JavaThread* native_thread = get_native(thread);
753
if (native_thread != NULL) {
754
JfrThreadLocal::include(native_thread);
755
} else {
756
// not started yet, untrack the thread oop
757
remove_thread_from_exclusion_list(thread);
758
}
759
}
760
761
bool JfrJavaSupport::is_excluded(jobject thread) {
762
JavaThread* native_thread = get_native(thread);
763
return native_thread != NULL ? native_thread->jfr_thread_local()->is_excluded() : is_thread_excluded(thread);
764
}
765
766
static const Klass* get_handler_field_descriptor(const Handle& h_mirror, fieldDescriptor* descriptor, TRAPS) {
767
assert(h_mirror.not_null(), "invariant");
768
assert(descriptor != NULL, "invariant");
769
Klass* const k = java_lang_Class::as_Klass(h_mirror());
770
assert(k->is_instance_klass(), "invariant");
771
InstanceKlass* const ik = InstanceKlass::cast(k);
772
if (ik->is_not_initialized()) {
773
ik->initialize(CHECK_NULL);
774
}
775
assert(ik->is_being_initialized() || ik->is_initialized(), "invariant");
776
const Klass* const typed_field_holder = ik->find_field(vmSymbols::eventHandler_name(),
777
vmSymbols::jdk_jfr_internal_handlers_EventHandler_signature(),
778
true,
779
descriptor);
780
return typed_field_holder != NULL ? typed_field_holder : ik->find_field(vmSymbols::eventHandler_name(),
781
vmSymbols::object_signature(), // untyped
782
true,
783
descriptor);
784
}
785
786
jobject JfrJavaSupport::get_handler(jobject clazz, TRAPS) {
787
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
788
HandleMark hm(THREAD);
789
const Handle h_mirror(Handle(THREAD, JNIHandles::resolve(clazz)));
790
assert(h_mirror.not_null(), "invariant");
791
fieldDescriptor handler_field_descriptor;
792
const Klass* const field_holder = get_handler_field_descriptor(h_mirror, &handler_field_descriptor, THREAD);
793
if (field_holder == NULL) {
794
// The only reason should be that klass initialization failed.
795
return NULL;
796
}
797
assert(java_lang_Class::as_Klass(h_mirror()) == field_holder, "invariant");
798
oop handler_oop = h_mirror->obj_field(handler_field_descriptor.offset());
799
return handler_oop != NULL ? JfrJavaSupport::local_jni_handle(handler_oop, THREAD) : NULL;
800
}
801
802
bool JfrJavaSupport::set_handler(jobject clazz, jobject handler, TRAPS) {
803
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
804
HandleMark hm(THREAD);
805
const Handle h_mirror(Handle(THREAD, JNIHandles::resolve(clazz)));
806
assert(h_mirror.not_null(), "invariant");
807
fieldDescriptor handler_field_descriptor;
808
const Klass* const field_holder = get_handler_field_descriptor(h_mirror, &handler_field_descriptor, THREAD);
809
if (field_holder == NULL) {
810
// The only reason should be that klass initialization failed.
811
return false;
812
}
813
assert(java_lang_Class::as_Klass(h_mirror()) == field_holder, "invariant");
814
const oop handler_oop = JNIHandles::resolve(handler);
815
assert(handler_oop != NULL, "invariant");
816
h_mirror->obj_field_put(handler_field_descriptor.offset(), handler_oop);
817
return true;
818
}
819
820
void JfrJavaSupport::on_thread_start(Thread* t) {
821
assert(t != NULL, "invariant");
822
assert(Thread::current() == t, "invariant");
823
if (!t->is_Java_thread()) {
824
return;
825
}
826
DEBUG_ONLY(check_new_unstarted_java_thread(t->as_Java_thread());)
827
HandleMark hm(t);
828
if (check_exclusion_state_on_thread_start(t->as_Java_thread())) {
829
JfrThreadLocal::exclude(t);
830
}
831
}
832
833