Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/jfr/jni/jfrJavaSupport.cpp
41149 views
1
/*
2
* Copyright (c) 2016, 2021, 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
// caller needs ResourceMark
491
const char* JfrJavaSupport::c_str(oop string, JavaThread* t) {
492
DEBUG_ONLY(check_java_thread_in_vm(t));
493
char* resource_copy = NULL;
494
const typeArrayOop value = java_lang_String::value(string);
495
if (value != NULL) {
496
const int length = java_lang_String::utf8_length(string, value);
497
resource_copy = NEW_RESOURCE_ARRAY_IN_THREAD(t, char, (length + 1));
498
if (resource_copy == NULL) {
499
JfrJavaSupport::throw_out_of_memory_error("Unable to allocate thread local native memory", t);
500
return NULL;
501
}
502
assert(resource_copy != NULL, "invariant");
503
java_lang_String::as_utf8_string(string, value, resource_copy, length + 1);
504
}
505
return resource_copy;
506
}
507
508
// caller needs ResourceMark
509
const char* JfrJavaSupport::c_str(jstring string, JavaThread* t) {
510
DEBUG_ONLY(check_java_thread_in_vm(t));
511
return string != NULL ? c_str(resolve_non_null(string), t) : NULL;
512
}
513
514
/*
515
* Exceptions and errors
516
*/
517
static void create_and_throw(Symbol* name, const char* message, TRAPS) {
518
assert(name != NULL, "invariant");
519
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
520
assert(!HAS_PENDING_EXCEPTION, "invariant");
521
THROW_MSG(name, message);
522
}
523
524
void JfrJavaSupport::throw_illegal_state_exception(const char* message, TRAPS) {
525
create_and_throw(vmSymbols::java_lang_IllegalStateException(), message, THREAD);
526
}
527
528
void JfrJavaSupport::throw_internal_error(const char* message, TRAPS) {
529
create_and_throw(vmSymbols::java_lang_InternalError(), message, THREAD);
530
}
531
532
void JfrJavaSupport::throw_illegal_argument_exception(const char* message, TRAPS) {
533
create_and_throw(vmSymbols::java_lang_IllegalArgumentException(), message, THREAD);
534
}
535
536
void JfrJavaSupport::throw_out_of_memory_error(const char* message, TRAPS) {
537
create_and_throw(vmSymbols::java_lang_OutOfMemoryError(), message, THREAD);
538
}
539
540
void JfrJavaSupport::throw_class_format_error(const char* message, TRAPS) {
541
create_and_throw(vmSymbols::java_lang_ClassFormatError(), message, THREAD);
542
}
543
544
void JfrJavaSupport::throw_runtime_exception(const char* message, TRAPS) {
545
create_and_throw(vmSymbols::java_lang_RuntimeException(), message, THREAD);
546
}
547
548
void JfrJavaSupport::abort(jstring errorMsg, JavaThread* t) {
549
DEBUG_ONLY(check_java_thread_in_vm(t));
550
551
ResourceMark rm(t);
552
const char* const error_msg = c_str(errorMsg, t);
553
if (error_msg != NULL) {
554
log_error(jfr, system)("%s",error_msg);
555
}
556
log_error(jfr, system)("%s", "An irrecoverable error in Jfr. Shutting down VM...");
557
vm_abort();
558
}
559
560
JfrJavaSupport::CAUSE JfrJavaSupport::_cause = JfrJavaSupport::VM_ERROR;
561
void JfrJavaSupport::set_cause(jthrowable throwable, JavaThread* t) {
562
DEBUG_ONLY(check_java_thread_in_vm(t));
563
564
HandleMark hm(t);
565
Handle ex(t, JNIHandles::resolve_external_guard(throwable));
566
567
if (ex.is_null()) {
568
return;
569
}
570
571
if (ex->is_a(vmClasses::OutOfMemoryError_klass())) {
572
_cause = OUT_OF_MEMORY;
573
return;
574
}
575
if (ex->is_a(vmClasses::StackOverflowError_klass())) {
576
_cause = STACK_OVERFLOW;
577
return;
578
}
579
if (ex->is_a(vmClasses::Error_klass())) {
580
_cause = VM_ERROR;
581
return;
582
}
583
if (ex->is_a(vmClasses::RuntimeException_klass())) {
584
_cause = RUNTIME_EXCEPTION;
585
return;
586
}
587
if (ex->is_a(vmClasses::Exception_klass())) {
588
_cause = UNKNOWN;
589
return;
590
}
591
}
592
593
void JfrJavaSupport::uncaught_exception(jthrowable throwable, JavaThread* t) {
594
DEBUG_ONLY(check_java_thread_in_vm(t));
595
assert(throwable != NULL, "invariant");
596
set_cause(throwable, t);
597
}
598
599
JfrJavaSupport::CAUSE JfrJavaSupport::cause() {
600
return _cause;
601
}
602
603
const char* const JDK_JFR_MODULE_NAME = "jdk.jfr";
604
const char* const JDK_JFR_PACKAGE_NAME = "jdk/jfr";
605
606
static bool is_jdk_jfr_module_in_readability_graph() {
607
// take one of the packages in the module to be located and query for its definition.
608
TempNewSymbol pkg_sym = SymbolTable::new_symbol(JDK_JFR_PACKAGE_NAME);
609
return Modules::is_package_defined(pkg_sym, Handle());
610
}
611
612
static void print_module_resolution_error(outputStream* stream) {
613
assert(stream != NULL, "invariant");
614
stream->print_cr("Module %s not found.", JDK_JFR_MODULE_NAME);
615
stream->print_cr("Flight Recorder can not be enabled.");
616
}
617
618
bool JfrJavaSupport::is_jdk_jfr_module_available() {
619
return is_jdk_jfr_module_in_readability_graph();
620
}
621
622
bool JfrJavaSupport::is_jdk_jfr_module_available(outputStream* stream, TRAPS) {
623
if (!JfrJavaSupport::is_jdk_jfr_module_available()) {
624
if (stream != NULL) {
625
print_module_resolution_error(stream);
626
}
627
return false;
628
}
629
return true;
630
}
631
632
class ThreadExclusionListAccess : public StackObj {
633
private:
634
static Semaphore _mutex_semaphore;
635
public:
636
ThreadExclusionListAccess() { _mutex_semaphore.wait(); }
637
~ThreadExclusionListAccess() { _mutex_semaphore.signal(); }
638
};
639
640
Semaphore ThreadExclusionListAccess::_mutex_semaphore(1);
641
static GrowableArray<jweak>* exclusion_list = NULL;
642
643
static bool equals(const jweak excluded_thread, Handle target_thread) {
644
return JfrJavaSupport::resolve_non_null(excluded_thread) == target_thread();
645
}
646
647
static int find_exclusion_thread_idx(Handle thread) {
648
if (exclusion_list != NULL) {
649
for (int i = 0; i < exclusion_list->length(); ++i) {
650
if (equals(exclusion_list->at(i), thread)) {
651
return i;
652
}
653
}
654
}
655
return -1;
656
}
657
658
static Handle as_handle(jobject thread) {
659
return Handle(Thread::current(), JfrJavaSupport::resolve_non_null(thread));
660
}
661
662
static bool thread_is_not_excluded(Handle thread) {
663
return -1 == find_exclusion_thread_idx(thread);
664
}
665
666
static bool thread_is_not_excluded(jobject thread) {
667
return thread_is_not_excluded(as_handle(thread));
668
}
669
670
static bool is_thread_excluded(jobject thread) {
671
return !thread_is_not_excluded(thread);
672
}
673
674
#ifdef ASSERT
675
static bool is_thread_excluded(Handle thread) {
676
return !thread_is_not_excluded(thread);
677
}
678
#endif // ASSERT
679
680
static int add_thread_to_exclusion_list(jobject thread) {
681
ThreadExclusionListAccess lock;
682
if (exclusion_list == NULL) {
683
exclusion_list = new (ResourceObj::C_HEAP, mtTracing) GrowableArray<jweak>(10, mtTracing);
684
}
685
assert(exclusion_list != NULL, "invariant");
686
assert(thread_is_not_excluded(thread), "invariant");
687
jweak ref = JfrJavaSupport::global_weak_jni_handle(thread, JavaThread::current());
688
const int idx = exclusion_list->append(ref);
689
assert(is_thread_excluded(thread), "invariant");
690
return idx;
691
}
692
693
static void remove_thread_from_exclusion_list(Handle thread) {
694
assert(exclusion_list != NULL, "invariant");
695
assert(is_thread_excluded(thread), "invariant");
696
assert(exclusion_list != NULL, "invariant");
697
const int idx = find_exclusion_thread_idx(thread);
698
assert(idx >= 0, "invariant");
699
assert(idx < exclusion_list->length(), "invariant");
700
JfrJavaSupport::destroy_global_weak_jni_handle(exclusion_list->at(idx));
701
exclusion_list->delete_at(idx);
702
assert(thread_is_not_excluded(thread), "invariant");
703
if (0 == exclusion_list->length()) {
704
delete exclusion_list;
705
exclusion_list = NULL;
706
}
707
}
708
709
static void remove_thread_from_exclusion_list(jobject thread) {
710
ThreadExclusionListAccess lock;
711
remove_thread_from_exclusion_list(as_handle(thread));
712
}
713
714
// includes removal
715
static bool check_exclusion_state_on_thread_start(JavaThread* jt) {
716
Handle h_obj(jt, jt->threadObj());
717
ThreadExclusionListAccess lock;
718
if (thread_is_not_excluded(h_obj)) {
719
return false;
720
}
721
remove_thread_from_exclusion_list(h_obj);
722
return true;
723
}
724
725
static JavaThread* get_native(jobject thread) {
726
ThreadsListHandle tlh;
727
JavaThread* native_thread = NULL;
728
(void)tlh.cv_internal_thread_to_JavaThread(thread, &native_thread, NULL);
729
return native_thread;
730
}
731
732
jlong JfrJavaSupport::jfr_thread_id(jobject thread) {
733
JavaThread* native_thread = get_native(thread);
734
return native_thread != NULL ? JFR_THREAD_ID(native_thread) : 0;
735
}
736
737
void JfrJavaSupport::exclude(jobject thread) {
738
JavaThread* native_thread = get_native(thread);
739
if (native_thread != NULL) {
740
JfrThreadLocal::exclude(native_thread);
741
} else {
742
// not started yet, track the thread oop
743
add_thread_to_exclusion_list(thread);
744
}
745
}
746
747
void JfrJavaSupport::include(jobject thread) {
748
JavaThread* native_thread = get_native(thread);
749
if (native_thread != NULL) {
750
JfrThreadLocal::include(native_thread);
751
} else {
752
// not started yet, untrack the thread oop
753
remove_thread_from_exclusion_list(thread);
754
}
755
}
756
757
bool JfrJavaSupport::is_excluded(jobject thread) {
758
JavaThread* native_thread = get_native(thread);
759
return native_thread != NULL ? native_thread->jfr_thread_local()->is_excluded() : is_thread_excluded(thread);
760
}
761
762
jobject JfrJavaSupport::get_handler(jobject clazz, TRAPS) {
763
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
764
const oop klass_oop = JNIHandles::resolve(clazz);
765
assert(klass_oop != NULL, "invariant");
766
Klass* klass = java_lang_Class::as_Klass(klass_oop);
767
HandleMark hm(THREAD);
768
Handle h_klass_oop(Handle(THREAD, klass->java_mirror()));
769
InstanceKlass* const instance_klass = static_cast<InstanceKlass*>(klass);
770
klass->initialize(CHECK_NULL);
771
772
fieldDescriptor event_handler_field;
773
Klass* f = instance_klass->find_field(
774
vmSymbols::eventHandler_name(),
775
vmSymbols::jdk_jfr_internal_handlers_EventHandler_signature(),
776
true, &event_handler_field);
777
if (f != NULL) {
778
oop ret = h_klass_oop->obj_field(event_handler_field.offset());
779
return ret != NULL ? JfrJavaSupport::local_jni_handle(ret, THREAD) : NULL;
780
}
781
782
fieldDescriptor object_field;
783
Klass* g = instance_klass->find_field(
784
vmSymbols::eventHandler_name(),
785
vmSymbols::object_signature(),
786
true, &object_field);
787
if (g != NULL) {
788
oop ret = h_klass_oop->obj_field(object_field.offset());
789
return ret != NULL ? JfrJavaSupport::local_jni_handle(ret, THREAD) : NULL;
790
}
791
assert(f == NULL && g == NULL, "no handler field for class");
792
return NULL;
793
}
794
795
bool JfrJavaSupport::set_handler(jobject clazz, jobject handler, TRAPS) {
796
DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD));
797
const oop klass_oop = JNIHandles::resolve(clazz);
798
assert(klass_oop != NULL, "invariant");
799
const oop handler_oop = JNIHandles::resolve(handler);
800
assert(handler_oop != NULL, "invariant");
801
Klass* klass = java_lang_Class::as_Klass(klass_oop);
802
HandleMark hm(THREAD);
803
Handle h_klass_oop(Handle(THREAD, klass->java_mirror()));
804
InstanceKlass* const instance_klass = static_cast<InstanceKlass*>(klass);
805
klass->initialize(CHECK_false);
806
807
fieldDescriptor event_handler_field;
808
Klass* f = instance_klass->find_field(
809
vmSymbols::eventHandler_name(),
810
vmSymbols::jdk_jfr_internal_handlers_EventHandler_signature(),
811
true, &event_handler_field);
812
if (f != NULL) {
813
h_klass_oop->obj_field_put(event_handler_field.offset(), handler_oop);
814
return true;
815
}
816
817
fieldDescriptor object_handler_field;
818
Klass* g = instance_klass->find_field(
819
vmSymbols::eventHandler_name(),
820
vmSymbols::object_signature(),
821
true, &object_handler_field);
822
if (g != NULL) {
823
h_klass_oop->obj_field_put(object_handler_field.offset(), handler_oop);
824
return true;
825
}
826
assert(f == NULL && g == NULL, "no handler field for class");
827
return false;
828
}
829
830
void JfrJavaSupport::on_thread_start(Thread* t) {
831
assert(t != NULL, "invariant");
832
assert(Thread::current() == t, "invariant");
833
if (!t->is_Java_thread()) {
834
return;
835
}
836
DEBUG_ONLY(check_new_unstarted_java_thread(t->as_Java_thread());)
837
HandleMark hm(t);
838
if (check_exclusion_state_on_thread_start(t->as_Java_thread())) {
839
JfrThreadLocal::exclude(t);
840
}
841
}
842
843