Thread start () - how does it enable threads to start? Where is the future of Java

registerNatives, the local method is defined in thread C, the following is the core source code of the definition:

static JNINativeMethod methods[] = {
    {"start0",           "()V",        (void *)&JVM_StartThread},
    {"stop0",            "(" OBJ ")V", (void *)&JVM_StopThread},
    {"isAlive",          "()Z",        (void *)&JVM_IsThreadAlive},
    {"suspend0",         "()V",        (void *)&JVM_SuspendThread},
    {"resume0",          "()V",        (void *)&JVM_ResumeThread},
    {"setPriority0",     "(I)V",       (void *)&JVM_SetThreadPriority},
    {"yield",            "()V",        (void *)&JVM_Yield},
    {"sleep",            "(J)V",       (void *)&JVM_Sleep},
    {"currentThread",    "()" THD,     (void *)&JVM_CurrentThread},
    {"interrupt0",       "()V",        (void *)&JVM_Interrupt},
    {"holdsLock",        "(" OBJ ")Z", (void *)&JVM_HoldsLock},
    {"getThreads",        "()[" THD,   (void *)&JVM_GetAllThreads},
    {"dumpThreads",      "([" THD ")[[" STE, (void *)&JVM_DumpThreads},
    {"setNativeName",    "(" STR ")V", (void *)&JVM_SetNativeThreadName},
};

  • As you can see from the definition, the start0 method executes the & JVM_ The startthread method starts the thread at the JVM level.

3. JVM create thread

3.1 JVM_StartThread

JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
  JVMWrapper("JVM_StartThread");
  JavaThread *native_thread = NULL;

  // Create thread
  native_thread = new JavaThread(&thread_entry, sz);
  // Start thread
  Thread::start(native_thread);

JVM_END

  • There are a lot of codes in this part, but the core content is to create and start threads, and thread_ Entry is also a method, as follows:

thread_entry, thread entry

static void thread_entry(JavaThread* thread, TRAPS) {
  HandleMark hm(THREAD);
  Handle obj(THREAD, thread->threadObj());
  JavaValue result(T_VOID);
  JavaCalls::call_virtual(&result,
                          obj,
                          KlassHandle(THREAD, SystemDictionary::Thread_klass()),
                          vmSymbols::run_method_name(),
                          vmSymbols::void_method_signature(),
                          THREAD);
}

The key point is that when creating a method for introducing this thread entry, thread_ The Java callback function javacalls:: call is included in the entry_ virtual. This callback function will be called by the JVM.

vmSymbols::run_method_name() is the callback method. The source code is as follows:

#define VM_SYMBOLS_DO(template, do_alias)
template(run_method_name, "run") 

  • This run is the run method that will be called in our Java program. Next, we continue to follow the code execution link to find out when the callback method was called.

3.2 JavaThread

native_thread = new JavaThread(&thread_entry, sz);

Next, let's continue to look at the source code execution content of java thread.

JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) :
  Thread()
#if INCLUDE_ALL_GCS
  , _satb_mark_queue(&_satb_mark_queue_set),
  _dirty_card_queue(&_dirty_card_queue_set)
#endif // INCLUDE_ALL_GCS
{
  if (TraceThreadEvents) {
    tty->print_cr("creating thread %p", this);
  }
  initialize();
  _jni_attach_state = _not_attaching_via_jni;
  set_entry_point(entry_point);
  // Create the native thread itself.
  // %note runtime_23
  os::ThreadType thr_type = os::java_thread;
  thr_type = entry_point == &compiler_thread_entry ? os::compiler_thread :os::java_thread;
  os::create_thread(this, thr_type, stack_sz);
}

  • ThreadFunction entry_point is the thread above us_ Entry method.

  • size_t stack_sz, indicating the number of existing threads in the process.

  • These two parameters are passed to os::create_thread method, which is used to create a thread.

3.3 os::create_thread

As we all know, what is a JVM!, Therefore, its OS service implementation, such as Linux and Windows, will implement the thread creation logic. This is a bit like adapter mode

os_linux -> os::create_thread

bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
  assert(thread->osthread() == NULL, "caller responsible");

  // Allocate the OSThread object
  OSThread* osthread = new OSThread(NULL, NULL);
  // Initial state is ALLOCATED but not INITIALIZED
  osthread->set_state(ALLOCATED);

  pthread_t tid;
  int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread);

  return true;
}

  • osthread->set_ State (allocated) initializes the allocated state, but it is not initialized at this time.

  • pthread_create is a function that creates threads for Unix like operating systems (Unix, Linux, Mac OS X, etc.).

  • java_start, which focuses on classes, is the method to actually create threads.

3.4 java_start

static void *java_start(Thread *thread) {

  // Thread ID
  int pid = os::current_process_id();

  // Set thread
  ThreadLocalStorage::set_thread(thread);

  // Set thread status: INITIALIZED initialization completed
  osthread->set_state(INITIALIZED);

  // Wake up all threads
  sync->notify_all();

 // Loop. If the initialization state is, wait for wait consistently
 while (osthread->get_state() == INITIALIZED) {
    sync->wait(Mutex::_no_safepoint_check_flag);
 }

  // After waiting for wake-up, execute the run method
  thread->run();

  return 0;
}

  • The JVM sets the thread state, and the INITIALIZED initialization is completed.

  • sync->notify_ All(), wake up all threads.

  • osthread->get_ State() = = initialized, while loop waiting

  • Thread - > run() is to wait for the thread to wake up, that is, to execute after the state changes. This is also reflected in our thread execution UML diagram

4. JVM startup thread

JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
  JVMWrapper("JVM_StartThread");
  JavaThread *native_thread = NULL;

  // Create thread
  native_thread = new JavaThread(&thread_entry, sz);
  // Start thread
  Thread::start(native_thread);

JVM_END

  • JVM_ There are two steps in startthread: create (new JavaThread) and start (Thread::start). After the creation process, let's talk about start.

4.1 Thread::start

void Thread::start(Thread* thread) {
  trace("start", thread);

  if (!DisableStartThread) {
    if (thread->is_Java_thread()) {
      java_lang_Thread::set_thread_status(((JavaThread*)thread)->threadObj(),
                                          java_lang_Thread::RUNNABLE);
    }
    // Different OS will have different startup code logic
    os::start_thread(thread);
  }
}

  • If the thread DisableStartThread is not disabled and is a java thread - > is_ Java_ Thread(), then set the thread status to RUNNABLE.

  • os::start_thread(thread), calling the thread startup method. Different OS will have different startup code logic

4.2 os::start_thread(thread)

void os::start_thread(Thread* thread) {
  // guard suspend/resume
  MutexLockerEx ml(thread->SR_lock(), Mutex::_no_safepoint_check_flag);
  OSThread* osthread = thread->osthread();
  osthread->set_state(RUNNABLE);
  pd_start_thread(thread);
}

  • osthread->set_ State (RUNNABLE) to set the thread state

  • pd_start_thread(thread) starts the thread. Each OS implementation class implements the startup method of its own system. For example, the code of windows system and Linux system is completely different.

4.3 pd_start_thread(thread)

void os::pd_start_thread(Thread* thread) {
  OSThread * osthread = thread->osthread();
  assert(osthread->get_state() != INITIALIZED, "just checking");
  Monitor* sync_with_child = osthread->startThread_lock();
  MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag);
  sync_with_child->notify();
}

  • This part of the code, notify(), is the most critical. It can wake up the thread.

  • After the thread wakes up, thread - > run() in 3.4; You can continue.

5. JVM thread callback

5.1 thread->run()[JavaThread::run()]

// The first routine called by a new Java thread
void JavaThread::run() {
  // ...  Initialize thread operation

  thread_main_inner();
}

  • os_ linux. Java in CPP class_ Thread - > run () in start is called in the end CPP's JavaThread::run() method.

  • This part needs to continue to look down, thread_main_inner(); method.

5.2 thread_main_inner

void JavaThread::thread_main_inner() {

  if (!this->has_pending_exception() &&
      !java_lang_Thread::is_stillborn(this->threadObj())) {
    {
      ResourceMark rm(this);
      this->set_native_thread_name(this->get_thread_name());
    }
    HandleMark hm(this);
    this->entry_point()(this, this);
  }

  DTRACE_THREAD_PROBE(stop, this);

  this->exit(false);
  delete this;
}

  • Here is the thread name you are familiar with, this - > set_ native_ thread_ name(this->get_thread_name()).

  • this->entry_ Point(), which actually calls thread in 3.1_ Entry method.

  • thread_ The entry method will eventually be called to javacalls:: call_ Vmsymbols:: run in virtual_ method_ name(). That is, the run() method. At this point, the thread is started and completed. Finally come back!

5, Summary

  • The thread startup process involves the participation of the JVM, so it is really difficult to understand it so thoroughly from a local method without careful understanding.

  • The whole source code analysis can be learned in combination with code calling UML sequence diagram. The basic core processes include: Java thread creation and startup, calling local method start0(), JVM in JVM_ Create and start the startthread, set the thread status and wait to be awakened, start the thread according to different OS and wake up, and finally call back the run() method to start the Java thread.

How to quickly update your technology accumulation?

  • In the existing projects, deep excavation technology, such as using netty, can make the relevant underlying code and key points appear.
  • If you don't know the current direction, it depends on what your leaders or skilled people in the company are learning.
  • After knowing the direction of effort, I don't know how to learn, so I look for relevant materials everywhere and practice.
  • If you don't know whether you have achieved anything after study, you can test it through the interview.

Personally, I think the interview is also like a new journey. Failure and victory are common things. Therefore, I advise you not to lose heart and morale because of the failure of the interview. Don't be complacent because you passed the interview. What's waiting for you will be a better future. Keep going!

The answers to the above interview topics have been compiled into interview documents. There are detailed answers in the documents, as well as some other interview questions of large factories. Friends in need Click here to get it for free

Xi.

  • If you don't know whether you have achieved anything after study, you can test it through the interview.

Personally, I think the interview is also like a new journey. Failure and victory are common things. Therefore, I advise you not to lose heart and morale because of the failure of the interview. Don't be complacent because you passed the interview. What's waiting for you will be a better future. Keep going!

The answers to the above interview topics have been compiled into interview documents. There are detailed answers in the documents, as well as some other interview questions of large factories. Friends in need Click here to get it for free

[external chain picture transferring... (img-kR2e7Zm8-1629244690310)]

[external chain picture transferring... (img-S6U5ojAl-1629244690312)]

Keywords: Java Interview Programmer

Added by fncuis on Tue, 21 Dec 2021 15:03:04 +0200