Live-Server-7-bsdiff動態庫的編譯以及差分包的生成
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的編譯
步驟如下:
- 檢視main()函式需要什麼引數
- 通過Java類,構建JNI標頭檔案
- 將bsdiff原始碼匯入VS中並修改
- 通過VS將其編譯成動態庫
1. 檢視main()函式需要什麼引數
來看下bsdiff windows版本的檔案目錄:
首先來看下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設定中,自定義如下工具
/* 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);
#ifdef __cplusplus
}
#endif
#endif
複製程式碼
3. 將bsdiff原始碼匯入VS中並修改
在VS中新建空白專案,將bsdiff windows的原始碼、jni.h、jni_md.h和剛剛編譯出來的JNI標頭檔案匯入到專案中。專案目錄如下:
隨後就要修改原始碼,使得整體呼叫邏輯變成通過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
複製程式碼
然後在常規設定中,將配置型別配置為動態庫(.dll),即可編譯。編譯成功後,呼叫JNI中的
Linux下bsdiff的編譯
在Linux中編譯bsdiff的步驟與在windows中類似:
- 編譯環境配置
- 通過Java類,構建JNI標頭檔案
- 修改JNI標頭檔案、原始碼
- 編譯成.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
複製程式碼