We all know that a Thread corresponds directly to a Thread object, and when we first started learning about threads we also knew that threads were started using the start() method, not the run() method.

So why is that?

If you are familiar with Thread’s code, you should know that some native methods are registered when the class loads

public

class Thread implements Runnable {

  /* Make sure registerNatives is the first thing <clinit> does. */

  private static native void registerNatives(a);

  static {

      registerNatives();

  }

}



Copy the code

As soon as I saw Native I remembered JNI,registerNatives() is actually a Java method and C/C++ function corresponding. These native methods are registered at first load. There are many native methods in Thread. If you are interested, you can go to see them.

For naming JNI methods, we can test this by declaring a native method in Java, Then you compile the source file using Javac (for example, javac main.java) and then generate the header file using Javah (javah main). Open this header file and you will know what the method name is

We can see the implementation of the registerNatives method by searching Java_java_lang_Thread_registerNatives in the JVM source code

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},

    {"countStackFrames"."()I",        (void *)&JVM_CountStackFrames},

    {"interrupt0"."()V",        (void *)&JVM_Interrupt},

    {"isInterrupted"."(Z)Z",       (void *)&JVM_IsInterrupted},

    {"holdsLock"."(" OBJ ")Z", (void *)&JVM_HoldsLock},

    {"getThreads"."()" THD,   (void *)&JVM_GetAllThreads},

    {"dumpThreads"."([" THD "The [[" STE, (void *)&JVM_DumpThreads},

    {"setNativeName"."(" STR ")V", (void *)&JVM_SetNativeThreadName},

};



JNIEXPORT void JNICALL

Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls)

{

    (*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods));

}

Copy the code

You can see that in the registerNatives function, many native methods such as the start0() method are registered.

All calls to JNI functions use the env pointer, which is the first argument to each local method. The env pointer is a pointer to the function pointer table. We can in docs.oracle.com/javase/8/do… To find the JNI API

In the thread.start () method, the Thread is actually started by calling start0().

public synchronized void start(a) {

       

  if(threadStatus ! =0)

      throw new IllegalThreadStateException();





  group.add(this);



  boolean started = false;

  try {

      // The start0() native method is called to start the thread

      start0();

      started = true;

  } finally {

      try {

          if(! started) {

              group.threadStartFailed(this);

          }

      } catch (Throwable ignore) {

          /* do nothing. If start0 threw a Throwable then

            it will be passed up the call stack */


      }

  }

}





private native void start0(a);



Copy the code

The JNINativeMethod data structure is defined as follows:



typedef struct {

  char *name;

  char *signature;

  void *fnPtr;

}

Copy the code

So the local function corresponding to the start0() method is JVM_StartThread

 {"start0"."()V", (void *)&JVM_StartThread}

Copy the code

Let’s look at the JVM_StartThread method implementation next

JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))

  JVMWrapper("JVM_StartThread");

  JavaThread *native_thread = NULL;



  bool throw_illegal_thread_state = false;



 

  {

    // Ensure that the C++ Thread and OSThread structures aren't freed before

    // we operate.

    MutexLocker mu(Threads_lock);



    // Starting with JDK5, use java.lang.Thread threadStatus to prevent restarting an already started Thread

    if(java_lang_Thread::thread(JNIHandles::resolve_non_null(jthread)) ! =NULL) {

      throw_illegal_thread_state = true;

    } else {

      

      jlong size =

             java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread));

      

      NOT_LP64(if (size > SIZE_MAX) size = SIZE_MAX;)

      size_t sz = size > 0 ? (size_t) size : 0;



      // Create a Java thread

      native_thread = new JavaThread(&thread_entry, sz);



     

      if(native_thread->osthread() ! =NULL) {

        native_thread->prepare(jthread);

      }

    }

  }



  if (throw_illegal_thread_state) {

    THROW(vmSymbols::java_lang_IllegalThreadStateException());

  }



  // Some code is omitted





  // Set the thread state to Runnable, indicating that it can be run

  Thread::start(native_thread);



JVM_END

Copy the code

The code above does three main things

  1. Judge whether the current thread state legal and illegal sell IllegalThreadStateException

  2. Creating a Java thread (what we need to focus on)

  3. Set the thread state to Runnable

If the interviewer will ask you later two call start () method, you can raise IllegalThreadStateException bold and firm reply.

The OS ::create_thread method is actually called in the JavaThread constructor

bool os::create_thread(Thread* thread, ThreadType thr_type,

                       size_t req_stack_size) {



  

  OSThread* osthread = new OSThread(NULL.NULL);

  if (osthread == NULL) {

    return false;

  }



  osthread->set_thread_type(thr_type);

  osthread->set_state(ALLOCATED);



  thread->set_osthread(osthread);



  // init thread attributes

  pthread_attr_t attr;

  pthread_attr_init(&attr);

  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);



  

  size_t stack_size = os::Posix::get_initial_stack_size(thr_type, req_stack_size);

  int status = pthread_attr_setstacksize(&attr, stack_size);



  ThreadState state;



  {

    pthread_t tid;



    // Create a thread

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



    

    // omit other code...



  }

  return true;

}



Copy the code

The pthread_create function creates a thread. Its third argument is the starting address of the function that the thread runs, and its fourth argument is the argument that runs the function

Threads are defined in the IEEE standard 1003.1c, which defines a thread package called PThreads. Most UNIX systems support this standard.

Our thread_native_entry actually passes in JavaThread, so we end up calling JavaThread::run()(in thread.cpp).

void JavaThread::run() {

  

.



  thread_main_inner();

.

}



void JavaThread::thread_main_inner() {

.

  this->entry_point()(this.this);

.

}



Copy the code

The return value of entry_point in the thread_main_inner function is actually the first thread_entry argument we passed in when we created JavaThread. The thread_entry pointer points to the following function:

static void thread_entry(JavaThread* thread, TRAPS) {

  HandleMark hm(THREAD);

  Handle obj(THREAD, thread->threadObj());

  JavaValue result(T_VOID);

  JavaCalls::call_virtual(&result,

    obj,

    SystemDictionary::Thread_klass(),

    // run method name run

    vmSymbols::run_method_name(),

    // Method signature ()V

    vmSymbols::void_method_signature(),

    THREAD);

}



Copy the code

So we finally call the run method through JavaCalls.

conclusion

The new Thread simply creates a normal Java object, and a real Thread is created only after the start() method is called. Within the JVM, the run() method is called after the Thread is created to execute the corresponding business logic.

Thread resources are an important resource because Java threads are ultimately tied to operating system threads, and threads are typically used as thread pools for reuse purposes.

Focus on me not getting lost

I am me, different fireworks

Pay attention and don’t get lost