JavaCPP技術使用經驗總結
本文是對 JNI 技術的一個補充方法,提出了替換 JNI、JNA 的一種開源技術。首先對 JavaCPP 技術進行簡單介紹及對應於其他現有方案的介紹、對比。接下來,通過一個簡單的示例讓大家瞭解 JavaCPP 的工作原理。然後,介紹了 JavaCPP presets 子專案,最後通過若干個針對 presets 的示例來讓大家瞭解如何使用它,本文主要提出了替換 JNI 的一種程式設計實現方式。
JavaCPP 簡介
JavaCPP 是一個開源庫,它提供了在 Java 中高效訪問本地 C++的方法。採用 JNI 技術實現,所以支援所有 Java 實現包括 Android 系統,Avian 和 RoboVM。
- Android
一種基於 Linux 的自由及開放原始碼的作業系統,主要使用於移動裝置,如智慧手機和平板電腦,由 Google 公司和開放手機聯盟領導及開發。
- Avian
Avian 是一個輕量級的 Java 虛擬機器和類庫,提供了 Java 特性的一個有用的子集,適合開發跨平臺、自包容的應用程式。它實現非常快速而且體積小,主要特性包括如下四點:
- 類似於 HotSpot JVM 的 JIT 編譯器,支援快速方法執行;
- 採用 JVM 的複製演算法,即將現有的記憶體空間分為兩快,每次只使用其中一塊,在垃圾回收時將正在使用的記憶體中的存活物件複製到未被使用的記憶體塊中,之後,清除正在使用的記憶體塊中的所有物件,交換兩個記憶體的角色,完成垃圾回收。這樣可以確保記憶體回收過程中記憶體暫停服務的時間較短,並且記憶體的使用空間侷限性較小;
- JVM 記憶體區域裡面的本地棧快速分配,沒有同步開銷;
- 作業系統訊號量方式解決了空指標問題,避免了不必要的分支。
- RoboVM
RoboVM 編譯器可以將 Java 位元組碼翻譯成 ARM 或者 x86 平臺上的原生程式碼,應用可直接在 CPU 上執行,無需其他直譯器或者虛擬機器。RoboVM 同時包含一個 Java 到 Objective-C 的橋,可像其他 Java 物件一樣來使用 Objective-C 物件。大多數 UIKit 已經支援,而且將會支援更多的框架。
總的來說,JavaCPP 提供了一系列的 Annotation 將 Java 程式碼對映到 C++程式碼,並使用一個可執行的 jar 包將 C++程式碼轉化為可以從 JVM 內呼叫的動態連結庫檔案。
與其他技術相比,特性總結如下表 1 所示。
表 1. 類似技術介紹或特點
技術名稱 | 技術介紹 |
---|---|
CableSwig | 用於針對 Tcl 和 Python 語言建立介面 |
JNIGeneratorApp | 所有用於 SWT 的 C 程式碼都是通過它來建立的 |
cxxwrap | 用於生成針對 C++的 Java JNI 包、HTML 文件、使用者手冊 |
JNIWrapper | 商業版本,可以幫助實現 Java 和原生程式碼之間的無縫結合 |
Platform Invoke | 微軟釋出的一個工具 |
GlueGen | 針對 C 語言的一個工具,幫助生成 JNI 程式碼 |
LWJGL Generator | JNI 程式碼生成器 |
ctypes | 針對 Python 的介面程式碼生成器 |
JNA | JNA(Java Native Access)提供一組 Java 工具類用於在執行期動態訪問系統本地庫(native library:如 Window 的 dll)而不需要編寫任何 Native/JNI 程式碼。開發人員只要在一個 Java 介面中描述目標 native library 的函式與結構,JNA 將自動實現 Java 介面到 native function 的對映。 |
JNIEasy | 替換 JNA 的一種技術 |
JNative | Windows 版本的庫 (DLL),提供了 JNI 程式碼生成 |
fficxx | 針對 haskell 模型的程式碼生成器,主要生成 C 語言 |
JavaCPP | 更加自然高效,它支援大部分的 C++語法特性。目前已經能成功封裝 OpenCV, FFmpeg, libdc1394, PGR FlyCapture, OpenKinect, videoInput, and ARToolKitPlus。除此之外,它還能直接把 C/C++的標頭檔案轉化成 Java 類,能自動生成 JNI 程式碼,編譯成本地庫,開發人員無需編寫繁瑣的 C++、JNI 程式碼,從而提高開發效率。 |
JavaCPP 示例
為了呼叫本地方法,JavaCPP 生成了對應的 JNI 程式碼,並且把這些程式碼輸入到 C++編譯器,用來構建本地庫。使用了 Annotations 特性的 Java 程式碼在執行時會自動呼叫 Loader.load() 方法從 Java 資源裡載入本地庫,這裡指的資源是工程構建過程中配置好的。
我們先來演示一個例子,這是一個簡單的注入/讀出方法,類似於 JavaBean 的工作方式。清單 1 所示的 LegacyLibrary.h 包含了 C++類。
清單 1. LegacyLibrary.h
#include <string> namespace LegacyLibrary { class LegacyClass { public: const std::string& get_property() { return property; } void set_property(const std::string& property) { this->property = property; } std::string property; }; }
接下來定義一個 Java 類,驅動 JavaCPP 來完成呼叫 C++程式碼。
清單 2. LegacyLibrary.java
import org.bytedeco.javacpp.*; import org.bytedeco.javacpp.annotation.*; @Platform(include="LegacyLibrary.h") @Namespace("LegacyLibrary") public class LegacyLibrary { public static class LegacyClass extends Pointer { static { Loader.load(); } public LegacyClass() { allocate(); } private native void allocate(); // to call the getter and setter functions public native @StdString String get_property(); public native void set_property(String property); // to access the member variable directly public native @StdString String property(); public native void property(String property); } public static void main(String[] args) { // Pointer objects allocated in Java get deallocated once they become unreachable, // but C++ destructors can still be called in a timely fashion with Pointer.deallocate() LegacyClass l = new LegacyClass(); l.set_property("Hello World!"); System.out.println(l.property()); } }
以上兩個類放在一個目錄下面,接下來執行一系列編譯指令,如清單 3 所示。
清單 3. 執行命令
$ javac -cp javacpp.jar LegacyLibrary.java $ java -jar javacpp.jar LegacyLibrary $ java -cp javacpp.jar LegacyLibrary Hello World!
我們看到清單 3 最後執行輸出了一行“Hello World!”,這是 LegacyLibrary 類裡面定義好的,通過一個 setter 方法注入字串,getter 方法讀出字串。
我們可以看到資料夾裡面內容的變化,剛開始的時候只有.h、.java 兩個檔案,清單 3 所示的 3 個命令執行過後,生成了 class 檔案及本地方法 (native method) 對應的.so 檔案。
http://www.ibm.com/developerworks/cn/java/j-lo-cpp/
相關文章
- Git Flow 使用經驗總結Git
- mysql索引使用經驗總結MySql索引
- Windows RocketMQ使用方法經驗總結WindowsMQ
- 使用 Golang 寫爬蟲經驗總結Golang爬蟲
- AOT使用經驗總結m8
- 工作經驗總結
- 常用快取系統使用經驗總結快取
- 做題經驗總結
- 考試經驗總結
- Redis在專案中合理使用經驗總結Redis
- docker技術總結Docker
- BypassUAC技術總結
- CMake技術總結
- WPF技術總結
- Android開發經驗總結Android
- iOS開發經驗總結iOS
- Flutter 介紹 & 經驗總結Flutter
- 工作經驗日常總結===20241105
- 日常專案經驗總結
- IT職場管理經驗總結
- Elasticsearch 實戰經驗總結Elasticsearch
- Git使用經驗總結5-修改提交資訊Git
- 智慧控制技術總結
- docker技術總結(二)Docker
- 池化技術總結
- node+express框架中連線使用mysql經驗總結Express框架MySql
- docker使用經驗總結(三、Docker compose基礎應用)Docker
- iOS開發經驗總結2iOS
- iOS開發經驗總結3iOS
- vue移動端經驗總結Vue
- 《軟體專案經驗總結》
- 計算機考研經驗總結計算機
- 我的刷題經驗總結
- web 前端秋招總結(內附面經)|掘金技術徵文Web前端
- 使用 Sphinx 撰寫技術文件並生成 PDF 總結
- Elasticsearch 技術分析(九):Elasticsearch的使用和原理總結Elasticsearch
- 個人技術棧總結
- 特徵選擇技術總結特徵
- 技術總監7年經驗,告訴大家,【拒絕】才是專業