Việc tích hợp mã C++ vào ứng dụng Java thông qua Java Native Interface (JNI) là một kỹ thuật thiết yếu khi cần khai thác hiệu năng cao hoặc tận dụng thư viện gốc đã tồn tại. Quy trình này yêu cầu sự phối hợp chặt chẽ giữa lớp Java khai báo hàm native và triển khai tương ứng bằng C++, cùng với các bước biên dịch và liên kết phù hợp.
1. Định nghĩa lớp Java với phương thức native
Tạo một lớp Java chứa các phương thức được đánh dấu native, đồng thời tải thư viện chia sẻ tại khối static.
public class HybridBridge {
public native void greetUser();
public native long computeFactorial(int n);
static {
System.loadLibrary("hybrid_bridge"); // Tải libhybrid_bridge.so (Linux/macOS) hoặc hybrid_bridge.dll (Windows)
}
public static void main(String[] args) {
HybridBridge bridge = new HybridBridge();
bridge.greetUser();
System.out.println("5! = " + bridge.computeFactorial(5));
}
}
2. Sinh tệp tiêu đề C++ từ bytecode
Sử dụng công cụ javac -h để tạo header tự động, đảm bảo tính tương thích về chữ ký hàm:
javac -h . HybridBridge.java
Tệp HybridBridge.h sinh ra sẽ chứa các khai báo như sau:
#include <jni.h>
#ifndef _Included_HybridBridge
#define _Included_HybridBridge
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL Java_HybridBridge_greetUser(JNIEnv *, jobject);
JNIEXPORT jlong JNICALL Java_HybridBridge_computeFactorial(JNIEnv *, jobject, jint);
#ifdef __cplusplus
}
#endif
#endif
3. Triển khai logic C++
Thực hiện các hàm trong tệp .cpp, tuân thủ quy ước đặt tên do JNI quy định và xử lý đúng kiểu dữ liệu:
#include "HybridBridge.h"
#include <iostream>
#include <cstdint>
JNIEXPORT void JNICALL Java_HybridBridge_greetUser(JNIEnv *env, jobject instance) {
std::cout << "[C++] Chào mừng đến với mô-đun gốc!\n";
}
JNIEXPORT jlong JNICALL Java_HybridBridge_computeFactorial(JNIEnv *env, jobject instance, jint n) {
if (n < 0) return -1L;
jlong result = 1L;
for (jint i = 2; i <= n; ++i) {
result *= i;
}
return result;
}
4. Biên dịch thành thư viện chia sẻ
Trên Linux/macOS:
g++ -shared -fPIC \
-I"$JAVA_HOME/include" \
-I"$JAVA_HOME/include/linux" \
HybridBridge.cpp -o libhybrid_bridge.so
Trên Windows (dùng MinGW):
g++ -shared \
-I"%JAVA_HOME%\include" \
-I"%JAVA_HOME%\include\win32" \
HybridBridge.cpp -o hybrid_bridge.dll
Lưu ý: Trên Windows, có thể cần thêm cờ
-Wl,--add-stdcall-aliasnếu sử dụng Visual Studio hoặc gặp lỗi liên quan đến calling convention.
5. Chạy ứng dụng Java
Đảm bảo thư viện nằm trong đường dẫn được chỉ định bởi -Djava.library.path:
java -Djava.library.path=. HybridBridge
Kết quả đầu ra mong đợi:
[C++] Chào mừng đến với mô-đun gốc!
5! = 120
Những điểm then chốt cần lưu ý
- Quy tắc đặt tên hàm: Hàm C++ phải bắt đầu bằng
Java_, theo sau là tên đầy đủ lớp (thay dấu.bằng_), rồi tới tên phương thức — ví dụ:Java_org_example_HybridBridge_greetUser. - Chuyển đổi chuỗi: Khi làm việc với
jstring, luôn dùngGetStringUTFChars()vàReleaseStringUTFChars()để tránh rò rỉ bộ nhớ. - Xử lý ngoại lệ: Gọi
env->ExceptionCheck()sau mỗi thao tác nhạy cảm, và dùngenv->ExceptionDescribe()để gỡ lỗi nếu có ngoại lệ chưa được xử lý. - Quản lý tham chiếu đối tượng: Tránh giữ
jobjectvượt ngoài phạm vi gọi — nếu cần, tạoGlobalRefvà giải phóng rõ ràng bằngDeleteGlobalRef. - Tương thích kiểu dữ liệu:
jlong↔int64_t,jboolean↔uint8_t,jdouble↔double.
Ví dụ nâng cao: Truyền và xử lý mảng số nguyên
Java:
public native int[] multiplyElements(int[] input, int factor);
C++:
JNIEXPORT jintArray JNICALL Java_HybridBridge_multiplyElements(
JNIEnv *env, jobject obj, jintArray input, jint factor) {
jsize length = env->GetArrayLength(input);
jint *elements = env->GetIntArrayElements(input, nullptr);
jintArray result = env->NewIntArray(length);
jint *output = new jint[length];
for (jsize i = 0; i < length; ++i) {
output[i] = elements[i] * factor;
}
env->SetIntArrayRegion(result, 0, length, output);
env->ReleaseIntArrayElements(input, elements, JNI_ABORT);
delete[] output;
return result;
}
Phương pháp này đặc biệt hữu ích trong các bài toán đòi hỏi xử lý nặng như xử lý tín hiệu, mô phỏng vật lý hoặc truy cập phần cứng trực tiếp — nơi Java thuần túy không đáp ứng đủ yêu cầu về hiệu năng hoặc khả năng kiểm soát hệ thống.