Live-Server-7-bsdiff动态库的编译以及差分包的

2019-08-03  本文已影响0人  G63HH

bsdiff和bspatch是用来生成和应用二进制补丁的工具,也就是bsdiff通过新旧文件生成差分包,bspatch通过旧文件和差分包生成新文件,通过差分包的传输,能有效减少网络间传输的流量和时间。bsdiff和bspatch都是基于bzip2,并默认其位置在于/usr/bin。
bsdiff和bspatch在运行时都需要消耗大量的内存空间和时间,假设n是旧文件的大小,m是新文件的大小,那么bsdiff需要的内存空间为max(17n, 9n+m)+O(1)字节;而bspatch需要n+m+O(1)字节。

首先在bsdiff的官网中,可以直接下载bsdiff-4.3这个版本的源码,但是这个版本的源码仅仅支持Linux系统,不支持Windows系统的编译,就需要找到windows版本。

windows下bsdiff的编译

步骤如下:

  1. 查看main()函数需要什么参数
  2. 通过Java类,构建JNI头文件
  3. 将bsdiff源代码导入VS中并修改
  4. 通过VS将其编译成动态库

1. 查看main()函数需要什么参数

来看下bsdiff windows版本的文件目录:


图片.png

首先来看下bsdiff.cpp文件中main()函数有这么一行代码:

if(argc!=4) errx(1,"usage: %s oldfile newfile patchfile\n",argv[0]);

表明main()函数需要传入4个参数,而第一个参数任意填,接着继续读main()函数的方法,可以得知剩余的3个参数分别是旧文件路径、新文件路径和差分包路径。

2. 通过Java类,构建JNI头文件

于是我们就可以编写Java代码和JNI代码。

public class BsDiff {

    public native static void diff(String oldFile, String newFile, String patchFile);

    static {
//        LibLoader.loadLib("Bsdiff.dll");
        LibLoader.loadLib("Bsdiff.so");
    }
}

编译,生成class文件后,通过Idea IDE生成jni头文件。在setting设置中,自定义如下工具


javah工具.png

随后调用该工具,就可以生成BsDiff这个类的JNI头文件。


生成JNI头文件.png
头文件如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_ljh_jni_BsDiff */

#ifndef _Included_com_ljh_jni_BsDiff
#define _Included_com_ljh_jni_BsDiff
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_ljh_jni_BsDiff
 * Method:    diff
 * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_ljh_jni_BsDiff_diff
  (JNIEnv *, jclass, jstring, jstring, jstring);

#ifdef __cplusplus
}
#endif
#endif

3. 将bsdiff源代码导入VS中并修改

在VS中新建空白项目,将bsdiff windows的源代码、jni.h、jni_md.h和刚刚编译出来的JNI头文件导入到项目中。项目目录如下:


图片.png

随后就要修改源代码,使得整体调用逻辑变成通过JNI方法,调用bsdiff中原有的main()函数,生成差分包。
将JNI头文件(com_ljh_jni_BsDiff.h)中的头文件引用修改为本地:

#include <jni.h>     ->    #include "jni.h"

在bsdiff.cpp源文件中,添加JNI头文件、修改main()函数名、添加JNI函数的实现。

1. #include "com_ljh_jni_BsDiff.h"

2.  int main(int argc,char *argv[]){ ... }  -> int bsdiff_main(int argc,char *argv[]){...}

3. 
//JNI调用
JNIEXPORT void JNICALL Java_com_ljh_jni_BsDiff_diff
(JNIEnv* env, jclass jcls, jstring oldfile_jstr, jstring newfile_jstr, jstring patchfile_jstr) {
    int argc = 4;
    char* oldfile = (char*)env->GetStringUTFChars(oldfile_jstr, NULL);
    char* newfile = (char*)env->GetStringUTFChars(newfile_jstr, NULL);
    char* patchfile = (char*)env->GetStringUTFChars(patchfile_jstr, NULL);

    //参数(第一个参数无效)
    char* argv[4];
    argv[0] = (char *)"bsdiff";
    argv[1] = oldfile;
    argv[2] = newfile;
    argv[3] = patchfile;

    bsdiff_main(argc, argv);

    env->ReleaseStringUTFChars(oldfile_jstr, oldfile);
    env->ReleaseStringUTFChars(newfile_jstr, newfile);
    env->ReleaseStringUTFChars(patchfile_jstr, patchfile);
}

4. 通过VS将其编译成动态库

在项目属性中,添加编译的命令行来取消安全性检查之类的异常

-D _CRT_SECURE_NO_WARNINGS -D _CRT_NONSTDC_NO_DEPRECATE 
图片.png

然后在常规设置中,将配置类型配置为动态库(.dll),即可编译。编译成功后,调用JNI中的


图片.png

Linux下bsdiff的编译

在Linux中编译bsdiff的步骤与在windows中类似:

  1. 编译环境配置
  2. 通过Java类,构建JNI头文件
  3. 修改JNI头文件、源代码
  4. 编译成.so动态库

1. 编译环境配置

编译需要gcc和bzip2,通过如下指令安装bzip2

sudo apt-get install libbz2-dev

2.通过Java类,构建JNI头文件 3. 修改JNI头文件、源代码 参考windows编译

4. 编译成.so动态库

gcc bsdiff.c -lbz2 -fPIC -shared -o bsdiff.so
上一篇下一篇

猜你喜欢

热点阅读