首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JNI (Java Native Interface) 標準原理深度解析:從 Java 呼叫 C++ 動態庫完整實作流程

     編輯:Java 相關知識

JNI 簡介

JNI (Java Native Interface) 是 Java 平台標準功能,彌補「跨平台」與「平台特有功能」間的鴻溝。讓 Java 應用在跨平台優勢下,仍能呼叫 C/C++ 動態庫(.so/.dll),發揮原生效能或存取硬體/系統 API。

知識架構圖

完整實作範例(Ubuntu 10.04 LTS 環境)

1. Java 類別宣告 native 方法

package com.magc.jni;

public class HelloWorld {
    static {
        System.loadLibrary("Hello"); // 載入 libHello.so
    }
    public native void DisplayHello(); // 原生方法宣告

    public static void main(String[] args) {
        new HelloWorld().DisplayHello();
    }
}

2. 編譯 Java 類別

javac ./com/magc/jni/HelloWorld.java

產生 HelloWorld.class。

3. 產生 C/C++ 標頭檔

javah -jni com.magc.jni.HelloWorld

產生 com_magc_jni_HelloWorld.h:

/* DO NOT EDIT - machine generated */
#include 
#ifndef _Included_com_magc_jni_HelloWorld
#define _Included_com_magc_jni_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL Java_com_magc_jni_HelloWorld_DisplayHello
  (JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif

關鍵點:

  • 函數命名規則:Java_包名_類別名_方法名(點號換底線)。
  • JNIEnv* 提供 JNI 函數表指標,jobject 對應 Java 這個實例。
  • 標頭檔無需編譯,直接被 C++ 實作檔 #include。

4. C++ 實作原生方法

#include 
#include "com_magc_jni_HelloWorld.h"
#include 

JNIEXPORT void JNICALL Java_com_magc_jni_HelloWorld_DisplayHello
  (JNIEnv *env, jobject obj) {
    printf("From jni_helloworldImpl.cpp :");
    printf("Hello world ! \n");
    return;
}

方法名稱、簽名必須與標頭檔完全一致。

5. 編譯動態庫

g++ -shared -I /usr/lib/jvm/java-6-openjdk/include \
    jni_helloworldImpl.cpp -o libHello.so

產生 libHello.so(Linux 慣例 lib 前綴 + 類別庫名)。

6. 執行 Java 程式

java -Djava.library.path=. com.magc.jni.HelloWorld

輸出:

From jni_helloworldImpl.cpp :Hello world !

關鍵總結

  • System.loadLibrary("Hello") 會依平台尋找 libHello.so (Linux) 或 Hello.dll (Windows)。
  • -Djava.library.path 指定動態庫搜尋路徑。
  • JNI 讓 Java 保有跨平台架構,同時整合原生高效能/系統級能力。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved