【源码】Thread相关native方法
Thread.registerNatives()
registerNatives()方法的作用是将本地方法注册JVM中,使得在JVM运行中可以调用到本地方法,如start0()。
//Thread.h
JNIEXPORT void JNICALL
Java_java_lang_Thread_registerNatives(JNIEnv *env, jclass cls)
{
(*env)->RegisterNatives(env, cls, methods, ARRAY_LENGTH(methods));
}
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 ")[[" STE, (void *)&JVM_DumpThreads},
{"setNativeName", "(" STR ")V", (void *)&JVM_SetNativeThreadName},
};
start0()
当前线程调用start0()方法,使线程进入就绪状态,等待线程调度器的调度。从上面本地方法注册中可以看到start0()对应着JVM_StartThread方法
//jvm.cpp
JVM_ENTRY(void, JVM_StartThread(JNIEnv* env, jobject jthread))
JVMWrapper("JVM_StartThread");
JavaThread *native_thread = NULL;
bool throw_illegal_thread_state = false;
{
MutexLocker mu(Threads_lock);
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));
size_t sz = size > 0 ? (size_t) size : 0;
native_thread = new JavaThread(&thread_entry, sz);//这里通过thread_entry回调了run()方法
if (native_thread->osthread() != NULL) {
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) {
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
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);
}
//vmSymbols.hpp
template(run_method_name, "run") \
class vmSymbols: AllStatic {
friend class vmIntrinsics;
friend class VMStructs;
public:
// enum for figuring positions and size of array holding Symbol*s
enum SID {
NO_SID = 0,
#define VM_SYMBOL_ENUM(name, string) VM_SYMBOL_ENUM_NAME(name),
VM_SYMBOLS_DO(VM_SYMBOL_ENUM, VM_ALIAS_IGNORE)
#undef VM_SYMBOL_ENUM
SID_LIMIT,
#define VM_ALIAS_ENUM(name, def) VM_SYMBOL_ENUM_NAME(name) = VM_SYMBOL_ENUM_NAME(def),
VM_SYMBOLS_DO(VM_SYMBOL_IGNORE, VM_ALIAS_ENUM)
#undef VM_ALIAS_ENUM
FIRST_SID = NO_SID + 1
};
enum {
log2_SID_LIMIT = 10 // checked by an assert at start-up
};
private:
// The symbol array
static Symbol* _symbols[];
// Field signatures indexed by BasicType.
static Symbol* _type_signatures[T_VOID+1];
public:
// Initialization
static void initialize(TRAPS);
// Accessing
#define VM_SYMBOL_DECLARE(name, ignore) \
static Symbol* name() { \
return _symbols[VM_SYMBOL_ENUM_NAME(name)]; \
}
VM_SYMBOLS_DO(VM_SYMBOL_DECLARE, VM_SYMBOL_DECLARE)
#undef VM_SYMBOL_DECLARE
// Sharing support
static void symbols_do(SymbolClosure* f);
static void serialize(SerializeClosure* soc);
static Symbol* type_signature(BasicType t) {
assert((uint)t < T_VOID+1, "range check");
assert(_type_signatures[t] != NULL, "domain check");
return _type_signatures[t];
}
// inverse of type_signature; returns T_OBJECT if s is not recognized
static BasicType signature_type(Symbol* s);
static Symbol* symbol_at(SID id) {
assert(id >= FIRST_SID && id < SID_LIMIT, "oob");
assert(_symbols[id] != NULL, "init");
return _symbols[id];
}
// Returns symbol's SID if one is assigned, else NO_SID.
static SID find_sid(Symbol* symbol);
static SID find_sid(const char* symbol_name);
#ifndef PRODUCT
// No need for this in the product:
static const char* name_for(SID sid);
#endif //PRODUCT
};
三、总结
通过代码可以清晰的看到Java线程是通过本地线程回调run()方法来实现的。
- Openjdk源码为openjdk-8u40-src-b25-10_feb_2015