• JNI接口native函数调用过程


    • dvmCallMethodV函数来执行方法,
    void dvmCallMethodV(Thread* self, const Method* method, Object* obj,
        bool fromJni, JValue* pResult, va_list args)
    {
        ...
        //判断函数是否为Native函数
        if (dvmIsNativeMethod(method)) {
              TRACE_METHOD_ENTER(self, method);
            
             //调用nativeFunc
            (*method->nativeFunc)((u4*)self->interpSave.curFrame, pResult,
                                  method, self);
            TRACE_METHOD_EXIT(self, method);
        } else {
            //如果是java函数,调用解释器去解释执行对应的dex方法字节码
            dvmInterpret(self, method, pResult);
        }
       ...
    }
    

    dvmCallMethodV函数会先判断是否为Method是否为native函数,如果是就调用Method->nativeFunc对应的地址。如果是java层函数,调用解释器去解释执行对应的dex方法字节码。

    • method->nativeFunc对应的地址
    DalvikBridgeFunc nativeFunc;
    
    typedef void (*DalvikBridgeFunc)(const u4* args, JValue* pResult,
        const Method* method, struct Thread* self);
    

    我们看一下他的定义,这个一个函数指针。那他的值是多少呢?
    在loadMethodFromDex中会对其进行赋值,在从dex中加载类的时候会调用loadMethodFromDex。也就是当类需要使用第一次被加载时会调用loadMethodFromDex,然后会解析类中的每一个方法并为其构建Method结构,同时函数会判断此方法是否为native类型的,如果是就会将Method结构的nativeFunc字段设置为dvmResolveNativeMethod函数地址。

    if (dvmIsNativeMethod(meth)) {
         meth->nativeFunc = dvmResolveNativeMethod;
         meth->jniArgInfo = computeJniArgInfo(&meth->prototype);
    }
    

    dvmResolveNativeMethod函数首先调用dvmLookupInternalNativeMethod判断是否为虚拟机实现的native函数,如果是直接调用。如果是其他so库实现的native函数则会调用lookupSharedLibMethod从对应的so库导出函数中查找指定的函数名称然后调用。

    void dvmResolveNativeMethod(const u4* args, JValue* pResult,
        const Method* method, Thread* self)
    {
        ClassObject* clazz = method->clazz;
    
        
        DalvikNativeFunc infunc = dvmLookupInternalNativeMethod(method);
        if (infunc != NULL) {
            /* resolution always gets the same answer, so no race here */
            IF_LOGVV() {
                char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
                LOGVV("+++ resolved native %s.%s %s, invoking",
                    clazz->descriptor, method->name, desc);
                free(desc);
            }
            if (dvmIsSynchronizedMethod(method)) {
                ALOGE("ERROR: internal-native can't be declared 'synchronized'");
                ALOGE("Failing on %s.%s", method->clazz->descriptor, method->name);
                dvmAbort();     // harsh, but this is VM-internal problem
            }
            DalvikBridgeFunc dfunc = (DalvikBridgeFunc) infunc;
            dvmSetNativeFunc((Method*) method, dfunc, NULL);
            dfunc(args, pResult, method, self);
            return;
        }
    
    
    
        /* now scan any DLLs we have loaded for JNI signatures */
        void* func = lookupSharedLibMethod(method);
       
    }
    
  • 相关阅读:
    git pull fatal: refusing to merge unrelated histories
    Git报错:Your branch is ahead of 'origin/master' by 1 commit
    java读取大文件内容到Elasticsearch分析(手把手教你java处理超大csv文件)
    Java try catch语句块中try()的括号中代码作用
    Redis这15个“雷坑”,别问我咋知道的……
    MySql死锁
    MQ限流应用
    什么是 JWT -- JSON WEB TOKEN
    mybatis-plus查询指定字段
    数据库炸了----我就重启了一下啊(Communications link failure)
  • 原文地址:https://www.cnblogs.com/revercc/p/16194323.html
Copyright © 2020-2023  润新知