Ubuntu Feisty 下开发 JNI 应用步骤 (Java调用C/C++的技术)


前两天,做了个只有一个页面的小网站 F1IP.com,用来查询本机IP地址和定位IP的地理位置。

其中主要就是用到 Java调用C/C++的JNI技术。下面,整理一下我开发 JNI 应用的大致过程。

========================================================
Java端代码
========================================================
1】参考《JNI编程指南与规范》(见参考),编写Java源文件(*.Java),建立相应的类;
$ cd /home/me/tipfoo/f1ip/lib.src/com.f1ip.locator/
$ mkdir -p src/com/f1ip/
$ gedit src/com/f1ip/IPLocator.java &

2】将*.java文件编译成*.class。
$ mkdir -p classes
$ javac -g:none src/com/f1ip/IPLocator.java -d classes

3】打包程序,生成Jar包
$ jar cvf com.f1ip.iplocator.jar -C classes/ .

========================================================
本地C/C++代码
========================================================
1】产生C++头文件(*.h)
$ cd classes/
$ javah com.f1ip.IPLocator
这时将生成“com_f1ip_IPLocator.h”文件。

2】编辑本地C++代码,实现所需功能。
$ gedit com_f1ip_IPLocator.h com_f1ip_IPLocator.cpp &

3】编译生成共享库(动态链接库)。

使用GCC时,必须通知编译器在何处查找此 Java 本地方法的头文件,并且显式通知编译器生成位置无关的代码,
Java 头文件路径通过下面的方法得到:

$ update-alternatives --list java
/usr/lib/jvm/java-6-sun/jre/bin/java

那么结果就是“/usr/lib/jvm/java-6-sun/include/”,于是得到下面的编译命令:

$ g++ -fPIC -O2 -shared -Wl,-soname,libf1iplocator.so.1 -o libf1iplocator.so.1.0 /
-I/usr/lib/jvm/java-6-sun/include/ -I/usr/lib/jvm/java-6-sun/include/linux /
com_f1ip_IPLocator.cpp ipsearcher.cpp

其中“ -fPIC”显式通知编译器生成位置无关的代码;“ -shared”生成共享库;“-O2”优化开关;
为ld指定“-Wl,-soname,libf1iplocator.so.1”是个好习惯,而不是以文件名搜索共享库;
输出文件为“libf1iplocator.so.1.0”。最后,列出所有要编译的源文件。

-------------------------------------------
注1:对于C++语言不能像下面这样编译。
$ gcc -fPIC -shared -O2 -I/usr/lib/jvm/java-6-sun/include/ -I/usr/lib/jvm/java-6-sun/include/linux /
    com_f1ip_IPLocator.c -o libf1iplocator.so.1.0
否则,编译通过,但运行时出错:
Cannot load F1IPLocator library:
 java.lang.UnsatisfiedLinkError: .............
undefined symbol: __gxx_personality_v0

注2:如果上面的编译命令中,没有列出所有的C/C++文件(*.c,*.cpp),则在运行时报错:
java: symbol lookup error: ........./libf1iplocator.so.1.0: undefined symbol: _ZN10IpSearcherC1Ev
-------------------------------------------

4】安装共享库。
以链接的形式,为生成的共享库创建标准文件名:
$ ln -sf libf1iplocator.so.1.0 libf1iplocator.so.1
$ ln -sf libf1iplocator.so.1 libf1iplocator.so
复制共享库到系统共享库目录下:
$ sudo cp libf1iplocator.so* /usr/lib/


========================================================
测试
========================================================
1】建立文本文件 TestF1IP.java,内容如下:

import com.f1ip.IPLocator;

class TestF1IP {
    public static void main(String args[]) {
        IPLocator ip;
        // 指定IP数据库的文件路径
        String filepath = "/home/me/tipfoo/f1ip/ipdb.update/ipdb.dat";

        ip = new IPLocator();
        ip.LoadDB(filepath);

        StringBuffer s;
        s = new StringBuffer("");

        // 打印指定IP的地理位置
        ip.Seek("127.0.0.1",s);
        System.out.println("Native method returns: " + s);
    }

2】编译执行
$ javac TestF1IP.java
$ java TestF1IP
Native method returns: 本机地址


========================================================
布署注意事项
========================================================
1】布署共享库
一种办法是在Java命令行中指定“ -Djava.library.path”参数,指向共享库所在的目录,例如:
 -Djava.library.path=/usr/local/lib/myjavalib

另一种,是将共享库文件“libf1iplocator.so*”放在“java.library.path”列出的路径中。
Ubuntu Feisty 可放在“/usr/lib/”目录下,而RHEL系列,应放在JRE的lib下,例如:
“/usr/lib/jvm/jdk1.6.0_03/jre/lib/amd64/”

2】布署Jar文件
因为本地共享库(动态链接库)只能载入一次;所以,将“com.f1ip.iplocator.jar”包放到“$CATALINA_HOME/lib”,以确保其类只载入一次。


========================================================
参考
========================================================
《JNI规范》
http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/jniTOC.html

《JNI编程指南与规范》英文版电子书下载
http://java.sun.com/docs/books/jni/download/jni.pdf
(目录 http://java.sun.com/docs/books/jni/index.html)

JNI参数传引用
http://www.javaworld.com/javaworld/javatips/jw-javatip54.html

Java代码编译
http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/javac.html
 
(tipfoo)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值