JNI开发教程之bsdiff增量更新的服务端实现

JNI简介

    JAVA NATIVE INTERFACE 顾名思义,就是JAVA语言调用其他NATIVE语言的一个接口。

    这样说来可能有点晦涩,说白了,JNI就是JAVA想调用其他语言的桥梁--比如C,C++(这种就叫做NATIVE语言)等。

    下面盗个图来解释一下关系:

                                      

  友情链接:https://blog.csdn.net/itachi85/article/details/73459880

---------------------------------------------------------------------------------------------------------------


下面用bsdiff增量更新来演示jni的调用过程

--准备工作:

    1.bzip2(这个很关键,后面会用到)下载 http://www.bzip.org/downloads.html(后面主要会用到这个),以及bsdiff源码 (用于了解)

    2.编译环境,建议最好在linux环境下,用GCC编译(博主在windows下面搞了几天没搞明白,有大神可以尝试)

      相关项目实例:https://github.com/ccj659/incremental-update-master   

      IDEA平台下JNI编程:https://blog.csdn.net/huachao1001/article/details/53906237

-- 开始编码(以下均在linux环境下进行,以JDK1.8为例):

     1.JAVA中创建NATIVE方法(其中的add方法主要用于main方法的测试,如果不需要可以忽略

package test;

public class TestBsdiff {
    public native static int diff(String oldFile, String newFile, String patchch);

    public native static int add(int a, int b);

    static {
        System.loadLibrary("app_bsdiff");
        System.out.println("loading C libary ");
    }

    public static void main(String args[]) {
        int sum = 0;
        sum = TestBsdiff.add(1, 2);
        System.out.print(sum);
    }
}

    这里静态块用于加载C代码(NATIVE代码)编程生成的文件--适用于windows为*.dll,适用于linux为*.so,我们这里以linux下的*.so为例

    编写好了JAVA代码,编译成C的头文件 *.h:

        jdk1.8以上编译使用    javac -h . TestBsdiff.java

        jdk1.8以下编译使用    javac TestBsdiff.java

                                          javah  TestBsdiff

     编译后,就会在当前目录生成test_TestBsdiff.h 即C语言的头文件 (不难看出,这个test是java文件的包名,下划线后面是类名)然后,将test_TestBsdiff.h放到src目录下

     2.将下载好的bzip2解压,将其中的bzlib.h,bzlib_private.h,bzlib.c,blocksort.c,bsdiff.c,bzip.c,compress.c,crctable.c,decompress.c,huffman.c,randtable.c解压到src目录下(与test_TestBsdiff.h位置一样)

      然后要修改bsdiff.c如下,在头中加入#include<jni.h> ,#include<test_TestBsdiff.h>(引入头文件并实现其中的方法)

#include <jni.h>
#include <test_TestBsdiff.h>
#include <sys/types.h>

    修改其中的main函数为bsdiff_main

int bsdiff_main(int argc,char *argv[])

    最后在末尾增加代码段,实现头文件中的两个方法test_TestBsdiff_diff与Java_test_TestBsdiff_add

JNIEXPORT jint JNICALL Java_test_TestBsdiff_diff
(JNIEnv *env, jclass cls, jstring old, jstring new, jstring patch){
    int argc=4;
    char * argv[argc];
    argv[0]="bsdiff";
    argv[1]=(char*)((*env)->GetStringUTFChars(env,old, 0));
    argv[2]=(char*)((*env)->GetStringUTFChars(env,new, 0));
    argv[3]=(char*)((*env)->GetStringUTFChars(env,patch, 0));

    int ret=bsdiff_main(argc, argv);

    (*env)->ReleaseStringUTFChars(env,old,argv[1]);
    (*env)->ReleaseStringUTFChars(env,new,argv[2]);
    (*env)->ReleaseStringUTFChars(env,patch,argv[3]);
    return ret;
}
JNIEXPORT jint JNICALL Java_test_TestBsdiff_add
(JNIEnv *env, jobject obj, jint a, jint b) {
        int var = 0;
        var = a + b;
        return var;
}

      这个时候,进入到src目录下,执行执行如下,将这些源码编译成*.so文件

    gcc -fPIC -I/usr/local/jdk1.8.0_91/include/ -I/usr/local/jdk1.8.0_91/include/linux/ -I/home/hotfixas2/workspace/src  -shared -o libapp_bsdiff.so  bzlib.c bzip2.c blocksort.c compress.c crctable.c decompress.c huffman.c randtable.c bsdiff.c

      以上指令略长,稍微说明一下

     (1)首先解释一下 gcc指令 

             -fPIC的含义表示编译成位置独立的代码(Position Independent Code),具体可以自己百度一下

             -shared的含义就是指定生成动态链接库*.so

             -o 表示输出的文件类型,这里面是*.so

     (2)解释一下其中的一些参数

            -I/usr/local/jdk1.8.0_91/include/ 意思就是要通过扫描使用jdk1.8包这里面的文件,jni.h

           -I/usr/local/jdk1.8.0_91/include/linux/ 同上,也是要用到其中的文件,jni_md.h

           libapp_bsdiff.so 这个要特别注意一下,虽然在java里面System.loadLibrary(“app_bsdiff.so”),但是在linux里面必须要加上lib这个前缀,表示这个是动态链接库

      这个时候,如果文件的位置都正确的话,就会在src目录下生成一个叫做libapp_bsdiff.so的动态链接库文件!!

    3.现在有了java的方法声明,C语言的实现app_bsdiff.so,那么就差最后这一环节----就是告诉JAVA程序,去哪里找实现类app_bsdiff.so。最后这一步也是尤为重要的一步,否则会报java.lang.unsatisfiedLinkError

      设置linux的LD_LIBRARY_PATH变量

      临时导入:$    export LD_LIBRARY_PATH=/home/hotfixas2/workspace/src(也就是app_bsdiff.so所在的目录)

      永久导入:可以在~/.bashrc或者~./bash_profile中末尾加入export语句 

                       export LD_LIBRARY_PATH=/home/hotfixas2/workspace/src(也就是app_bsdiff.so所在的目录)

      修改完毕后,记得关掉当前终端的并重新打开一个新的终端使之生效

    4.自测是否已经链接成功

      进入到src目录下,TestBsdiff.class所在目录src/test, 执行指令java -cp . test.TestBsdiff,如果运行成功

      将会输出 loading C library 3 

   5.既然链接成功,那么就可以试试diff方法是否可以正常解析(找两个apk的新旧两个包,放到指定目录下)

    将apk包放入指定的目录,也就是java中diff的前两个参数,最后一个参数是比对成功后生成patch的名字

    执行一下,看看能否生成想要的patch

TestBsdiff.diff("old.apk","new.apk","result.patch");

   ---------------------------------------------

 英文较好的同学,请参考 :  jni API文档英文链接



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值