美文网首页
Java线程类中其他的JNI方法

Java线程类中其他的JNI方法

作者: buzzerrookie | 来源:发表于2019-03-03 10:24 被阅读0次

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

    相关文章

      网友评论

          本文标题:Java线程类中其他的JNI方法

          本文链接:https://www.haomeiwen.com/subject/nolusqtx.html