предисловие
В Java мы часто сталкиваемся с ситуациями, когда хотим получить текущий поток, в это время мы обычно передаемThread.currentThread()
Чтобы получить его, давайте посмотрим, что делает выполнение этого оператора в JVM.
Простой пример
Ниже приведен простой пример: получите текущий поток и напечатайте имя потока, вывод «основной», который является основным потоком.
public class CurrentThreadTest {
public static void main(String[] args) {
Thread t = Thread.currentThread();
System.out.println(t.getName());
}
}
метод currentThread
В классе ThreadcurrentThread
является статическим и собственным методом.
public static native Thread currentThread();
Thread.c
Собственные методы, объявленные на уровне Java, соответственно реализованы в Thread.c,currentThread
это метод, зарегистрированный в JVM, который совпадает с методом в JVMJVM_CurrentThread
Функция связана, поэтому логика реализации находится вJVM_CurrentThread
в функции. Логика такова:
-
JVMWrapper("JVM_CurrentThread")
для отладки. - пройти через
thread->threadObj()
Получить oop, поток здесь вJNI_ENTRY
полученный в макросе, для получения подробной информации обратитесь к следующемуJNI_ENTRY
а такжеJNI_END
макрос. - перечислить
JNIHandles::make_local
функция
#define THD "Ljava/lang/Thread;"
static JNINativeMethod methods[] = {
...
{"currentThread", "()" THD, (void *)&JVM_CurrentThread},
...
};
JVM_ENTRY(jobject, JVM_CurrentThread(JNIEnv* env, jclass threadClass))
JVMWrapper("JVM_CurrentThread");
oop jthread = thread->threadObj();
assert (thread != NULL, "no current thread!");
return JNIHandles::make_local(env, jthread);
JVM_END
make_local
В основном смотрите на функциюthread_from_jni_environment
функция, она используется для получения текущего потока, ее логикаJavaThread *thread_from_jni_env = (JavaThread*)((intptr_t)env - in_bytes(jni_environment_offset()));
, то есть вычисление вычитания выполняется напрямую через смещение адреса.JavaThread*
, это связано с тем, что объект JavaThread содержит свойства объекта JNIEnv, поэтому его можно передать черезJNIEnv*
Вычтите смещение для расчетаJavaThread*
. Наконец, необходимо проверить, был ли завершен поток, и объект потока не будет возвращен до тех пор, пока он не будет завершен.
получитьJavaThread*
После объекта выделите дескриптор и назначьте oop для дескриптора и преобразуйте его в объект задания уровня Java.
jobject JNIHandles::make_local(JNIEnv* env, oop obj) {
if (obj == NULL) {
return NULL;
} else {
JavaThread* thread = JavaThread::thread_from_jni_environment(env);
assert(Universe::heap()->is_in_reserved(obj), "sanity check");
return thread->active_handles()->allocate_handle(obj);
}
}
static JavaThread* thread_from_jni_environment(JNIEnv* env) {
JavaThread *thread_from_jni_env = (JavaThread*)((intptr_t)env - in_bytes(jni_environment_offset()));
if (thread_from_jni_env->is_terminated()) {
thread_from_jni_env->block_if_vm_exited();
return NULL;
} else {
return thread_from_jni_env;
}
}
JNI_ENTRY
а такжеJNI_END
макрос
Эти два макроса извлекли общие части. вJNI_END
Проще, всего две закрывающие скобки.
#define JNI_ENTRY(result_type, header) JNI_ENTRY_NO_PRESERVE(result_type, header) WeakPreserveExceptionMark __wem(thread);
#define JNI_END } }
JNI_ENTRY
Основная логика:
- Получить объект указателя JavaThread текущего потока выполнения.
- Создайте объект ThreadInVMfromNative.
- TRACE_CALL здесь ничего не делает.
- Создайте объект HandleMarkCleaner.
- Назначьте поток THREAD в исключениях.
- Проверьте выравнивание стека.
- Создайте объект WeakPreserveExceptionMark.
#define JNI_ENTRY_NO_PRESERVE(result_type, header) \
extern "C" { \
result_type JNICALL header { \
JavaThread* thread=JavaThread::thread_from_jni_environment(env); \
assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \
ThreadInVMfromNative __tiv(thread); \
debug_only(VMNativeEntryWrapper __vew;) \
VM_ENTRY_BASE(result_type, header, thread)
#define VM_ENTRY_BASE(result_type, header, thread) \
TRACE_CALL(result_type, header) \
HandleMarkCleaner __hm(thread); \
Thread* THREAD = thread; \
os::verify_stack_alignment();
------------- Рекомендуем прочитать ------------
Резюме моей статьи за 2017 год — машинное обучение
Краткое изложение моих статей за 2017 год — Java и промежуточное ПО
Резюме моих статей 2017 года — глубокое обучение
Краткое изложение моих статей за 2017 год — исходный код JDK
Резюме моей статьи за 2017 год — обработка естественного языка
Резюме моих статей 2017 года — Java Concurrency
Поговори со мной, задай мне вопросы:
Меню официальной учетной записи было разделено на «Сводка для чтения», «Распределенное», «Машинное обучение», «Глубокое обучение», «НЛП», «Глубина Java», «Ядро параллелизма Java», «Исходный код JDK», "Tomcat Core" "Подождите, может быть, есть тот, который соответствует вашему аппетиту.
Зачем писать «Анализ проектирования ядра Tomcat»
Добро пожаловать, чтобы следовать: