java native 例子_Java native方法以及JNI实践
前言
今天看AndFix實現(xiàn)時,核心方法之ReplaceMethod方法是一個native方法,之前并沒有遇到過,所以在此整理記錄。
native的作用
總而言之:native是與C++聯(lián)合開發(fā)的時候用的!使用native關鍵字說明這個方法是原生函數(shù),也就是這個方法是用C/C++語言實現(xiàn)的,并且被編譯成了DLL,由java去調(diào)用。
native 是用做java 和其他語言(如c++)進行協(xié)作時使用的,也就是native 后的函數(shù)的實現(xiàn)不是用java寫的。
既然都不是java,那就別管它的源代碼了,我們只需要知道這個方法已經(jīng)被實現(xiàn)即可。
native的意思就是通知操作系統(tǒng), 這個函數(shù)你必須給我實現(xiàn),因為我要使用。 所以native關鍵字的函數(shù)都是操作系統(tǒng)實現(xiàn)的, java只能調(diào)用。
java是跨平臺的語言,既然是跨了平臺,所付出的代價就是犧牲一些對底層的控制,而java要實現(xiàn)對底層的控制,就需要一些其他語言的幫助,這個就是native的作用了
JNI簡介
native方法是通過java中的JNI實現(xiàn)的。JNI是Java Native Interface的 縮寫。從Java 1.1開始,Java Native Interface (JNI)標準成為java平臺的一部分,它允許Java代碼和其他語言寫的代碼進行交互。
JNI一開始是為了本地已編譯語言,尤其是C和C++而設計 的,但是它并不妨礙你使用其他語言,只要調(diào)用約定受支持就可以了。
目前java與dll交互的技術主要有3種:jni,jawin和jacob。
目前功能性而言:jni >> jawin > jacob,其大致的結構如下圖:
jni_jawin_jacob
windows,基于native的PE結構,windows的jvm基于native結構,Java的應用體系構建于jvm之上。jvm通過加載此jni程序間接調(diào)用目標原生函數(shù)。
image
JNI的生成步驟——Mac版
編寫帶有native聲明的方法的java類,生成.java文件
使用javac命令編譯所編寫的java類,生成.class文件
使用javah -jni java類名生成擴展名為h的頭文件,也即生成.h文件
使用C/C++(或者其他編程想語言)實現(xiàn)本地方法,創(chuàng)建.h文件的實現(xiàn),也就是創(chuàng)建.cpp文件實現(xiàn).h文件中的方法
將C/C++編寫的文件生成動態(tài)連接庫,生成jnilib文件
JNI實例
接下來我們按照上述步驟一個一個來生成JNI實例
1.編寫帶有native聲明的java類,HelloWorld.java
public class HelloWorld {
public native void sayHelloWorld(); //申明一個native方法
static{
System.loadLibrary("HelloWorldImpl"); //裝入動態(tài)鏈接庫,"HelloWorldImpl"是裝入動態(tài)鏈接庫的名稱
}
public static void main(String[] args){
HelloWorld helloWorld = new HelloWorld();
helloWorld.sayHelloWorld();
}
}
2.使用javac生成HelloWorld.class
javac HelloWorld.java
3.使用javah -jni java類生成擴展名為h的頭文件
javah -jni HelloWorld
此處需要注意的是,我們應該在包名的根目錄下執(zhí)行,因為生成的文件的文件名需要引用包目錄。不然就會報找不到類文件的錯誤
生成com_think_jni_HelloWorld.h文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class com_think_jni_HelloWorld */
#ifndef _Included_com_think_jni_HelloWorld
#define _Included_com_think_jni_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_think_jni_HelloWorld
* Method: displayHelloWorld
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_think_jni_HelloWorld_displayHelloWorld
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
這里我們可以這樣理解:這個h文件相當于我們在java里面的接口,這里聲明了一個 Java_HelloWorld_displayHelloWorld (JNIEnv *, jobject);方法,然后在我們的本地方法里面實現(xiàn)這個方法,也就是說我們在編寫C/C++程序的時候所使用的方法名必須和這里的一致
4使用C/C++實現(xiàn)本地方法
創(chuàng)建HelloWorldImpl.cpp,代碼如下所示:
#include "jni.h"
#include "com_think_jni_HelloWorld.h"
#include
JNIEXPORT void JNICALL Java_com_think_jni_HelloWorld_displayHelloWorld(JNIEnv *env,jobject obj){
printf("Hello World!\n");
return;
}
5 將本地方法編寫的文件生成動態(tài)鏈接庫
gcc -I/Library/Java/JavaVirtualMachines/[根據(jù)裝的jdk版本來定]/Contents/Home/include/ -dynamiclib HelloWorldImpl.cpp -o libhell.jnilib
但是會出現(xiàn)運行這個命令報錯
file not found
我們找到這個文件在
/Library/Java/JavaVirtualMachines/[根據(jù)安裝的jdk版本來定]/Contents/Home/include/darwin/
這個目錄下,所以我們再鏈接該目錄到以上命令中
gcc -I/Library/Java/JavaVirtualMachines/jdk1.8.0_71.jdk/Contents/Home/include/ -I/Library/Java/JavaVirtualMachines/jdk1.8.0_71
.jdk/Contents/Home/include/darwin/ -dynamiclib HelloWorldImpl.cpp -o libhell.jnilib
最終成功生成libhell.jnilib
6 運行可執(zhí)行文件
把上述文件放在同一個文件夾后,執(zhí)行
java HelloWorld
即可看到
image
總結
以上是生活随笔為你收集整理的java native 例子_Java native方法以及JNI实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java print int_java
- 下一篇: java 2d 绘图教程_Java标准教