其实其内部最核心的原理是在c语言,而不是在java,其是利用了一个c语言的动态链接库来实现了加载动态链接库
dlopen、dlsym、dlclose加载动态链接库
我们先生成一个动态链接库
// lib.h
int gcd(int a,int b);
// lib.c
#include<lib.h>
int gcd(int a,int b){
if(b == 0){
return a;
}
return gcd(b,a%b);
}
用上面的函数生成动态链接库
# 生成动态链接库
gcc lib.c -fPIC -shared -o libl.so
使用上面的动态链接库
// t.c
#include<stdio.h>
// 三个函数所在头文件
#include<dlfcn.h>
// 函数指针
typedef int (*Gcd)(int,int);
int main(){
// 加载对应的动态链接库,传入文件路径
void* handle = dlopen("./libl.so",RTLD_LAZY);
if(!handle){
printf("dynamic link library load fail\n");
return 0;
}
// 调用动态链接库中的函数
Gcd gcd = (Gcd)dlsym(handle,"gcd");
printf("gcd:%d\n",gcd(100,50));
dlclose(handle);
}
编译
# 编译时候要加入 -ldl (指定dl库)
gcc t.c -ldl
之后就可以运行了
dlopen中的几个mode
RTLD_LAZY:在dlopen返回前,对于动态库中存在的未定义的变量(如外部变量extern,也可以是函数)不执行解析,就是不解析这个变量的地址。
RTLD_NOW:与上面不同,他需要在dlopen返回前,解析出每个未定义变量的地址,如果解析不出来,在dlopen会返回NULL,错误为 : undefined symbol: xxxx…
RTLD_GLOBAL:它的含义是使得库中的解析的定义变量在随后的其它的链接库中变得可以使用。
RTLD_LOCAL:与RTLD_GLOBAL作用相反,动态库中定义的符号不能被其后打开的其它库重定位。如果没有指明是RTLD_GLOBAL还是RTLD_LOCAL,则缺省为RTLD_LOCAL。
上述几种mode使用|进行组合