Java线程类中其他的JNI方法

2019-03-03  本文已影响0人  buzzerrookie

本文分析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);
        }
    }
}
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线程设置了新优先级。

上一篇下一篇

猜你喜欢

热点阅读