JNI的高级用法(1)——动态库中的动态编译技术

本文介绍了一种利用Java Native Interface (JNI)实现的动态编译技术。该技术分为caller、callee和base三部分,通过动态装配callee代码实现程序的灵活性。caller作为Java接口调用动态库,callee为动态编译部分,base提供基础函数支持。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

对于普通的Java Native Interface的用法已经比较常见,网上或书中的例子有如汗牛充栋,但是C/C++作为Java动态库而实现的动态编译技术却是比较少见。虽然并不常见,但在某些情况下,这种动态编译技术确是不可或缺,有了它才能满足这种动态的装配需求。

先从结构说起,如图所示,首先这种动态结构的JNI分为三个部分:作为Java的接口而直接被调用的部分称为caller,这部分会单独被编译为被Java代码直接调用的动态库;程序需要动态编译的代码(称为callee)是不确定的部分,即程序的其它部分编译好发布之时,callee这部分代码还不存在或尚未编译,因此是动态的;callee本身还需要调用基础函数或基础类库(自己编写的、非系统库的部分),这部分成为base。

这种动态装配技术在使用中,显然要分为三个操作步骤:第一步让程序的使用者指定或完成不确定的代码部分(动态装配),第二步根据使用者提供的代码进行编译(当然是让程序去自动编译),第三步运行整个程序,调用动态部分。

Base部分由于是基础函数/基础类库部分,因此代码在最初是确定的,将Base部分编译为静态库更为合理,这个静态库最终将被动态的callee所调用,当Callee部分被编译时再链接这个精态度而形成Callee的动态库,编译过程中会检查相关符号链接。Caller本身在此之前就会被编译为动态库,这部分动态库直接被Java代码所调用,caller动态库在运行时又会去调用callee部分的动态库,从而实现上述所说的动态编译技术。

对于Base部分的Makefile如下:

CC = gcc
AR = ar
CFLAGS = -fPIC -O2 -g -Wall
OBJS = base.o log.o util.o config.o

libsoap.a : $(OBJS)
 $(AR) rcs libbase.a $(OBJS)

%.o : %.c
 $(CC) -c $(CFLAGS) $< -o $@

......

 

Caller部分的代码如下:

   ......

   dlerror();
   fcn = dlsym(handle, callee);
   if ((errmsg = dlerror()) != NULL)
   {
    fprintf(stderr, "Can't find function (%s): (%s)/n", callee, errmsg);
    exit(-1);
   }
   fcn();

   ......

 

另外,使用中需要特别注意环境变量的设置(LD_LIBRARY_PATH),将相关动态库的目录设置在其中,否则编译或运行时就会出现动态库找不到的情况。

为了实现这种动态编译,需要在运行环境必须事先安装好与编译相关的软件,例如编译器(gcc)和makefile。

本文所面向的环境是针对Linux/Unix平台,对于Windows平台,仍然从中可以得到启发,创建于此相类似的过程。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值