日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

c调用其他类的方法_Java 的 Native 方法——今天又进步了

發布時間:2025/3/19 java 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c调用其他类的方法_Java 的 Native 方法——今天又进步了 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 簡介

1.1 個人理解

初次遇見 native 是在 java.lang.String 源碼中的一個 intern 方法:

public?native?String?intern();

因為還是第一次遇到,所以就去搜了一些文章進行了解。下面就對一些 Native 關鍵字進行一些總結。

native 也即 JNI —— Java Native Interface(Java 本地接口)。凡是一種語言,都希望是純的。比如解決某一個方案就單單使用同一個語言來實現。而 Java 卻不然,Java 平臺有個用戶和本地 C 代碼進行相互操作的 API,稱為 Java Native Interface (Java 本地接口)。也就是說,相當于使用 Java 語言聲明了一個方法,而這個方法的具體實現是在其他語言(如 C、C++等)中實現的,所以 Java 中編寫的也就類似于一個接口,只是這個接口被稱作本地接口。

Java 使用本地接口也是有原因的,因為 Java 的平臺無關性,有優勢當然也有犧牲,它的缺點就是不能使用 Java 代碼直接對一些底層進行操作,但是對底層的操作又是一個語言必不可少的,于是 Java 就想到了間接去操作底層,而中間利用的就是操作系統。所以有些方法,Java 聲明為了 native ,具體的實現是在 DLL 中,JVM 去進行真正的操作。

「簡單記憶:native 方法是 Java 中聲明,由操作系統中具體方法實現。」

1.2 其他介紹

網友見解:

  • native 是與 C++ 聯合開發的時候用的!java 自己開發不用的!
  • 使用 native 關鍵字說明這個方法是「原生函數」,也就是這個方法是用 C/C++ 語言實現的,并且被編譯成了 DLL,由 Java去調用。這些函數的實現體在 DLL 中,JDK 的源代碼中并不包含,你應該是看不到的。對于不同的平臺它們也是不同的。這也是 Java 的底層機制,實際上 Java 就是在不同的平臺上調用不同的 native 方法實現對操作系統的訪問的。
  • native 是用做 java 和其他語言(如c++)進行協作時用的也就是 native 后的函數的實現不是用 Java 寫的,既然都不是 Java,那就別管它的源代碼了,呵呵。
  • native 的意思就是通知操作系統,這個函數你必須給我實現,因為我要使用。所以 native 關鍵字的函數都是操作系統實現的,Java 只能調用。
  • Java 是跨平臺的語言,既然是跨了平臺,所付出的代價就是犧牲一些對底層的控制,而 Java 要實現對底層的控制,就需要一些其他語言的幫助,這個就是 native 的作用了
  • Java 不是完美的,Java 的不足除了體現在運行速度上要比傳統的 C++ 慢許多之外,Java 無法直接訪問到操作系統底層(如系統硬件等),為此 Java 使用 native 方法來擴展 Java 程序的功能。

Java 本地方法適用的情況:

  • 為了使用底層的主機平臺的某個特性,而這個特性不能通過 Java API 訪問;
  • 為了訪問一個老的系統或者使用一個已有的庫,而這個系統或這個庫不是用 Java 編寫的;
  • 為了加快程序的性能,而將一段時間敏感的代碼作為本地方法實現。
  • 2. 用 Java 調用 C 的實例

    為了更好的理解 Java 中調用 Native 方法,特來編寫一個具體的小的測試。

    以下所有文件都存于個人本地文件夾:C:\Users\Eric\Desktop\NativeTest。

    2.1 創建包含本地方法的類

    在文件夾下創建一個 HelloNative.java 文件,里面包含著一個 native 的方法和加載庫的方法 loadLibrary。代碼如下:

    public?class?HelloNative?{
    ????static?{
    ????????//?注意加載庫的名字為?HelloNative,需要與下文的生成文件保持一致
    ????????System.loadLibrary("HelloNative");
    ????}
    ?????
    ????public?static?native?void?sayHello();
    ?????
    ????@SuppressWarnings("static-access")
    ????public?static?void?main(String[]?args)?{
    ????????new?HelloNative().sayHello();
    ????}
    }

    首先注意的是 native 方法,然后那個加載庫的靜態代碼塊在后面也起作用。native 關鍵字告訴編譯器(其實是 JVM)調用的是該方法在外部定義,這里指的是 C。

    2.2 編譯運行

    在當前文件夾下使用 CMD 命令行編譯 HelloNative.java,如下。

    如果當前類中沒有 Native 方法,那么我們可以直接使用 java 命令直接運行,但是此時大家直接運行這個代碼,會出現以下結果:

    意思是虛擬機說不知道如何找到 sayHello。因為我們定義的 sayHello 方法為 native 類型,所以我們還需要再進行下文的操作步驟。

    2.3 獲得頭文件

    在當前文件目錄下運行 javah,得到包含該方法的 C 聲明頭文件 。命令如下:

    javah HelloNative # 生成 .h文件

    得到的結果如下:

    得到的 HelloNative.h 文件,內容如下:

    /*?DO?NOT?EDIT?THIS?FILE?-?it?is?machine?generated?*/
    #include?
    /*?Header?for?class?HelloNative?*/
    ?
    #ifndef?_Included_HelloNative
    #define?_Included_HelloNative
    #ifdef?__cplusplus
    extern?"C"?{
    #endif
    /*
    ?*?Class:?????HelloNative
    ?*?Method:????sayHello
    ?*?Signature:?()V
    ?*/
    JNIEXPORT?void?JNICALL?Java_HelloNative_sayHello(JNIEnv?*,?jclass);
    ?
    #ifdef?__cplusplus
    }
    #endif
    #endif

    這個頭文件中可以看見我們聲明的 Java 本地化 sayHello 方法,對應 C 的聲明:JNIEXPORT void JNICALL Java_HelloNative_sayHello(JNIEnv *, jclass);,我們只要實現這個方法即可。

    注意:頭文件中 jni.h 這個文件,是在本地 JDK 目錄下的 include 文件夾中,例如我的目錄:

    2.3 C 實現頭文件的聲明方法

    生成了頭文件之后,我們再在當前文件夾下創建一個 HelloNative.c 文件,并簡單地實現 HelloNative.h 文件中聲明的 sayHello 方法,代碼如下:

    //?包含剛才生成的.h文件
    #include?"HelloNative.h"
    #include?

    JNIEXPORT?void?JNICALL?Java_HelloNative_sayHello(JNIEnv?*env,?jclass?thisClass)?{
    ????printf("Hello,?Native!!");
    }

    結果:

    2.4 生成動態鏈接庫

    到了這一步,我們需要將上述兩個文件 HelloNative.c 和 HelloNative.h 編譯為動態鏈接庫。

    這里說明「兩種」方法:分步編譯或一次性編譯形成動態鏈接庫文件。

    「(1)一次性編譯」

    在 Windows CMD 命令行里,使用如下命令:

    gcc -m64 -Wl,--add-stdcall-alias -I"C:/Program Files/Java/jdk1.8.0_181/include" -I"C:/Program Files/Java/jdk1.8.0_181/include/win32" -shared -o HelloNative.dll HelloNative.c

    注意:上述 JDK 為個人本地路徑,需要根據個人情況進行修改。-m64 表示生成 dll 庫是 64 位的,參數 -I 指定頭文件路徑上述命令運行后,我們會在目錄文件夾下生成相應的動態鏈接庫文件,如下:

    ?

    如果使用的 Windows 上面沒有 gcc,需要先下載壓縮包然后配置一下環境變量即可使用(兩分鐘就搞定),壓縮包及配置步驟,這里推薦一條有關的配置博文:https://blog.csdn.net/jbk3311/article/details/103886095

    ?

    「(2)分步編譯」

    為了演示分步編譯,我們先把上面一次性編譯生成的動態鏈接庫文件 HelloNative.dll 給刪除掉。然后再執行如下命令:

    $ gcc -c -I"C:/Program Files/Java/jdk1.8.0_181/include" -I"C:/Program Files/Java/jdk1.8.0_181/include/win32" HelloNative.c HelloNative.h

    結果如下:

    在這里我們只需要先關注生成的 HelloNative.o 文件,然后我們執行第二步驟的命令,將該文件編譯為 dll 文件:

    $ gcc -Wl,--add-stdcall-alias -shared -o HelloNative.dll HelloNative.o

    結果如下:

    2.5 再次運行Java類

    使用 2.4 中的任意一種方法生成動態鏈接庫 HelloNative.dll 文件后,我們再次使用 java 命令運行 Java 類,結果如下:

    我們可以看到 Java 類已經可以成功運行了,并且我們也可以看出它運行的實際是我們使用 C 語言編寫的實現方法,它作為本地方法 native 來被 Java 代碼調用。

    2.6 總結

    可以將 native 方法比作 Java 程序同C程序的接口,其實現步驟:

  • 在 Java 中聲明 native 方法,然后編譯成 .class 文件;
  • 用 javah 產生一個 .h 文件;
  • 寫一個 .c 或 .cpp 文件實現 native 導出方法,其中需要包含第二步產生的 .h 文件(注意其中又包含了JDK帶的jni.h文件);
  • 將第三步的 .c 或 .cpp 文件編譯成動態鏈接庫文件;
  • 在 Java 中用 System.loadLibrary() 方法加載第四步產生的動態鏈接庫文件,這個 native 方法就可以在 Java 中被訪問了。
  • 「JNI 調用 C 流程圖」

    「參考文章」

    • Java native方法:https://www.jianshu.com/p/1eb6d859175d
    • Java Programming TutorialJava Native Interface (JNI):https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html
    • Java的native方法是什么:https://blog.csdn.net/qq_29229567/article/details/80695742?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~all~first_rank_v2~rank_v25-4-80695742.nonecase

    我是阿數,葛立恒數的數,我們下期再見。

    「分享、點贊、在看」

    總結

    以上是生活随笔為你收集整理的c调用其他类的方法_Java 的 Native 方法——今天又进步了的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。