The principle of JNI imitates the use of System.loadLibrary and dlopen

Preface

As shown in the figure below, the OpenNativeLibrary code uses the dlopenopen dynamic library. This article calls dlopen and dlsym in the source code to call the method in so to strengthen the understanding.
Following the above review of the LoadLibrary source code process , this article is to imitate the process. After obtaining the so path to be called in the Java layer, pass in the c layer to call dlopenopen, and end dlsymafter calling the method dlclose.image.png

Function description

  • The dlopen() function opens the specified dynamic link library file in the specified mode and returns a handle to the calling process.

    • RTLD_LAZY
      Each external function reference is bound the first time the function is called.
      Before dlopen returns, the undefined variables in the dynamic library (such as external variables extern, or functions) are not parsed, that is, the variable is not parsed Until the first call;
    • RTLD_NOW
      All external function references are bound immediately during the call to dlopen().
      Before dlopen returns, the address of each undefined variable is parsed. If it can’t be resolved, dlopen will return NULL. The error is:
  • dlerror() returns the error that occurred.

  • Use dlsym() to manipulate handles and symbols through the dynamic link library, and return the address corresponding to the symbol.

  • Use dlclose() to unload the opened library.

Example

Step 1: Type the file test.cpplibtest-lib.so

// 文件1 test.cpp: 
int fibonacci(int n) {
    
    
    if (n == 1) return 1;
    if (n == 2) return 1;

    return fibonacci(n - 1) + fibonacci(n - 2);
}

Step 2: The file testdlopen.cpp is printedlibdlopen-lib.so

// 文件2:testdlopen.cpp
extern "C"
JNIEXPORT void JNICALL
Java_com_baiiu_jnitest_dlopen_DLOpenFragment_testdlopen(JNIEnv *env, jobject thiz, jstring jstr) {
    
    
    const char *soPath = env->GetStringUTFChars(jstr, JNI_FALSE);

    LOGD("native--> soPath: %s", soPath);
    // 
    void *handle = dlopen(soPath, RTLD_NOW);

    char *error_msg = nullptr;
    if (handle == nullptr) {
    
    
        error_msg = strdup(dlerror());
        LOGD("%s", error_msg);
    }

    LOGD("handle is %p", handle);

//    void *sym = dlsym(handle, "fibonacci"); // 注意函数名称,这里是个坑点,readelf so发现名称变化了
    void *sym = dlsym(handle, "_Z9fibonaccii");
    if (sym == nullptr) {
    
    
        LOGD("can not find the function");
        return;
    }

    using FIBONACCI = int (*)(int);
    FIBONACCI fibonacci = reinterpret_cast<FIBONACCI>(sym);
    int result = (*fibonacci)(5);

    LOGD("fibonacci result is: %d", result);

    dlclose(handle);

    env->ReleaseStringUTFChars(jstr, soPath);

}

The third step: imitate System#loadLibrary

Finding the libtest-lib.sopath in the Java code was originally performed by hook DexPathList, and the code was also implemented. Suddenly, I found that the findLibrary in BaseDexClassLoader turned out to be public. Isn't that simple? Call it directly, and I am happy.

	private static final String LIB_NAME = "test-lib";
	
	private void test() {
    
    
        try {
    
    
            // 直接调用BaseDexClassLoader#findLibrary找到test-lib路径,传到c层进行dlopen,模仿System#loadLibrary操作
            BaseDexClassLoader dexPathClassLoader = (BaseDexClassLoader) Binder.class.getClassLoader();
            String targetSoAbsolutePath = dexPathClassLoader.findLibrary(LIB_NAME);
            android.util.Log.e("mLogU", "ClassLoader#findLibrary: " + targetSoAbsolutePath);

            testdlopen(targetSoAbsolutePath +"\lib" + LIB_NAME + ".so");
        } catch (Exception e) {
    
    
            android.util.Log.e("mLogU", e.toString());
        }
    }

	private native void testdlopen(String targetSoAbsolutePath);

Conclusion

This article imitates the System#loadLibrary process, and directly opens the so dynamic library in the c layer and calls the execution method. I am a little familiar with this.
Please correct me if there is an error.

Guess you like

Origin blog.csdn.net/u014099894/article/details/111699084