本文分析Thread类的currentThread方法和setPriority方法。
获取当前线程
currentThread方法是一个静态的native方法,由RegisterNatives函数可知,在JRE调用currentThread方法后会在JVM调用JVM_CurrentThread函数。JVM_CurrentThread方法代码如下:
extern "C" {
jobject JNICALL JVM_CurrentThread(JNIEnv* env, jclass threadClass) {
JavaThread* thread=JavaThread::thread_from_jni_environment(env);
ThreadInVMfromNative __tiv(thread); HandleMarkCleaner __hm(thread);
Thread* __the_thread__ = thread;
os::verify_stack_alignment();
oop jthread = thread->threadObj();
assert (thread != NULL, "no current thread!");
return JNIHandles::make_local(env, jthread);
}
}
它通过thread_from_jni_environment静态函数利用JNI接口指针取得JavaThread对象,再返回由该对象保存的Java句柄转换成的局部变量。
thread_from_jni_environment函数
thread_from_jni_environment函数定义在JavaThread类中,来看一下它是如何根据JNI接口指针得到当前JavaThread指针的:
static JavaThread* thread_from_jni_environment(JNIEnv* env) {
JavaThread *thread_from_jni_env = (JavaThread*)((intptr_t)env - in_bytes(jni_environment_offset()));
// Only return NULL if thread is off the thread list; starting to
// exit should not return NULL.
if (thread_from_jni_env->is_terminated()) {
thread_from_jni_env->block_if_vm_exited();
return NULL;
} else {
return thread_from_jni_env;
}
}
class JavaThread: public Thread {
private:
JavaThread* _next; // The next thread in the Threads list
oop _threadObj; // The Java level thread object
JavaFrameAnchor _anchor; // Encapsulation of current java frame and it state
ThreadFunction _entry_point;
JNIEnv _jni_environment;
// 省略部分代码
}
in_bytes(jni_environment_offset())返回_jni_environment成员变量在类中以字节为单位的偏移量,注意看JavaThread成员变量的声明顺序,_jni_environment变量的地址减去该偏移量刚好是JavaThread对象的地址。JNI接口指针是如何为每个线程分配一个的呢,《The Java Native Interface: Programmer's Guide and Specification》
A JNIEnv interface pointer is a pointer to thread-local data, which in turn contains a pointer to a function table. Because the JNIEnv interface pointer is thread-local, native code must not use the JNIEnv interface pointer belonging to one thread in another thread.
设置线程优先级
Thread类实例可以通过setPriority成员方法改变线程优先级:
public final void setPriority(int newPriority) {
ThreadGroup g;
checkAccess();
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
throw new IllegalArgumentException();
}
if((g = getThreadGroup()) != null) {
if (newPriority > g.getMaxPriority()) {
newPriority = g.getMaxPriority();
}
setPriority0(priority = newPriority);
}
}
private native void setPriority0(int newPriority);
由RegisterNatives函数可知,在JRE调用setPriority0方法后会在JVM调用JVM_SetThreadPriority函数。JVM_SetThreadPriority函数代码如下:
extern "C" {
jobject JNICALL JVM_SetThreadPriority(JNIEnv* env, jobject jthread, jint prio) {
JavaThread* thread=JavaThread::thread_from_jni_environment(env);
ThreadInVMfromNative __tiv(thread); HandleMarkCleaner __hm(thread);
Thread* __the_thread__ = thread;
os::verify_stack_alignment();
// Ensure that the C++ Thread and OSThread structures aren't freed before we operate
MutexLocker ml(Threads_lock);
oop java_thread = JNIHandles::resolve_non_null(jthread);
java_lang_Thread::set_priority(java_thread, (ThreadPriority)prio);
JavaThread* thr = java_lang_Thread::thread(java_thread);
if (thr != NULL) { // Thread not yet started; priority pushed down when it is
Thread::set_priority(thr, (ThreadPriority)prio);
}
}
}
- java_lang_Thread::set_priority函数为jthread对应的句柄保存了新优先级;
- Thread类的set_priority函数为JavaThread设置新优先级。
void Thread::set_priority(Thread* thread, ThreadPriority priority) {
trace("set priority", thread);
debug_only(check_for_dangling_thread_pointer(thread);)
// Can return an error!
(void)os::set_priority(thread, priority);
}
OSReturn os::set_priority(Thread* thread, ThreadPriority p) {
if (p >= MinPriority && p <= MaxPriority) {
int priority = java_to_os_priority[p];
return set_native_priority(thread, priority);
} else {
assert(false, "Should not happen");
return OS_ERR;
}
}
OSReturn os::set_native_priority(Thread* thread, int newpri) {
if ( !UseThreadPriorities || ThreadPriorityPolicy == 0 ) return OS_OK;
int ret = setpriority(PRIO_PROCESS, thread->osthread()->thread_id(), newpri);
return (ret == 0) ? OS_OK : OS_ERR;
}
可以看到,Thread类的set_priority函数最后通过setpriority系统调用为Linux线程设置了新优先级。
网友评论