/** * Runs java.lang.Thread.detach() method. */ static jint run_java_detach(jthread java_thread) { assert(hythread_is_suspend_enabled()); JNIEnv *jni_env = jthread_get_JNI_env(java_thread); Global_Env *vm_env = jni_get_vm_env(jni_env); Class *thread_class = vm_env->java_lang_Thread_Class; static Method *detach = NULL; if (detach == NULL) { const char *method_name = "detach"; const char *descriptor = "(Ljava/lang/Throwable;)V"; detach = class_lookup_method(thread_class, method_name, descriptor); if (detach == NULL) { TRACE("Failed to find thread's detach method " << descriptor << " , exception = " << exn_get()); return TM_ERROR_INTERNAL; } } // Initialize arguments. jvalue args[2]; args[0].l = java_thread; if (vm_env->IsVmShutdowning()) { args[1].l = NULL; } else { args[1].l = exn_get(); } exn_clear(); hythread_suspend_disable(); vm_execute_java_method_array((jmethodID) detach, 0, args); hythread_suspend_enable(); if (exn_raised()) { TRACE ("java.lang.Thread.detach(Throwable) method completed with an exception: " << exn_get_name()); return TM_ERROR_INTERNAL; } return TM_ERROR_NONE; }
Class_Handle type_info_get_class_no_exn(Type_Info_Handle tih) { // Store raised exception jthrowable exc_object = exn_get(); // Workaround to let JIT invoke class loader even if exception is pending exn_clear(); Class_Handle ch = type_info_get_class(tih); // To clear exn_class if set exn_clear(); // Restore saved exception if (exc_object) exn_raise_object(exc_object); return ch; } // type_info_get_class_no_exn
// Create an exception from a given type and a message. // Set cause to the current thread exception. static void compile_raise_exception(const char* name, const char* message, Method* method) { assert(hythread_is_suspend_enabled()); jthrowable old_exc = exn_get(); exn_clear(); const char* c = method->get_class()->get_name()->bytes; const char* m = method->get_name()->bytes; const char* d = method->get_descriptor()->bytes; size_t sz = 3 + // a space, a dot, and a terminator strlen(message) + method->get_class()->get_name()->len + method->get_name()->len + method->get_descriptor()->len; char* msg_raw = (char*)STD_MALLOC(sz); assert(msg_raw); sprintf(msg_raw, "%s%s.%s%s", message, c, m, d); assert(strlen(msg_raw) < sz); jthrowable new_exc = exn_create(name, msg_raw, old_exc); exn_raise_object(new_exc); STD_FREE(msg_raw); }
Class* Class::_resolve_class(Global_Env* env, unsigned cp_index) { assert(hythread_is_suspend_enabled()); ConstantPool& cp = m_const_pool; lock(); if(cp.is_entry_in_error(cp_index)) { TRACE2("resolve.testing", "Constant pool entry " << cp_index << " already contains error."); unlock(); return NULL; } #ifdef ORDER if(cp.is_entry_resolved(cp_index, this)) {//ORDER unlock(); return cp.get_class_class(cp_index); } #else if(cp.is_entry_resolved(cp_index)) {//ORDER unlock(); return cp.get_class_class(cp_index); } #endif const String* classname = cp.get_utf8_string(cp.get_class_name_index(cp_index)); unlock(); // load the class in Class* other_clss = m_class_loader->LoadVerifyAndPrepareClass(env, classname); if(other_clss == NULL) { // FIXMECL should find out if this is VirtualMachineError assert(exn_raised()); class_report_failure(this, cp_index, exn_get()); exn_clear(); return NULL; } // Check access control: // referenced class should be public, // or referenced class & declaring class are the same, // or referenced class & declaring class are in the same runtime package, // or declaring class not checked // (the last case is needed for certain magic classes, // eg, reflection implementation) if(m_can_access_all || other_clss->is_public() || other_clss == this || m_package == other_clss->m_package) { lock(); cp.resolve_entry(cp_index, other_clss); unlock(); return other_clss; } // Check access control for inner classes: // access control checks is the same as for members if(strrchr(other_clss->get_name()->bytes, '$') != NULL && can_access_inner_class(env, other_clss)) { lock(); cp.resolve_entry(cp_index, other_clss); unlock(); return other_clss; } CLASS_REPORT_FAILURE(this, cp_index, "java/lang/IllegalAccessError", "from " << get_name()->bytes << " to " << other_clss->get_name()->bytes); // IllegalAccessError return NULL; } // Class::_resolve_class