- 所谓的native准确的说是借由虚拟机实现的JNI接口调用的操作系统提供的API
- JNI使得class中的ACC_NATIVE标至的方法能借由JNI类的实例转换为JNI规范(如全限定名)的c实现方法实例(已经由.lib在虚拟机初始化时加载或者借由已经加载的类库的load方法,用java等语言加入内存),该实例会调用本地方法栈中的方法(操作系统提供的API)
.h、.cpp、.lib和.dll
.h头文件和.cpp是编译时必须的,lib是链接时需要的,dll是运行时需要的。
.h:声明函数接口
.cpp:c++语言实现的功能源码
.lib :
LIB有两种,一种是静态库,比如C-Runtime库,这种LIB中有函数的实现代码,一般用在静态连编上,它是将LIB中的代码加入目标模块(EXE或者DLL)文件中,所以链接好了之后,LIB文件就没有用了。
一种LIB是和DLL配合使用的,里面没有代码,代码在DLL中,这种LIB是用在静态调用DLL上的,所以起的作用也是链接作用,链接完成了,LIB也没用了。至于动态调用DLL的话,根本用不上LIB文件。 目标模块(EXE或者DLL)文件生成之后,就用不着LIB文件了。
.dll:
动态链接库英文为DLL,是Dynamic Link Library的缩写。DLL是一个包含可由多个程序,同时使用的代码和数据的库。
当程序使用 DLL 时,具有以下的优点: 使用较少的资源,当多个程序使用同一个函数库时,DLL 可以减少在磁盘和物理内存中加载的代码的重复量(运行时需要的库是需要加入内存的)。
.h和.cpp编译后会生成.lib和.dll 或者 .dll 文件
我们的程序引用别的文件的函数,需要调用其头文件,但是头文件找到相应的实现有两种方式,一种是同个项目目录下的其他cpp文件(公用性差),一种是链接时的lib文件(静态,lib中自己有实现代码),一种是运行时的dll文件,一种是lib和dll 的结合(动态,lib放索引,dll为具体实现)
还要指定编译器链接相应的库文件。在IDE环境下,一般是一次指定所有用到的库文件,编译器自己寻找每个模块需要的库;在命令行编译环境下,需要指定每个模块调用的库。
一般不开源的系统是后面三种方式,因为可以做到接口开放,源码闭合
静态链接库
静态链接库(Static Libary,以下简称“静态库”),静态库是一个或者多个obj文件的打包,所以有人干脆把从obj文件生成lib的过程称为Archive,即合并到一起。比如你链接一个静态库,如果其中有错,它会准确的找到是哪个obj有错,即静态lib只是壳子,但是静态库本身就包含了实际执行代码、符号表等等。
如果采用静态链接库,在链接的时候会将lib链接到目标代码中,结果便是lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了。
这个lib文件是静态编译出来的,索引和实现都在其中。
静态编译的lib文件有好处:给用户安装时就不需要再挂动态库了。但也有缺点,就是导致应用程序比较大,而且失去了动态库的灵活性,在版本升级时,同时要发布新的应用程序才行。
动态链接库(DLL)
.dll + .lib : 导入库形式,在动态库的情况下,有两个文件,而一个是引入库(.LIB)文件,一个是DLL文件,引入库文件包含被DLL导出的函数的名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到所需要使用的DLL文件,库中的函数和数据并不复制到可执行文件中,因此在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内存地址,这样当一个或多个应用程序运行是再把程序代码和被调用的函数代码链接起来,从而节省了内存资源。
从上面的说明可以看出,DLL和.LIB文件必须随应用程序一起发行,否则应用程序将会产生错误。
.dll形式: 单独的可执行文件形式,因为没有lib 的静态载入,需要自己手动载入,LoadLibary调入DLL文件,然后再手工GetProcAddress获得对应函数了,若是java 会调用System的LoadLibary,但是也是调用JVM中对于操作系统的接口,使用操作系统的LoadLibary等方法真正的将.dll读入内存,再调用生成的相应函数。
.dll+ .lib和.dll本质上是一样的,只是前者一般用于通用库的预设置,是的我们通过lib直接能查询到.dll文件,不用我们自己去查询,虽会消耗一部分性能,但是实用性很大。.dll 每一个需要到的文件都需自己调用加载命令,容易出错与浪费较多时间(但是我们测试时却可以很快的看出功能实现情况,而且更灵活地调用)
JNI
JNI是Java Native Interface的缩写,通过使用 Java本地接口书写程序,可以确保代码在不同的平台上方便移植,它允许Java代码和其他语言写的代码进行交互。
java生成符合JNI规范的C接口文件(头文件):
-
编写带有native声明的方法的java类
-
使用javac命令编译所编写的java类
-
然后使用javah + java类名生成扩展名为h的头文件
-
使用C/C++实现本地方法
-
将C/C++编写的文件生成动态连接库 (linux gcc windows 可以用VS)