1 /* 2 * Copyright (c) 2016, 2018, 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 "jni.h" 27 #include "classfile/javaClasses.inline.hpp" 28 #include "classfile/modules.hpp" 29 #include "classfile/symbolTable.hpp" 30 #include "classfile/systemDictionary.hpp" 31 #include "classfile/vmSymbols.hpp" 32 #include "jfr/jni/jfrJavaCall.hpp" 33 #include "jfr/jni/jfrJavaSupport.hpp" 34 #include "logging/log.hpp" 35 #include "memory/resourceArea.hpp" 36 #include "oops/instanceOop.hpp" 37 #include "oops/oop.inline.hpp" 38 #include "oops/objArrayKlass.hpp" 39 #include "oops/objArrayOop.inline.hpp" 40 #include "runtime/handles.inline.hpp" 41 #include "runtime/fieldDescriptor.hpp" 42 #include "runtime/java.hpp" 43 #include "runtime/jniHandles.inline.hpp" 44 #include "runtime/synchronizer.hpp" 45 #include "runtime/thread.inline.hpp" 46 #include "runtime/threadSMR.hpp" 47 48 #ifdef ASSERT 49 void JfrJavaSupport::check_java_thread_in_vm(Thread* t) { 50 assert(t != NULL, "invariant"); 51 assert(t->is_Java_thread(), "invariant"); 52 assert(((JavaThread*)t)->thread_state() == _thread_in_vm, "invariant"); 53 } 54 55 void JfrJavaSupport::check_java_thread_in_native(Thread* t) { 56 assert(t != NULL, "invariant"); 57 assert(t->is_Java_thread(), "invariant"); 58 assert(((JavaThread*)t)->thread_state() == _thread_in_native, "invariant"); 59 } 60 #endif 61 62 /* 63 * Handles and references 64 */ 65 jobject JfrJavaSupport::local_jni_handle(const oop obj, Thread* t) { 66 DEBUG_ONLY(check_java_thread_in_vm(t)); 67 return t->active_handles()->allocate_handle(obj); 68 } 69 70 jobject JfrJavaSupport::local_jni_handle(const jobject handle, Thread* t) { 71 DEBUG_ONLY(check_java_thread_in_vm(t)); 72 const oop obj = JNIHandles::resolve(handle); 73 return obj == NULL ? NULL : local_jni_handle(obj, t); 74 } 75 76 void JfrJavaSupport::destroy_local_jni_handle(jobject handle) { 77 JNIHandles::destroy_local(handle); 78 } 79 80 jobject JfrJavaSupport::global_jni_handle(const oop obj, Thread* t) { 81 DEBUG_ONLY(check_java_thread_in_vm(t)); 82 HandleMark hm(t); 83 return JNIHandles::make_global(Handle(t, obj)); 84 } 85 86 jobject JfrJavaSupport::global_jni_handle(const jobject handle, Thread* t) { 87 const oop obj = JNIHandles::resolve(handle); 88 return obj == NULL ? NULL : global_jni_handle(obj, t); 89 } 90 91 void JfrJavaSupport::destroy_global_jni_handle(jobject handle) { 92 JNIHandles::destroy_global(handle); 93 } 94 95 oop JfrJavaSupport::resolve_non_null(jobject obj) { 96 return JNIHandles::resolve_non_null(obj); 97 } 98 99 /* 100 * Method invocation 101 */ 102 void JfrJavaSupport::call_static(JfrJavaArguments* args, TRAPS) { 103 JfrJavaCall::call_static(args, THREAD); 104 } 105 106 void JfrJavaSupport::call_special(JfrJavaArguments* args, TRAPS) { 107 JfrJavaCall::call_special(args, THREAD); 108 } 109 110 void JfrJavaSupport::call_virtual(JfrJavaArguments* args, TRAPS) { 111 JfrJavaCall::call_virtual(args, THREAD); 112 } 113 114 void JfrJavaSupport::notify_all(jobject object, TRAPS) { 115 assert(object != NULL, "invariant"); 116 DEBUG_ONLY(check_java_thread_in_vm(THREAD)); 117 HandleMark hm(THREAD); 118 Handle h_obj(THREAD, resolve_non_null(object)); 119 assert(h_obj.not_null(), "invariant"); 120 ObjectSynchronizer::jni_enter(h_obj, THREAD); 121 ObjectSynchronizer::notifyall(h_obj, THREAD); 122 ObjectSynchronizer::jni_exit(h_obj(), THREAD); 123 DEBUG_ONLY(check_java_thread_in_vm(THREAD)); 124 } 125 126 /* 127 * Object construction 128 */ 129 static void object_construction(JfrJavaArguments* args, JavaValue* result, InstanceKlass* klass, TRAPS) { 130 assert(args != NULL, "invariant"); 131 assert(result != NULL, "invariant"); 132 assert(klass != NULL, "invariant"); 133 assert(klass->is_initialized(), "invariant"); 134 135 HandleMark hm(THREAD); 136 instanceOop obj = klass->allocate_instance(CHECK); 137 instanceHandle h_obj(THREAD, obj); 138 assert(h_obj.not_null(), "invariant"); 139 args->set_receiver(h_obj); 140 result->set_type(T_VOID); // constructor result type 141 JfrJavaSupport::call_special(args, CHECK); 142 result->set_type(T_OBJECT); // set back to original result type 143 result->set_jobject((jobject)h_obj()); 144 } 145 146 static void array_construction(JfrJavaArguments* args, JavaValue* result, InstanceKlass* klass, int array_length, TRAPS) { 147 assert(args != NULL, "invariant"); 148 assert(result != NULL, "invariant"); 149 assert(klass != NULL, "invariant"); 150 assert(klass->is_initialized(), "invariant"); 151 152 Klass* const ak = klass->array_klass(THREAD); 153 ObjArrayKlass::cast(ak)->initialize(THREAD); 154 HandleMark hm(THREAD); 155 objArrayOop arr = ObjArrayKlass::cast(ak)->allocate(array_length, CHECK); 156 result->set_jobject((jobject)arr); 157 } 158 159 static void create_object(JfrJavaArguments* args, JavaValue* result, TRAPS) { 160 assert(args != NULL, "invariant"); 161 assert(result != NULL, "invariant"); 162 assert(result->get_type() == T_OBJECT, "invariant"); 163 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); 164 165 InstanceKlass* const klass = static_cast<InstanceKlass*>(args->klass()); 166 klass->initialize(CHECK); 167 168 const int array_length = args->array_length(); 169 170 if (array_length > 0) { 171 array_construction(args, result, klass, array_length, CHECK); 172 } else { 173 object_construction(args, result, klass, THREAD); 174 } 175 } 176 177 static void handle_result(JavaValue* result, bool global_ref, Thread* t) { 178 assert(result != NULL, "invariant"); 179 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(t)); 180 const oop result_oop = (const oop)result->get_jobject(); 181 if (result_oop == NULL) { 182 return; 183 } 184 result->set_jobject(global_ref ? 185 JfrJavaSupport::global_jni_handle(result_oop, t) : 186 JfrJavaSupport::local_jni_handle(result_oop, t)); 187 } 188 189 void JfrJavaSupport::new_object(JfrJavaArguments* args, TRAPS) { 190 assert(args != NULL, "invariant"); 191 DEBUG_ONLY(check_java_thread_in_vm(THREAD)); 192 create_object(args, args->result(), THREAD); 193 } 194 195 void JfrJavaSupport::new_object_local_ref(JfrJavaArguments* args, TRAPS) { 196 assert(args != NULL, "invariant"); 197 DEBUG_ONLY(check_java_thread_in_vm(THREAD)); 198 JavaValue* const result = args->result(); 199 assert(result != NULL, "invariant"); 200 create_object(args, result, CHECK); 201 handle_result(result, false, THREAD); 202 } 203 204 void JfrJavaSupport::new_object_global_ref(JfrJavaArguments* args, TRAPS) { 205 assert(args != NULL, "invariant"); 206 DEBUG_ONLY(check_java_thread_in_vm(THREAD)); 207 JavaValue* const result = args->result(); 208 assert(result != NULL, "invariant"); 209 create_object(args, result, CHECK); 210 handle_result(result, true, THREAD); 211 } 212 213 jstring JfrJavaSupport::new_string(const char* c_str, TRAPS) { 214 assert(c_str != NULL, "invariant"); 215 DEBUG_ONLY(check_java_thread_in_vm(THREAD)); 216 const oop result = java_lang_String::create_oop_from_str(c_str, THREAD); 217 return (jstring)local_jni_handle(result, THREAD); 218 } 219 220 jobjectArray JfrJavaSupport::new_string_array(int length, TRAPS) { 221 DEBUG_ONLY(check_java_thread_in_vm(THREAD)); 222 JavaValue result(T_OBJECT); 223 JfrJavaArguments args(&result, "java/lang/String", "<init>", "()V", CHECK_NULL); 224 args.set_array_length(length); 225 new_object_local_ref(&args, THREAD); 226 return (jobjectArray)args.result()->get_jobject(); 227 } 228 229 jobject JfrJavaSupport::new_java_lang_Boolean(bool value, TRAPS) { 230 DEBUG_ONLY(check_java_thread_in_vm(THREAD)); 231 JavaValue result(T_OBJECT); 232 JfrJavaArguments args(&result, "java/lang/Boolean", "<init>", "(Z)V", CHECK_NULL); 233 args.push_int(value ? (jint)JNI_TRUE : (jint)JNI_FALSE); 234 new_object_local_ref(&args, THREAD); 235 return args.result()->get_jobject(); 236 } 237 238 jobject JfrJavaSupport::new_java_lang_Integer(jint value, TRAPS) { 239 DEBUG_ONLY(check_java_thread_in_vm(THREAD)); 240 JavaValue result(T_OBJECT); 241 JfrJavaArguments args(&result, "java/lang/Integer", "<init>", "(I)V", CHECK_NULL); 242 args.push_int(value); 243 new_object_local_ref(&args, THREAD); 244 return args.result()->get_jobject(); 245 } 246 247 jobject JfrJavaSupport::new_java_lang_Long(jlong value, TRAPS) { 248 DEBUG_ONLY(check_java_thread_in_vm(THREAD)); 249 JavaValue result(T_OBJECT); 250 JfrJavaArguments args(&result, "java/lang/Long", "<init>", "(J)V", CHECK_NULL); 251 args.push_long(value); 252 new_object_local_ref(&args, THREAD); 253 return args.result()->get_jobject(); 254 } 255 256 void JfrJavaSupport::set_array_element(jobjectArray arr, jobject element, int index, Thread* t) { 257 assert(arr != NULL, "invariant"); 258 DEBUG_ONLY(check_java_thread_in_vm(t)); 259 HandleMark hm(t); 260 objArrayHandle a(t, (objArrayOop)resolve_non_null(arr)); 261 a->obj_at_put(index, resolve_non_null(element)); 262 } 263 264 /* 265 * Field access 266 */ 267 static void write_int_field(const Handle& h_oop, fieldDescriptor* fd, jint value) { 268 assert(h_oop.not_null(), "invariant"); 269 assert(fd != NULL, "invariant"); 270 h_oop->int_field_put(fd->offset(), value); 271 } 272 273 static void write_float_field(const Handle& h_oop, fieldDescriptor* fd, jfloat value) { 274 assert(h_oop.not_null(), "invariant"); 275 assert(fd != NULL, "invariant"); 276 h_oop->float_field_put(fd->offset(), value); 277 } 278 279 static void write_double_field(const Handle& h_oop, fieldDescriptor* fd, jdouble value) { 280 assert(h_oop.not_null(), "invariant"); 281 assert(fd != NULL, "invariant"); 282 h_oop->double_field_put(fd->offset(), value); 283 } 284 285 static void write_long_field(const Handle& h_oop, fieldDescriptor* fd, jlong value) { 286 assert(h_oop.not_null(), "invariant"); 287 assert(fd != NULL, "invariant"); 288 h_oop->long_field_put(fd->offset(), value); 289 } 290 291 static void write_oop_field(const Handle& h_oop, fieldDescriptor* fd, const oop value) { 292 assert(h_oop.not_null(), "invariant"); 293 assert(fd != NULL, "invariant"); 294 h_oop->obj_field_put(fd->offset(), value); 295 } 296 297 static void write_specialized_field(JfrJavaArguments* args, const Handle& h_oop, fieldDescriptor* fd, bool static_field) { 298 assert(args != NULL, "invariant"); 299 assert(h_oop.not_null(), "invariant"); 300 assert(fd != NULL, "invariant"); 301 assert(fd->offset() > 0, "invariant"); 302 assert(args->length() >= 1, "invariant"); 303 304 // attempt must set a real value 305 assert(args->param(1).get_type() != T_VOID, "invariant"); 306 307 switch(fd->field_type()) { 308 case T_BOOLEAN: 309 case T_CHAR: 310 case T_SHORT: 311 case T_INT: 312 write_int_field(h_oop, fd, args->param(1).get_jint()); 313 break; 314 case T_FLOAT: 315 write_float_field(h_oop, fd, args->param(1).get_jfloat()); 316 break; 317 case T_DOUBLE: 318 write_double_field(h_oop, fd, args->param(1).get_jdouble()); 319 break; 320 case T_LONG: 321 write_long_field(h_oop, fd, args->param(1).get_jlong()); 322 break; 323 case T_OBJECT: 324 write_oop_field(h_oop, fd, (oop)args->param(1).get_jobject()); 325 break; 326 case T_ADDRESS: 327 write_oop_field(h_oop, fd, JfrJavaSupport::resolve_non_null(args->param(1).get_jobject())); 328 break; 329 default: 330 ShouldNotReachHere(); 331 } 332 } 333 334 static void read_specialized_field(JavaValue* result, const Handle& h_oop, fieldDescriptor* fd) { 335 assert(result != NULL, "invariant"); 336 assert(h_oop.not_null(), "invariant"); 337 assert(fd != NULL, "invariant"); 338 assert(fd->offset() > 0, "invariant"); 339 340 switch(fd->field_type()) { 341 case T_BOOLEAN: 342 case T_CHAR: 343 case T_SHORT: 344 case T_INT: 345 result->set_jint(h_oop->int_field(fd->offset())); 346 break; 347 case T_FLOAT: 348 result->set_jfloat(h_oop->float_field(fd->offset())); 349 break; 350 case T_DOUBLE: 351 result->set_jdouble(h_oop->double_field(fd->offset())); 352 break; 353 case T_LONG: 354 result->set_jlong(h_oop->long_field(fd->offset())); 355 break; 356 case T_OBJECT: 357 result->set_jobject((jobject)h_oop->obj_field(fd->offset())); 358 break; 359 default: 360 ShouldNotReachHere(); 361 } 362 } 363 364 static bool find_field(InstanceKlass* ik, 365 Symbol* name_symbol, 366 Symbol* signature_symbol, 367 fieldDescriptor* fd, 368 bool is_static = false, 369 bool allow_super = false) { 370 if (allow_super || is_static) { 371 return ik->find_field(name_symbol, signature_symbol, is_static, fd) != NULL; 372 } 373 return ik->find_local_field(name_symbol, signature_symbol, fd); 374 } 375 376 static void lookup_field(JfrJavaArguments* args, InstanceKlass* klass, fieldDescriptor* fd, bool static_field) { 377 assert(args != NULL, "invariant"); 378 assert(klass != NULL, "invariant"); 379 assert(klass->is_initialized(), "invariant"); 380 assert(fd != NULL, "invariant"); 381 find_field(klass, args->name(), args->signature(), fd, static_field, true); 382 } 383 384 static void read_field(JfrJavaArguments* args, JavaValue* result, TRAPS) { 385 assert(args != NULL, "invariant"); 386 assert(result != NULL, "invariant"); 387 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); 388 389 InstanceKlass* const klass = static_cast<InstanceKlass*>(args->klass()); 390 klass->initialize(CHECK); 391 const bool static_field = !args->has_receiver(); 392 fieldDescriptor fd; 393 lookup_field(args, klass, &fd, static_field); 394 assert(fd.offset() > 0, "invariant"); 395 396 HandleMark hm(THREAD); 397 Handle h_oop(static_field ? Handle(THREAD, klass->java_mirror()) : Handle(THREAD, args->receiver())); 398 read_specialized_field(result, h_oop, &fd); 399 } 400 401 static void write_field(JfrJavaArguments* args, JavaValue* result, TRAPS) { 402 assert(args != NULL, "invariant"); 403 assert(result != NULL, "invariant"); 404 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); 405 406 InstanceKlass* const klass = static_cast<InstanceKlass*>(args->klass()); 407 klass->initialize(CHECK); 408 409 const bool static_field = !args->has_receiver(); 410 fieldDescriptor fd; 411 lookup_field(args, klass, &fd, static_field); 412 assert(fd.offset() > 0, "invariant"); 413 414 HandleMark hm(THREAD); 415 Handle h_oop(static_field ? Handle(THREAD, klass->java_mirror()) : Handle(THREAD, args->receiver())); 416 write_specialized_field(args, h_oop, &fd, static_field); 417 } 418 419 void JfrJavaSupport::set_field(JfrJavaArguments* args, TRAPS) { 420 assert(args != NULL, "invariant"); 421 write_field(args, args->result(), THREAD); 422 } 423 424 void JfrJavaSupport::get_field(JfrJavaArguments* args, TRAPS) { 425 assert(args != NULL, "invariant"); 426 read_field(args, args->result(), THREAD); 427 } 428 429 void JfrJavaSupport::get_field_local_ref(JfrJavaArguments* args, TRAPS) { 430 assert(args != NULL, "invariant"); 431 DEBUG_ONLY(check_java_thread_in_vm(THREAD)); 432 433 JavaValue* const result = args->result(); 434 assert(result != NULL, "invariant"); 435 assert(result->get_type() == T_OBJECT, "invariant"); 436 437 read_field(args, result, CHECK); 438 const oop obj = (const oop)result->get_jobject(); 439 440 if (obj != NULL) { 441 result->set_jobject(local_jni_handle(obj, THREAD)); 442 } 443 } 444 445 void JfrJavaSupport::get_field_global_ref(JfrJavaArguments* args, TRAPS) { 446 assert(args != NULL, "invariant"); 447 DEBUG_ONLY(check_java_thread_in_vm(THREAD)); 448 449 JavaValue* const result = args->result(); 450 assert(result != NULL, "invariant"); 451 assert(result->get_type() == T_OBJECT, "invariant"); 452 read_field(args, result, CHECK); 453 const oop obj = (const oop)result->get_jobject(); 454 if (obj != NULL) { 455 result->set_jobject(global_jni_handle(obj, THREAD)); 456 } 457 } 458 459 /* 460 * Misc 461 */ 462 Klass* JfrJavaSupport::klass(const jobject handle) { 463 const oop obj = resolve_non_null(handle); 464 assert(obj != NULL, "invariant"); 465 return obj->klass(); 466 } 467 468 // caller needs ResourceMark 469 const char* JfrJavaSupport::c_str(jstring string, Thread* t) { 470 DEBUG_ONLY(check_java_thread_in_vm(t)); 471 if (string == NULL) { 472 return NULL; 473 } 474 const char* temp = NULL; 475 const oop java_string = resolve_non_null(string); 476 if (java_lang_String::value(java_string) != NULL) { 477 const size_t length = java_lang_String::utf8_length(java_string); 478 temp = NEW_RESOURCE_ARRAY_IN_THREAD(t, const char, (length + 1)); 479 if (temp == NULL) { 480 JfrJavaSupport::throw_out_of_memory_error("Unable to allocate thread local native memory", t); 481 return NULL; 482 } 483 assert(temp != NULL, "invariant"); 484 java_lang_String::as_utf8_string(java_string, const_cast<char*>(temp), (int) length + 1); 485 } 486 return temp; 487 } 488 489 /* 490 * Exceptions and errors 491 */ 492 static void create_and_throw(Symbol* name, const char* message, TRAPS) { 493 assert(name != NULL, "invariant"); 494 DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); 495 assert(!HAS_PENDING_EXCEPTION, "invariant"); 496 THROW_MSG(name, message); 497 } 498 499 void JfrJavaSupport::throw_illegal_state_exception(const char* message, TRAPS) { 500 create_and_throw(vmSymbols::java_lang_IllegalStateException(), message, THREAD); 501 } 502 503 void JfrJavaSupport::throw_internal_error(const char* message, TRAPS) { 504 create_and_throw(vmSymbols::java_lang_InternalError(), message, THREAD); 505 } 506 507 void JfrJavaSupport::throw_illegal_argument_exception(const char* message, TRAPS) { 508 create_and_throw(vmSymbols::java_lang_IllegalArgumentException(), message, THREAD); 509 } 510 511 void JfrJavaSupport::throw_out_of_memory_error(const char* message, TRAPS) { 512 create_and_throw(vmSymbols::java_lang_OutOfMemoryError(), message, THREAD); 513 } 514 515 void JfrJavaSupport::throw_class_format_error(const char* message, TRAPS) { 516 create_and_throw(vmSymbols::java_lang_ClassFormatError(), message, THREAD); 517 } 518 519 void JfrJavaSupport::abort(jstring errorMsg, Thread* t) { 520 DEBUG_ONLY(check_java_thread_in_vm(t)); 521 522 ResourceMark rm(t); 523 const char* const error_msg = c_str(errorMsg, t); 524 if (error_msg != NULL) { 525 log_error(jfr, system)("%s",error_msg); 526 } 527 log_error(jfr, system)("%s", "An irrecoverable error in Jfr. Shutting down VM..."); 528 vm_abort(); 529 } 530 531 JfrJavaSupport::CAUSE JfrJavaSupport::_cause = JfrJavaSupport::VM_ERROR; 532 void JfrJavaSupport::set_cause(jthrowable throwable, Thread* t) { 533 DEBUG_ONLY(check_java_thread_in_vm(t)); 534 535 HandleMark hm(t); 536 Handle ex(t, JNIHandles::resolve_external_guard(throwable)); 537 538 if (ex.is_null()) { 539 return; 540 } 541 542 if (ex->is_a(SystemDictionary::OutOfMemoryError_klass())) { 543 _cause = OUT_OF_MEMORY; 544 return; 545 } 546 if (ex->is_a(SystemDictionary::StackOverflowError_klass())) { 547 _cause = STACK_OVERFLOW; 548 return; 549 } 550 if (ex->is_a(SystemDictionary::Error_klass())) { 551 _cause = VM_ERROR; 552 return; 553 } 554 if (ex->is_a(SystemDictionary::RuntimeException_klass())) { 555 _cause = RUNTIME_EXCEPTION; 556 return; 557 } 558 if (ex->is_a(SystemDictionary::Exception_klass())) { 559 _cause = UNKNOWN; 560 return; 561 } 562 } 563 564 void JfrJavaSupport::uncaught_exception(jthrowable throwable, Thread* t) { 565 DEBUG_ONLY(check_java_thread_in_vm(t)); 566 assert(throwable != NULL, "invariant"); 567 set_cause(throwable, t); 568 } 569 570 JfrJavaSupport::CAUSE JfrJavaSupport::cause() { 571 return _cause; 572 } 573 574 const char* const JDK_JFR_MODULE_NAME = "jdk.jfr"; 575 const char* const JDK_JFR_PACKAGE_NAME = "jdk/jfr"; 576 577 static bool is_jdk_jfr_module_in_readability_graph() { 578 Thread* const t = Thread::current(); 579 // take one of the packages in the module to be located and query for its definition. 580 TempNewSymbol pkg_sym = SymbolTable::new_symbol(JDK_JFR_PACKAGE_NAME, t); 581 return Modules::is_package_defined(pkg_sym, Handle(), t); 582 } 583 584 static void print_module_resolution_error(outputStream* stream) { 585 assert(stream != NULL, "invariant"); 586 stream->print_cr("%s not found.", JDK_JFR_MODULE_NAME); 587 stream->print_cr("Flight Recorder can not be enabled."); 588 stream->print_cr("To use Flight Recorder, you might need to add" \ 589 " \"--add-modules %s\" to the VM command-line options.", JDK_JFR_MODULE_NAME); 590 } 591 592 bool JfrJavaSupport::is_jdk_jfr_module_available() { 593 return is_jdk_jfr_module_in_readability_graph(); 594 } 595 596 bool JfrJavaSupport::is_jdk_jfr_module_available(outputStream* stream, TRAPS) { 597 if (!JfrJavaSupport::is_jdk_jfr_module_available()) { 598 if (stream != NULL) { 599 print_module_resolution_error(stream); 600 } 601 return false; 602 } 603 return true; 604 } 605 606 jlong JfrJavaSupport::jfr_thread_id(jobject target_thread) { 607 ThreadsListHandle tlh; 608 JavaThread* native_thread = NULL; 609 (void)tlh.cv_internal_thread_to_JavaThread(target_thread, &native_thread, NULL); 610 return native_thread != NULL ? THREAD_TRACE_ID(native_thread) : 0; 611 }