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