Java Thread 启动线程

Java Threadjava.lang.Thread)类提供了一个启动线程的方法。该方法是这样的:

public synchronized void start()

 

该方法调用了一个native方法,通过这个native方法来启动线程,这个本地方法声明如下:

private native void start0();

该方法注册的对应实现为JVM_StartThread,在hotspot\src\share\vm\prims目录下的jvm.cpp,内部实现如下:

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

  JVMWrapper("JVM_StartThread");

  JavaThread *native_thread = NULL;

 

  // We cannot hold the Threads_lock when we throw an exception,

  // due to rank ordering issues. Example:  we might need to grab the

  // Heap_lock while we construct the exception.

  bool throw_illegal_thread_state = false;

 

  // We must release the Threads_lock before we can post a jvmti event

  // in Thread::start.

  {

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

    // we operate.

    MutexLocker mu(Threads_lock);

 

    // Since JDK 5 the java.lang.Thread threadStatus is used to prevent

    // re-starting an already started thread, so we should usually find

    // that the JavaThread is null. However for a JNI attached thread

    // there is a small window between the Thread object being created

    // (with its JavaThread set) and the update to its threadStatus, so we

    // have to check for this

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

      throw_illegal_thread_state = true;

    } else {

      // We could also check the stillborn flag to see if this thread was already stopped, but

      // for historical reasons we let the thread detect that itself when it starts running

 

      jlong size =

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

      // Allocate the C++ Thread structure and create the native thread.  The

      // stack size retrieved from java is signed, but the constructor takes

      // size_t (an unsigned type), so avoid passing negative values which would

      // result in really large stacks.

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

      native_thread = new JavaThread(&thread_entry, sz);

 

      // At this point it may be possible that no osthread was created for the

      // JavaThread due to lack of memory. Check for this situation and throw

      // an exception if necessary. Eventually we may want to change this so

      // that we only grab the lock if the thread was created successfully -

      // then we can also do this check and throw the exception in the

      // JavaThread constructor.

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

        // Note: the current thread is not being used within "prepare".

        native_thread->prepare(jthread);

      }

    }

  }

 

  if (throw_illegal_thread_state) {

    THROW(vmSymbols::java_lang_IllegalThreadStateException());

  }

 

  assert(native_thread != NULL, "Starting null thread?");

 

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

    // No one should hold a reference to the 'native_thread'.

    delete native_thread;

    if (JvmtiExport::should_post_resource_exhausted()) {

      JvmtiExport::post_resource_exhausted(

        JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS,

        "unable to create new native thread");

    }

    THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(),

              "unable to create new native thread");

  }

 

  Thread::start(native_thread);

 

JVM_END

 

完整代码需要展开来才能看:

// no define ASSERT

extern "C" {

  void JNICALL JVM_StartThread(JNIEnv* env, jobject jthread) {

    JavaThread* thread=JavaThread::thread_from_jni_environment(env);

    ThreadInVMfromNative __tiv(thread);

   

    /* do nothing */

    HandleMarkCleaner __hm(thread);

    Thread* THREAD = thread;

    /* begin of body */

 

    ;

    JavaThread *native_thread = NULL;

 

    // We cannot hold the Threads_lock when we throw an exception,

    // due to rank ordering issues. Example:  we might need to grab the

    // Heap_lock while we construct the exception.

    bool throw_illegal_thread_state = false;

 

    // We must release the Threads_lock before we can post a jvmti event

    // in Thread::start.

    {

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

      // we operate.

      MutexLocker mu(Threads_lock);

 

      // Since JDK 5 the java.lang.Thread threadStatus is used to prevent

      // re-starting an already started thread, so we should usually find

      // that the JavaThread is null. However for a JNI attached thread

      // there is a small window between the Thread object being created

      // (with its JavaThread set) and the update to its threadStatus, so we

      // have to check for this

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

        throw_illegal_thread_state = true;

      } else {

        // We could also check the stillborn flag to see if this thread was already stopped, but

        // for historical reasons we let the thread detect that itself when it starts running

 

        jlong size =

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

        // Allocate the C++ Thread structure and create the native thread.  The

        // stack size retrieved from java is signed, but the constructor takes

        // size_t (an unsigned type), so avoid passing negative values which would

        // result in really large stacks.

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

        native_thread = new JavaThread(&thread_entry, sz);

 

        // At this point it may be possible that no osthread was created for the

        // JavaThread due to lack of memory. Check for this situation and throw

        // an exception if necessary. Eventually we may want to change this so

        // that we only grab the lock if the thread was created successfully -

        // then we can also do this check and throw the exception in the

        // JavaThread constructor.

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

          // Note: the current thread is not being used within "prepare".

          native_thread->prepare(jthread);

        }

      }

    }

 

    if (throw_illegal_thread_state) {

      THROW(vmSymbols::java_lang_IllegalThreadStateException());

    }

 

    assert(native_thread != NULL, "Starting null thread?");

 

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

      // No one should hold a reference to the 'native_thread'.

      delete native_thread;

      if (JvmtiExport::should_post_resource_exhausted()) {

        JvmtiExport::post_resource_exhausted(

          JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | JVMTI_RESOURCE_EXHAUSTED_THREADS,

          "unable to create new native thread");

      }

      THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(),

                "unable to create new native thread");

    }

 

    Thread::start(native_thread);

 

  }

}

该方法创建了一个JavaThread线程,在创建JavaThread线程时传入了两个参数,第一个参数为线程执行的函数入口:entry_pointThreadFunction),第二个参数表示线程栈空间大小。

thread_entry

hotspot\src\share\vm\prims目录下的jvm.cpp

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);

}

 

 

native_thread = new JavaThread(&thread_entry, sz);

这个JavaThread构造实现代码如下:(在\hotspot\src\share\vm\runtime目录下的thread.cpp

JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) :

  Thread()

#ifndef SERIALGC

  , _satb_mark_queue(&_satb_mark_queue_set),

  _dirty_card_queue(&_dirty_card_queue_set)

#endif // !SERIALGC

{

  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);

 

  // The _osthread may be NULL here because we ran out of memory (too many threads active).

  // We need to throw and OutOfMemoryError - however we cannot do this here because the caller

  // may hold a lock and all locks must be unlocked before throwing the exception (throwing

  // the exception consists of creating the exception object & initializing it, initialization

  // will leave the VM via a JavaCall and then all locks must be unlocked).

  //

  // The thread is still suspended when we reach here. Thread must be explicit started

  // by creator! Furthermore, the thread must also explicitly be added to the Threads list

  // by calling Threads:add. The reason why this is not done here, is because the thread

  // object must be fully initialized (take a look at JVM_Start)

}

这里调用os::create_thread创建了线程,该方法声明如下:

static bool create_thread(Thread* thread,

                            ThreadType thr_type,

                            size_t stack_size = 0);

具体实现不同平台不一样,代码实现在hotspot\src\os\solaris\vmos_solaris.cpp下,其他平台在src\os\solaris\vm\os_solaris.cpphotspot\src\os\windows\vm\os_windows.cpphotspot\src\os\linux\vm\os_linux.cpphotspot\src\os\bsd\vm\os_bsd.cpp下面。

Linux:

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);

  if (osthread == NULL) {

    return false;

  }

 

  // set the correct thread state

  osthread->set_thread_type(thr_type);

 

  // Initial state is ALLOCATED but not INITIALIZED

  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);

 

  // stack size

  if (os::Linux::supports_variable_stack_size()) {

    // calculate stack size if it's not specified by caller

    if (stack_size == 0) {

      stack_size = os::Linux::default_stack_size(thr_type);

 

      switch (thr_type) {

      case os::java_thread:

        // Java threads use ThreadStackSize which default value can be

        // changed with the flag -Xss

        assert (JavaThread::stack_size_at_create() > 0, "this should be set");

        stack_size = JavaThread::stack_size_at_create();

        break;

      case os::compiler_thread:

        if (CompilerThreadStackSize > 0) {

          stack_size = (size_t)(CompilerThreadStackSize * K);

          break;

        } // else fall through:

          // use VMThreadStackSize if CompilerThreadStackSize is not defined

      case os::vm_thread:

      case os::pgc_thread:

      case os::cgc_thread:

      case os::watcher_thread:

        if (VMThreadStackSize > 0) stack_size = (size_t)(VMThreadStackSize * K);

        break;

      }

    }

 

    stack_size = MAX2(stack_size, os::Linux::min_stack_allowed);

    pthread_attr_setstacksize(&attr, stack_size);

  } else {

    // let pthread_create() pick the default value.

  }

 

  // glibc guard page

  pthread_attr_setguardsize(&attr, os::Linux::default_guard_size(thr_type));

 

  ThreadState state;

 

  {

    // Serialize thread creation if we are running with fixed stack LinuxThreads

    bool lock = os::Linux::is_LinuxThreads() && !os::Linux::is_floating_stack();

    if (lock) {

      os::Linux::createThread_lock()->lock_without_safepoint_check();

    }

 

    pthread_t tid;

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

 

    pthread_attr_destroy(&attr);

 

    if (ret != 0) {

      if (PrintMiscellaneous && (Verbose || WizardMode)) {

        perror("pthread_create()");

      }

      // Need to clean up stuff we've allocated so far

      thread->set_osthread(NULL);

      delete osthread;

      if (lock) os::Linux::createThread_lock()->unlock();

      return false;

    }

 

    // Store pthread info into the OSThread

    osthread->set_pthread_id(tid);

 

    // Wait until child thread is either initialized or aborted

    {

      Monitor* sync_with_child = osthread->startThread_lock();

      MutexLockerEx ml(sync_with_child, Mutex::_no_safepoint_check_flag);

      while ((state = osthread->get_state()) == ALLOCATED) {

        sync_with_child->wait(Mutex::_no_safepoint_check_flag);

      }

    }

 

    if (lock) {

      os::Linux::createThread_lock()->unlock();

    }

  }

 

  // Aborted due to thread limit being reached

  if (state == ZOMBIE) {

      thread->set_osthread(NULL);

      delete osthread;

      return false;

  }

 

  // The thread is returned suspended (in state INITIALIZED),

  // and is started higher up in the call chain

  assert(state == INITIALIZED, "race condition");

  return true;

}

最终在这里调用了pthread_create创建线程,注意第三个参数java_start, 这个是线程执行的回调函数,也就是传给pthread_createstart routine,在这个函数里调用的Java Thread线程的run方法,在这里设置线程为初始状态INITIALIZED,并进入阻塞等待直到后面调用os::start_thread后才能继续运行。具体代码如下:

具体实现不同平台不一样,代码实现在hotspot\src\os\solaris\vmos_solaris.cpp下,其他平台在src\os\solaris\vm\os_solaris.cpphotspot\src\os\windows\vm\os_windows.cpphotspot\src\os\linux\vm\os_linux.cpphotspot\src\os\bsd\vm\os_bsd.cpp下面。

Linux:

 

// Thread start routine for all newly created threads

static void *java_start(Thread *thread) {

  // Try to randomize the cache line index of hot stack frames.

  // This helps when threads of the same stack traces evict each other's

  // cache lines. The threads can be either from the same JVM instance, or

  // from different JVM instances. The benefit is especially true for

  // processors with hyperthreading technology.

  static int counter = 0;

  int pid = os::current_process_id();

  alloca(((pid ^ counter++) & 7) * 128);

 

  ThreadLocalStorage::set_thread(thread);

 

  OSThread* osthread = thread->osthread();

  Monitor* sync = osthread->startThread_lock();

 

  // non floating stack LinuxThreads needs extra check, see above

  if (!_thread_safety_check(thread)) {

    // notify parent thread

    MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag);

    osthread->set_state(ZOMBIE);

    sync->notify_all();

    return NULL;

  }

 

  // thread_id is kernel thread id (similar to Solaris LWP id)

  osthread->set_thread_id(os::Linux::gettid());

 

  if (UseNUMA) {

    int lgrp_id = os::numa_get_group_id();

    if (lgrp_id != -1) {

      thread->set_lgrp_id(lgrp_id);

    }

  }

  // initialize signal mask for this thread

  os::Linux::hotspot_sigmask(thread);

 

  // initialize floating point control register

  os::Linux::init_thread_fpu_state();

 

  // handshaking with parent thread

  {

    MutexLockerEx ml(sync, Mutex::_no_safepoint_check_flag);

 

    // notify parent thread

    osthread->set_state(INITIALIZED);

    sync->notify_all();

 

    // wait until os::start_thread()

    while (osthread->get_state() == INITIALIZED) {

      sync->wait(Mutex::_no_safepoint_check_flag);

    }

  }

 

  // call one more level start routine

  thread->run();

 

  return 0;

}

 

 

并调用Thread::start方法启动线程(JavaThread线程),这个方法实现在hotspot\src\share\vm\runtime目录下的thread.cpp

void Thread::start(Thread* thread) {

  trace("start", thread);

  // Start is different from resume in that its safety is guaranteed by context or

  // being called from a Java method synchronized on the Thread object.

  if (!DisableStartThread) {

    if (thread->is_Java_thread()) {

      // Initialize the thread state to RUNNABLE before starting this thread.

      // Can not set it after the thread started because we do not know the

      // exact thread state at that time. It could be in MONITOR_WAIT or

      // in SLEEPING or some other state.

      java_lang_Thread::set_thread_status(((JavaThread*)thread)->threadObj(),

                                          java_lang_Thread::RUNNABLE);

    }

    os::start_thread(thread);

  }

}

这里调用了os::start_thread来启动线程,该方法实现在hotspot\src\share\vm\runtime目录下的os.cpp

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);

}

最后调用pd_start_thread方法启动,代码实现在hotspot\src\os\solaris\vmos_solaris.cpp下,其他平台在src\os\solaris\vm\os_solaris.cpphotspot\src\os\windows\vm\os_windows.cpphotspot\src\os\linux\vm\os_linux.cpphotspot\src\os\bsd\vm\os_bsd.cpp下面。

Solaris:

void os::pd_start_thread(Thread* thread) {

  int status = thr_continue(thread->osthread()->thread_id());

  assert_status(status == 0, status, "thr_continue failed");

}

Linux:

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();

}

 

 

JavaThreadThread的继承关系:

 



 

猜你喜欢

转载自lobin.iteye.com/blog/2327876