Java Thread(java.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_point(ThreadFunction),第二个参数表示线程栈空间大小。
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\vm的os_solaris.cpp下,其他平台在src\os\solaris\vm\os_solaris.cpp、hotspot\src\os\windows\vm\os_windows.cpp、hotspot\src\os\linux\vm\os_linux.cpp、hotspot\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_create的start routine,在这个函数里调用的Java Thread线程的run方法,在这里设置线程为初始状态INITIALIZED,并进入阻塞等待直到后面调用os::start_thread后才能继续运行。具体代码如下:
具体实现不同平台不一样,代码实现在hotspot\src\os\solaris\vm的os_solaris.cpp下,其他平台在src\os\solaris\vm\os_solaris.cpp、hotspot\src\os\windows\vm\os_windows.cpp、hotspot\src\os\linux\vm\os_linux.cpp、hotspot\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\vm的os_solaris.cpp下,其他平台在src\os\solaris\vm\os_solaris.cpp、hotspot\src\os\windows\vm\os_windows.cpp、hotspot\src\os\linux\vm\os_linux.cpp、hotspot\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(); } |
JavaThread与Thread的继承关系: