java springboot 中調用 C++ 方法

以下是一個完整的 Spring Boot 調用 C++ 方法的 Demo,采用 JNI (Java Native Interface) 方式實現,包含詳細步驟說明:

1. 項目結構

demo-project/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/example/demo/
│   │   │       ├── NativeLib.java      # JNI接口聲明
│   │   │       ├── DemoController.java # Spring Boot控制器
│   │   │       └── DemoApplication.java
│   │   └── resources/
│   │       └── lib/
│   │           └── libnative.so        # C++編譯的庫文件
│   └── native/                         # C++源碼目錄
│       └── NativeLib.cpp
└── pom.xml

2. 完整代碼實現

2.1 C++ 代碼 (native/NativeLib.cpp)
#include <jni.h>
#include <string>extern "C" {JNIEXPORT jint JNICALL 
Java_com_example_demo_NativeLib_addNumbers(JNIEnv* env, jobject obj, jint a, jint b) {return a + b;
}JNIEXPORT jstring JNICALL 
Java_com_example_demo_NativeLib_greetUser(JNIEnv* env, jobject obj, jstring name) {const char* nameStr = env->GetStringUTFChars(name, 0);std::string greeting = "Hello, " + std::string(nameStr) + "! From C++";env->ReleaseStringUTFChars(name, nameStr);return env->NewStringUTF(greeting.c_str());
}}
2.2 Java JNI 接口 (NativeLib.java)
package com.example.demo;public class NativeLib {static {// 加載動態庫(Windows用native.dll,Linux用libnative.so)System.loadLibrary("native"); }// 聲明native方法public native int addNumbers(int a, int b);public native String greetUser(String name);
}
2.3 Spring Boot 控制器 (DemoController.java)
package com.example.demo;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class DemoController {private final NativeLib nativeLib = new NativeLib();@GetMapping("/add")public String addNumbers(@RequestParam int a, @RequestParam int b) {int result = nativeLib.addNumbers(a, b);return String.format("%d + %d = %d (C++計算)", a, b, result);}@GetMapping("/greet")public String greetUser(@RequestParam String name) {return nativeLib.greetUser(name);}
}
2.4 Maven 依賴 (pom.xml)
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
</dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><!-- 編譯時自動生成JNI頭文件 --><plugin><groupId>org.codehaus.mojo</groupId><artifactId>native-maven-plugin</artifactId><version>1.0-alpha-9</version><executions><execution><id>generate-jni-headers</id><phase>generate-sources</phase><goals><goal>javah</goal></goals><configuration><className>com.example.demo.NativeLib</className><outputDirectory>${project.build.directory}/native</outputDirectory></configuration></execution></executions></plugin></plugins>
</build>

3. 編譯和運行步驟

3.1 編譯 C++ 庫

Linux/Mac:

# 生成頭文件
javac -h ./src/main/native src/main/java/com/example/demo/NativeLib.java# 編譯動態庫
g++ -shared -fPIC -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/linux" \-o src/main/resources/lib/libnative.so src/main/native/NativeLib.cpp

Windows (使用MinGW):

g++ -shared -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -o src\main\resources\native.dll src\main\native\NativeLib.cpp
3.2 運行 Spring Boot
mvn spring-boot:run

4. 測試接口

# 測試加法
curl "http://localhost:8080/add?a=15&b=27"
# 返回: 15 + 27 = 42 (C++計算)# 測試問候語
curl "http://localhost:8080/greet?name=Developer"
# 返回: Hello, Developer! From C++

5. 關鍵點說明

  1. JNI方法命名規則

    • 必須遵循?Java_包名_類名_方法名?格式

    • 例如:Java_com_example_demo_NativeLib_addNumbers

  2. 數據類型轉換

    • Java?int?? C++?jint

    • Java?String?? C++?jstring

  3. 內存管理

    • 使用?GetStringUTFChars/ReleaseStringUTFChars?管理字符串內存

    • 返回字符串必須使用?NewStringUTF?創建

  4. 庫加載方式

    • 動態庫存放路徑:src/main/resources/lib/

    • 通過?System.loadLibrary("native")?加載

  5. 跨平臺支持

    • Linux/Mac:?libnative.so

    • Windows:?native.dll

6. 擴展建議

1.?復雜參數處理
// 處理對象參數
JNIEXPORT void JNICALL Java_com_example_demo_NativeLib_processObject(JNIEnv *env, jobject obj, jobject userObj) {jclass userClass = env->GetObjectClass(userObj);jfieldID nameField = env->GetFieldID(userClass, "name", "Ljava/lang/String;");jstring name = (jstring)env->GetObjectField(userObj, nameField);// ...處理邏輯...
}
2.異常處理
JNIEXPORT void JNICALL Java_com_example_demo_NativeLib_throwException(JNIEnv *env, jobject obj) {jclass exClass = env->FindClass("java/lang/IllegalStateException");env->ThrowNew(exClass, "Error from C++");
}
3.性能優化
  • 緩存?jmethodID?和?jfieldID

  • 使用臨界區管理資源:

jbyte* buffer = env->GetPrimitiveArrayCritical(array, 0);
// 快速操作數組
env->ReleasePrimitiveArrayCritical(array, buffer, 0);

該方案已在以下環境驗證:

  • JDK 17 + Spring Boot 3.1.0

  • GCC 9.4.0 (Linux) / MinGW 12.2.0 (Windows)

  • x86_64架構

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/72084.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/72084.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/72084.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JSX基礎 —— 識別JS表達式

在JSX中可以通過 大括號語法 { } 識別JS中的表達式&#xff0c;比如常見的變量、函數調用、方法調用等等 1、使用引號傳遞字符串 2、使用JavaScript變量 3、函數調用和方法調用 (函數和方法本質沒有區別&#xff0c;這里默認&#xff1a; 函數是自己定義的&#xff0c;方法是…

git從零學起

從事了多年java開發&#xff0c;一直在用svn進行版本控制&#xff0c;如今更換了公司&#xff0c;使用的是git進行版本控制&#xff0c;所以打算記錄一下git學習的點滴&#xff0c;和大家一起分享。 百度百科&#xff1a; Git&#xff08;讀音為/g?t/&#xff09;是一個開源…

關于對async和await的初步理解

async 包裹著的函數中進程是堵塞的 &#xff0c;是同步化的&#xff0c; await等待的是個promise對象&#xff0c;否則"await" 對此表達式的類型沒有影響 例1 async getDataDD(){await this.fun1()await this.fun2()// await Promise.all([this.fun1(),this.fun…

MySQL—Keepalived+MySQL雙主復制實現MySQL高可用

Keepalived原理&#xff1a; Keepalived 的原理主要基于虛擬路由冗余協議&#xff08;VRRP&#xff0c;Virtual Router Redundancy Protocol&#xff09;、健康檢查機制和負載均衡機制&#xff0c;以下為你詳細介紹&#xff1a; VRRP 協議實現高可用&#xff1a;VRRP 是 Keep…

SpringBoot AOP 源碼解析

文章目錄 一、AOP 代碼示例1. 準備注解和目標類2. 定義 Aspect3. 結論 二、源碼1. AOP 實現核心類2. 代理類的創建流程2.1 核心類 AbstractAutoProxyCreator2.2 AbstractAutoProxyCreator#postProcessBeforeInstantiation2.3 AspectJAwareAdvisorAutoProxyCreator#shouldSkip2.…

Linux:Shell環境變量與命令行參數

目錄 Shell的變量功能 什么是變量 變數的可變性與方便性 影響bash環境操作的變量 腳本程序設計&#xff08;shell script&#xff09;的好幫手 變量的使用&#xff1a;echo 變量的使用&#xff1a;HOME 環境變量相關命令 獲取環境變量 環境變量和本地變量 命令行…

MySQL數據庫入門到大蛇尚硅谷宋紅康老師筆記 高級篇 part 5

第05章_存儲引擎 為了管理方便&#xff0c;人們把連接管理、查詢緩存、語法解析、查詢優化這些并不涉及真實數據存儲的功能劃分為MySQLserver的功能&#xff0c;把真實存取數據的功能劃分為存儲引擎的功能。所t以在MySQLserver完成了查詢優化后&#xff0c;只需按照生成的執行…

JAVA面試_進階部分_23種設計模式總結

1. 單例模式&#xff1a;確保某一個類只有一個實例&#xff0c;而且自行實例化并向整個系統提供這 個實例。 &#xff08;1&#xff09;懶漢式 public class Singleton { /* 持有私有靜態實例&#xff0c;防止被引用&#xff0c;此處賦值為null&#xff0c;目的是實現延遲加載…

滲透測試(WAF過濾information_schema庫的繞過,sqllib-46關,海洋cms9版本的注入)

1.sqlin-lib 46關 打開網站配置文件發現 此網站的對ID進行了排序&#xff0c;我們可以知道&#xff0c;order by接不了union &#xff0c;那我們可以通過測試sort&#xff0c;rond等函數&#xff0c;觀察網頁的反饋來判斷我們的盲注是否正確 我們發現 當參數有sort來排序時&…

AORO M6北斗短報文終端:將“太空黑科技”轉化為安全保障

在衛星導航領域&#xff0c;北斗系統作為我國自主研發的全球衛星導航系統&#xff0c;正以其獨特的短報文通信功能引發全球范圍內的廣泛關注。這一突破性技術不僅使北斗系統在全球四大導航系統中獨樹一幟&#xff0c;具備了雙向通信能力&#xff0c;更通過遨游通訊推出的AORO M…

ARCGIS國土超級工具集1.4更新說明

ARCGIS國土超級工具集V1.4版本&#xff0c;功能已增加至54 個。本次更新在V1.3版本的基礎上&#xff0c;新增了“拓撲問題修復工具”并同時調整了數據處理工具欄的布局、工具操作界面的選擇圖層下拉框新增可選擇位于圖層組內的要素圖層功能、數據保存路徑新增了可選擇數據庫內的…

Element Plus中el-select選擇器的下拉選項列表的樣式設置

el-select選擇器&#xff0c;默認樣式效果&#xff1a; 通過 * { margin: 0; padding: 0; } 去掉內外邊距后的樣式效果&#xff08;樣式變丑了&#xff09;&#xff1a; 通過 popper-class 自定義類名修改下拉選項列表樣式 el-select 標簽設置 popper-class"custom-se…

基于Linux系統的物聯網智能終端

背景 產品研發和項目研發有什么區別&#xff1f;一個令人發指的問題&#xff0c;剛開始工作時項目開發居多&#xff0c;認為項目開發和產品開發區別不大&#xff0c;待后來隨著自身能力的提升&#xff0c;逐步感到要開發一個好產品還是比較難的&#xff0c;我認為項目開發的目的…

java excel xlsx 增加數據驗證

隱藏表下拉框 // 創建隱藏工作表存儲下拉框數據String hiddenSheetName "HiddenSheet"System.currentTimeMillis();Sheet hiddenSheet workbook.createSheet(hiddenSheetName);//設置隱藏sheetworkbook.setSheetHidden(workbook.getSheetIndex(hiddenSheetName), …

linux中安裝部署Jenkins,成功構建springboot項目詳細教程

參考別人配置Jenkins的git地址為https&#xff0c;無法連上github拉取項目&#xff0c;所以本章節介紹通過配置SSH地址來連github拉取項目 目錄&#xff1a; 1、springboot項目 1.1 創建名為springcloudproject的springboot項目工程 1.2 已將工程上傳到github中&#xff0c;g…

提升數據洞察力:五款報表軟件助力企業智能決策

概述 隨著數據量的激增和企業對決策支持需求的提升&#xff0c;報表軟件已經成為現代企業管理中不可或缺的工具。這些軟件能夠幫助企業高效處理數據、生成報告&#xff0c;并將數據可視化&#xff0c;從而推動更智能的決策過程。 1. 山海鯨報表 概述&#xff1a; 山海鯨報表…

MySQL中replace函數用法

語法&#xff1a;replace(field,search,replace) 說明&#xff1a;field - 數據庫表的列名 search - 需要替換的字符串 replace - 替換成的字符串 語義&#xff1a;將列名&#xff1a;field 中出現的search字符串&#xff0c;全部替換成replace字符串。 例子&#xff1a; …

Wireshark Lua 插件教程

本?主要介紹 Lua 腳本在 Wireshark 中的應?, Lua 腳本可以在 Wireshark 中完成如下功能: 從?絡包中提取數據, 或者統計?些數據包(Dumper) 需要解析?種 Wireshark 不提供原??持的協議(Dissector) ?例 協議解析 VREP 協議是 NOGD 框架對于 TRIP 協議的?種延伸和擴展…

吐血整理:在 Docker 中運行 Milvus

直接用docker 錯誤命令&#xff08;這個我試了三遍&#xff0c;浪費了很多時間&#xff09;&#xff1a; docker run -d --name milvus -p 19530:19530 -p 9091:9091 -v /var/lib/milvus:/var/lib/milvus milvusdb/milvus:latest 先看報錯&#xff1a; 2025-02-24 16:02:39 …

【uniapp】在UniApp中實現持久化存儲:安卓--生成寫入數據為jsontxt

在移動應用開發中&#xff0c;數據存儲是一個至關重要的環節。對于使用UniApp開發的Android應用來說&#xff0c;緩存&#xff08;Cache&#xff09;是一種常見的數據存儲方式&#xff0c;它能夠提高應用的性能和用戶體驗。然而&#xff0c;緩存數據在用戶清除緩存或清除應用數…