首页 > 其他分享 >android jni静态注册和动态注册

android jni静态注册和动态注册

时间:2023-01-11 11:56:31浏览次数:40  
标签:jni 调用 java 函数 注册 android method native

静态注册

对于静态注册的jni函数而言,jni函数签名名称要与java层对应的函数名称一一对应。当一个java类被加载时会调用LoadMethod将其所有的方法也都加载到虚拟机中,并调用LinkMethod设置函数的入口。

static void LinkCode(ClassLinker* class_linker,
                     ArtMethod* method,
                     const OatFile::OatClass* oat_class,
                     uint32_t class_def_method_index) REQUIRES_SHARED(Locks::mutator_lock_) {
//省略
if (method->IsNative()) {
    // Unregistering restores the dlsym lookup stub.
    //设置native函数入口为一个统一的跳板函数
    method->UnregisterNative();

    if (enter_interpreter || quick_code == nullptr) {
      // We have a native method here without code. Then it should have either the generic JNI
      // trampoline as entrypoint (non-static), or the resolution trampoline (static).
      // TODO: this doesn't handle all the cases where trampolines may be installed.
      const void* entry_point = method->GetEntryPointFromQuickCompiledCode();
      DCHECK(class_linker->IsQuickGenericJniStub(entry_point) ||
             class_linker->IsQuickResolutionStub(entry_point));
    }
  }
}

UnregisterNative函数调用GetJniDlsymLookupStup函数返回的是跳板函数art_jni_dlsym_lookup_stub的地址,然后调用SetEntryPointFromJni设置ArtMethod的data_为art_jni_dlsym_lookup_stub。

art_jni_dlsym_lookup_stub函数再调用dlsym通过签名规则匹配到对应的native函数,设置ArtMethod的native函数入口data_并进行调用。

动态注册

Jni_Onload中调用RegisterNative注册jni函数,其内部会调用ArtMethod::RegisterNative并将ArtMethod的native函数入口data_设置为对应的动态注册的函数。因此动态注册对与函数名称没有要求,而且因为调用的时候不需要进行函数签名规则的匹配,省去了函数查找所需要的时间所以效率更高。

const void* ArtMethod::RegisterNative(const void* native_method) {
  CHECK(IsNative()) << PrettyMethod();
  CHECK(native_method != nullptr) << PrettyMethod();
  void* new_native_method = nullptr;
  Runtime::Current()->GetRuntimeCallbacks()->RegisterNativeMethod(this,
                                                                  native_method,
                                                                  /*out*/&new_native_method);
  //设置ArtMethod的data_为new_native_method
  SetEntryPointFromJni(new_native_method);
  return new_native_method;
}

动态注册通过

jni多线程与类查询

通过java层调用的jni函数,其与此java函数属于同一个java线程。每一个java线程都有一个JNIEnv线程环境块,而每一个JNIEnv都对应者一个classloader。对于java函数调用的jni函数而言,其对应的classloader就是加载此so时调用System.load调用者的classloader。再通过JNIEnv提供的接口FindClass去查询相关类时使用的就是此JNIEnv对应的classloader。

而对于native多线程而言,其他线程默认情况下并不与android虚拟机相关联,自然也没有与之对应的java线程。可以通过手动调用JavaVM的AttachCurrentThread方法将当前native线程与android虚拟机相关联并获取对应的java线程的JNIEnv,但是此JNIEnv默认对应的classloader为系统类加载器(getSystemClassLoader),所以如果通过此JNIEnv去查询app中自定义的类会出现如下错误:搜索不到。

java.lang.ClassNotFoundException: Didn't find class "class_name" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/system/lib64, /vendor/lib64, /system/lib64, /vendor/lib64]]
       at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:125)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:312)

标签:jni,调用,java,函数,注册,android,method,native
From: https://www.cnblogs.com/revercc/p/17043309.html

相关文章

  • android11 keymaster4 和 keymaster3 接口差异点
    最近在尝试升级optee的keymaster3实现到keymaster4。记录下升级过程中的方法和一些坑,便于回溯。keymaster源码:https://github.com/linaro-swg/kmgk基于这份源码,basedan......
  • Android hook so function
    //枚举导入表varimprots=Module.enumerateImports("1.so");for(leti=0;i<improts.length;i++){console.log(JSON.stringify(improts[i]));cons......
  • android包加固重签名
    apk打包后需要重新手动签名使用androidapksigner签名https://developer.android.google.cn/studio/command-line/apksigner  使用的时候需要注意密码不是直接的密......
  • 关于Unity的Android工程,写文件的问题
    UnityAndroid工程中的写文件在安卓工程下,写入文件可以直接用:File.WriteAllText(UnityEngine.Application.persistentDataPath+"/XXX.txt","文件内容");路径前面没有加“......
  • Android BaseAdapter应用基础
    Android基础类之BaseAdapterBaseAdapter就Android应用程序中经常用到的基础数据适配器,它的主要用途是将一组数据传到像ListView、Spinner、Gallery及GridView等UI显示......
  • android studio真机调试华为手机
    背景近来开发一个视频通话App,需要在华为手机上调试,按网上一顿操作,开启了USB调试之后,发现手机连上电脑后,androidstudio没反应,在此记录下解决方法。调试的手机型号是华为n......
  • Android从assets和res中读取文件
    1.相关文件夹介绍     在Android项目文件夹里面,主要的资源文件是放在res文件夹里面的。assets文件夹是存放不进行编译加工的原生文件,即该文件夹里面的文件不会像......
  • Android之Adobe AIR本地扩展
    ​ ​​学前准备...2​​​​所需知识...2​​​​额外工具...2​​​​用户等级...2​​​​例子文件...2​​​​设置AIRSDK以及本地开发工具...2​​​​含ASC2.......
  • android 原生打包到混合开发框架uniapp 和cordova (2)解决Execution failed for task ‘
    android原生打包到混合开发框架uniapp和cordova(1) 在使用gradle自动打包的时候出现了Executionfailedfortask':app:lintVitalRelease'.>Lintfoundfatalerror......
  • android 原生打包到混合开发框架uniapp 和cordova (1) ----Android Studio中的Gradle面
    AndroidStudio中的Gradle面板没有Task任务列表 Tasklistnotbuiltduring sync 找不到gradle命令解决:1.找到gradle工具栏2.点击图中扳手->选中gradlesettin......