Как получить текущий поток в Java

Java задняя часть JVM глубокое обучение
Как получить текущий поток в Java

предисловие

В 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»

Добро пожаловать, чтобы следовать:

这里写图片描述