Java — JVM_ENTRY в исходном коде OpenJDK

Я читаю коды, которые выдают исключения в горячей точке OpenJDK 7, и отслеживаю, какие классы их используют. Они оказались в классах, которые реализуют JVM_ENTRY(result_type, header)например в jvm.cpp, java.cppи т. д. У меня вопрос, какова функция JVM_ENTRY и как это работает?

Ниже приведен пример в jvm.cpp

JVM_ENTRY(jobject, JVM_AllocateNewObject(JNIEnv *env, jobject receiver, jclass currClass, jclass initClass))
JVMWrapper("JVM_AllocateNewObject");
JvmtiVMObjectAllocEventCollector oam;
// Receiver is not used
oop curr_mirror = JNIHandles::resolve_non_null(currClass);
oop init_mirror = JNIHandles::resolve_non_null(initClass);

// Cannot instantiate primitive types
if (java_lang_Class::is_primitive(curr_mirror) || java_lang_Class::is_primitive(init_mirror)) {
ResourceMark rm(THREAD);
THROW_0(vmSymbols::java_lang_InvalidClassException());
}

// Arrays not allowed here, must use JVM_AllocateNewArray
if (Klass::cast(java_lang_Class::as_klassOop(curr_mirror))->oop_is_javaArray() ||
Klass::cast(java_lang_Class::as_klassOop(init_mirror))->oop_is_javaArray()) {
ResourceMark rm(THREAD);
THROW_0(vmSymbols::java_lang_InvalidClassException());
}

instanceKlassHandle curr_klass (THREAD, java_lang_Class::as_klassOop(curr_mirror));
instanceKlassHandle init_klass (THREAD, java_lang_Class::as_klassOop(init_mirror));

assert(curr_klass->is_subclass_of(init_klass()), "just checking");

// Interfaces, abstract classes, and java.lang.Class classes cannot be instantiated directly.
curr_klass->check_valid_for_instantiation(false, CHECK_NULL);

// Make sure klass is initialized, since we are about to instantiate one of them.
curr_klass->initialize(CHECK_NULL);

methodHandle m (THREAD,
init_klass->find_method(vmSymbols::object_initializer_name(),
vmSymbols::void_method_signature()));
if (m.is_null()) {
ResourceMark rm(THREAD);
THROW_MSG_0(vmSymbols::java_lang_NoSuchMethodError(),
methodOopDesc::name_and_sig_as_C_string(Klass::cast(init_klass()),
vmSymbols::object_initializer_name(),
vmSymbols::void_method_signature()));
}

if (curr_klass ==  init_klass && !m->is_public()) {
// Calling the constructor for class 'curr_klass'.
// Only allow calls to a public no-arg constructor.
// This path corresponds to creating an Externalizable object.
THROW_0(vmSymbols::java_lang_IllegalAccessException());
}

if (!force_verify_field_access(curr_klass(), init_klass(), m->access_flags(), false)) {
// subclass 'curr_klass' does not have access to no-arg constructor of 'initcb'
THROW_0(vmSymbols::java_lang_IllegalAccessException());
}

Handle obj = curr_klass->allocate_instance_handle(CHECK_NULL);
// Call constructor m. This might call a constructor higher up in the hierachy
JavaCalls::call_default_constructor(thread, m, obj, CHECK_NULL);

return JNIHandles::make_local(obj());
JVM_END

Я нашел определение JVM_ENTRY в hotspot/src/share/vm/runtime/interfaceSupport.hpp

#define JVM_ENTRY(result_type, header)                               \
extern "C" {                                                         \
result_type JNICALL header {                                       \
JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
ThreadInVMfromNative __tiv(thread);                              \
debug_only(VMNativeEntryWrapper __vew;)                          \
VM_ENTRY_BASE(result_type, header, thread)

0

Решение

JVM_ENTRY — это макрос препроцессора, который добавляет некоторый шаблонный код, общий для всех функций API HotSpot JVM. Этот API является уровнем соединения между собственным кодом библиотеки классов JDK и JVM.

Что делает макрос JVM_ENTRY:

  1. Получает указатель на текущий JavaThread от JNIEnv* аргумент.
  2. Выполняет переход состояния потока из _thread_in_native в _thread_in_vmблокировка в безопасном месте при необходимости.
  3. Очищает локальные ссылки JNI при выходе из функции.
  4. Заботится об отслеживании и проверке отладки в отладочных сборках JVM.
6

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]