NDK env->GetStaticMethodID源码解析

在NDK中,我们通过env->GetStaticMethodID来查找一个静态方法,那返回值jmethodID到底是什么了? 接下来,来看一下GetStaticMethodID内部逻辑。

env->GetStaticMethodID实际会调用jni_internal.cc#GetStaticMethodID
来看 art/runtime/jni_internal.cc
在这里插入图片描述
可以看到最终调用了FindMethodID,主要步骤,已通过代码注释标记。

static jmethodID FindMethodID(ScopedObjectAccess& soa, jclass jni_class,
                              const char* name, const char* sig, bool is_static)
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  mirror::Class* c = EnsureInitialized(soa.Self(), soa.Decode<mirror::Class*>(jni_class)); //确认是否已经初始化完毕
  if (c == nullptr) {
    return nullptr;
  }
  mirror::ArtMethod* method = nullptr;
  if (is_static) { //是否是静态函数
    method = c->FindDirectMethod(name, sig);
  } else if (c->IsInterface()) { //是否是接口函数
    method = c->FindInterfaceMethod(name, sig); //--> 实际调用的也是FindVirtualMethod
  } else { //是否是虚函数
    method = c->FindVirtualMethod(name, sig);
    if (method == nullptr) {
      // No virtual method matching the signature.  Search declared
      // private methods and constructors.
      method = c->FindDeclaredDirectMethod(name, sig);
    }
  }
  if (method == nullptr || method->IsStatic() != is_static) {
  	// >>>>>>>> 如果method为null或不为static,抛出NoSuchMethodError,这个开发时候经常会遇到
    ThrowNoSuchMethodError(soa, c, name, sig, is_static ? "static" : "non-static");
    return nullptr;
  }
  return soa.EncodeMethod(method); //将ArtMethod进行编码,返回一个jmethodID
}

可以看到,会判断是否是静态函数,如果是静态函数,就调用FindDirectMethod,否则无论是接口函数还是虚函数,都是调用的FindVirtualMethod。这两个方法具体内部逻辑我们先略过,从返回值可以知道,这两个方法都会找到ArtMethod。

再来看art/runtime/scoped_thread_state_change.h#EncodeMethod()

jmethodID EncodeMethod(mirror::ArtMethod* method) const
    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
  Locks::mutator_lock_->AssertSharedHeld(Self());
  DCHECK(IsRunnable());  // Don't work with raw objects in non-runnable states.
  CHECK(!kMovingMethods);
  return reinterpret_cast<jmethodID>(method); //将ArtMethod强转为jmethodId,即ArtMethod就是jmethodId
}

这里将找到的ArtMethod强转为jmethodID,即ArtMethod就是jmethodID,并最终返回。

小结

我们可以得出结论: ArtMethod就是jmethodID

ArtMethod位于art/runtime/mirror/art_method.cc,是一个结构体,ArtMethod中保存着方法的 类、访问权限和执行地址等信息。

其他

源码为Android 5.1.0_r3

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章