/* * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions.
*/
// When an upcall is invoked from a thread that is not attached to the VM, we need to attach it, // and then to detach it at some point later. Detaching a thread as soon as the upcall completes // is suboptimal, as the same thread could later upcall to Java again, at which point the VM would // create multiple Java views of the same native thread. For this reason, we use thread local storage // to keep track of the fact that we have attached a native thread to the VM. When the thread local // storage is destroyed (which happens when the native threads is terminated), we check if the // storage has an attached thread and, if so, we detach it from the VM. struct UpcallContext {
Thread* attachedThread;
UpcallContext() {} // Explicit constructor to address XL C compiler bug.
~UpcallContext() { if (attachedThread != NULL) {
JavaVM_ *vm = (JavaVM *)(&main_vm);
vm->functions->DetachCurrentThread(vm);
}
}
};
assert(thread->can_call_java(), "must be able to call Java");
// Allocate handle block for Java code. This must be done before we change thread_state to _thread_in_Java, // since it can potentially block.
context->new_handles = JNIHandleBlock::allocate_block(thread);
// clear any pending exception in thread (native calls start with no exception pending)
thread->clear_pending_exception();
// The call to transition_from_native below contains a safepoint check // which needs the code cache to be writable.
MACOS_AARCH64_ONLY(ThreadWXEnable wx(WXWrite, thread));
// After this, we are officially in Java Code. This needs to be done before we change any of the thread local // info, since we cannot find oops before the new information is set up completely.
ThreadStateTransition::transition_from_native(thread, _thread_in_Java, true/* check_asyncs */);
context->old_handles = thread->active_handles();
// For the profiler, the last_Java_frame information in thread must always be in // legal state. We have no last Java frame if last_Java_sp == NULL so // the valid transition is to clear _last_Java_sp and then reset the rest of // the (platform specific) state.
debug_only(thread->inc_java_call_counter());
thread->set_active_handles(context->new_handles); // install new handle block and reset Java frame linkage
return thread;
}
// modelled after JavaCallWrapper::~JavaCallWrapper void UpcallLinker::on_exit(UpcallStub::FrameData* context) {
JavaThread* thread = context->thread;
assert(thread == JavaThread::current(), "must still be the same thread");
// Old thread-local info. has been restored. We are now back in native code.
ThreadStateTransition::transition_from_java(thread, _thread_in_native);
thread->frame_anchor()->copy(&context->jfa);
// Release handles after we are marked as being in native code again, since this // operation might block
JNIHandleBlock::release_block(context->new_handles, thread);
assert(!thread->has_pending_exception(), "Upcall can not throw an exception");
}
void UpcallLinker::handle_uncaught_exception(oop exception) {
ResourceMark rm; // Based on CATCH macro
tty->print_cr("Uncaught exception:");
exception->print();
ShouldNotReachHere();
}
assert(entry->method_holder()->is_initialized(), "no clinit barrier");
CompilationPolicy::compile_if_required(mh_entry, CHECK_0);
assert(entry->is_static(), "static only"); // Fill in the signature array, for the calling-convention call. constint total_out_args = entry->size_of_parameters();
assert(total_out_args > 0, "receiver arg");
/** * This one function is exported, used by NativeLookup.
*/
JNI_ENTRY(void, JVM_RegisterUpcallLinkerMethods(JNIEnv *env, jclass UL_class))
ThreadToNativeFromVM ttnfv(thread); int status = env->RegisterNatives(UL_class, UL_methods, sizeof(UL_methods)/sizeof(JNINativeMethod));
guarantee(status == JNI_OK && !env->ExceptionOccurred(), "register jdk.internal.foreign.abi.UpcallLinker natives");
JNI_END
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.