1、什麼是JNI?
一種讓Java調用其他語言的技術。
本博文將會介紹JNI 調用C++的技術。
有關於此教程的所有代碼下載。
------------------------------------------分割線------------------------------------------
免費下載地址在 http://linux.linuxidc.com/
用戶名與密碼都是www.linuxidc.com
具體下載目錄在 /2014年資料/10月/9日/Ubuntu仿Mac主題:SnowBird
下載方法見 http://www.linuxidc.com/Linux/2013-07/87684.htm
------------------------------------------分割線------------------------------------------
2、JNI 之 HelloWorld in JAVA
HelloWorld.java:
package com.hello;
public class HelloWorld {
public native void hello(String name);
public HelloWorld(){
}
static {
System.loadLibrary( "HelloWorld" );
}
}
注意下,如果我們用JNI編出的文件叫: HelloWorld.dll ,那麼System.loadLibrary("HelloWorld"),不用加“.dll”。
TestHelloWorld.java:
package com.hello;
public class TestHelloWorld {
public static void main(String[] args) {
HelloWorld helloWorld = new HelloWorld();
helloWorld.hello("emaster");
}
}
編譯一下,生成兩個class文件。
至此,java方面的代碼就完事了。
在開始之前,我推薦大家用VC++6.0,而不是CodeBlocks來編寫C++方面的代碼!
理由如下:
這是CodeBlocks生成的DLL的導出函數:
_Z44Java_com_regMonitor_RegMonitor_jniRegMonitorP7JNIEnv_P8_jobject@8
這是VC生成的DLL的導出函數:
發現沒有?CB生成的DLL導出函數多了一些:_Z44啊,P7JNIEnv_P8_jobject之類的。
導出函數多一些東西之後,會導致我們在Java中找不到對應的函數。
哎,也可能是我 CB沒有調整好編譯命令吧。總之我在VC下成功了。
Ps:
DLL查看導出函數器下載見本文上面的Linux公社資源下載。
4、javah生成C++用的頭文件
我的工作目錄如下:
D:\pub\workspace\JNIHelloWorld\src\com\hello 的目錄
2014-05-14 18:04 <DIR> .
2014-05-14 18:04 <DIR> ..
2014-05-14 18:04 218 HelloWorld.java
2014-05-14 18:04 207 TestHelloWorld.java
在com.hello下有上面提到的兩個java文件。(請注意,之前已經編譯過java文件,所以bin文件夾下有類文件!)
請注意我生成頭文件的目錄和命令:
D:\pub\workspace\JNIHelloWorld\bin>javah com.hello.HelloWorld
D:\pub\workspace\JNIHelloWorld\bin>dir
2014-05-14 18:21 <DIR> .
2014-05-14 18:21 <DIR> ..
2014-05-14 18:04 <DIR> com
2014-05-14 18:21 475 com_hello_HelloWorld.h
看到沒有,生成了一個頭文件:com_hello_HelloWorld.h。
如果目錄不對,很可能報錯如下:
錯誤:無法訪問 HelloWorld
錯誤的類文件: D:\pub\workspace\JNIHelloWorld\bin\com\hello\HelloWorld.class
類文件包含錯誤的類: com.hello.HelloWorld
請刪除該文件或確保該文件位於正確的類路徑子目錄中。
com.sun.tools.javac.util.Abort
at com.sun.tools.javac.comp.Check.completionError(Check.java:162)
at com.sun.tools.javadoc.DocEnv.loadClass(DocEnv.java:147)
at com.sun.tools.javadoc.RootDocImpl.<init>(RootDocImpl.java:77)
at com.sun.tools.javadoc.JavadocTool.getRootDocImpl(JavadocTool.java:159
)
at com.sun.tools.javadoc.Start.parseAndExecute(Start.java:330)
at com.sun.tools.javadoc.Start.begin(Start.java:128)
at com.sun.tools.javadoc.Main.execute(Main.java:66)
at com.sun.tools.javah.Main.main(Main.java:147)
javadoc: 錯誤 - 致命錯誤
2 錯誤
VC新建項目,選擇Win32 Dynamic-Link Library項目(生成DLL的),默認即可。
我的項目名字為:JNIHelloWorld。
把第4步的頭文件:com_hello_HelloWorld.h 放到VC中。
修改下輸出DLL的名字:VC菜單 -> 工程 -> 設置 -> 連接 -> 輸出文件名 這一欄,改成:Debug/HelloWorld.dll
這樣子就和Java代碼中的dll名字一樣了,其實可以手動F2修改的,這裡設置後就不能每次都去修改了,懶人。
5.4、步驟4
把HelloWorld.dll放到Java項目的根目錄下,我這裡是根目錄是:
D:\pub\workspace\JNIHelloWorld
所以該dll的路徑是:
配置jni頭文件,不然C++會報錯找不到該頭文件:
就是到jdk的安裝目錄下include下把以下相應的文件,復制到vc目錄下的include文件夾下:
\jdk\include\jni.h
\jdk\include\win32\jawt_md.h
\jdk\include\win32\jni_md.h
上面主是jdk安裝目錄下的三個文件,分別復制它們到vc目錄下的include文件夾下。如我的安裝位置是:
D:\Program Files\Microsoft Visual Studio\VC98\Include
你們可以根據自己的安裝位置自行確定。
代碼如下:
com_hello_HelloWorld.h:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_hello_HelloWorld */
#ifndef _Included_com_hello_HelloWorld
#define _Included_com_hello_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_hello_HelloWorld
* Method: hello
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_hello_HelloWorld_hello
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
JNIHelloWorld.cpp:
// JNIHelloWorld.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include "com_hello_HelloWorld.h"
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
return TRUE;
}
JNIEXPORT void JNICALL Java_com_hello_HelloWorld_hello
(JNIEnv *, jobject, jstring)
{
printf("I am in C++!\n");
return;
}
可以看到,我們在Java中,調用C++的方法成功!
至此,一個完整的HelloWorld版本的JNI過程,就完成了。
Tiny6410內核模塊編譯之HelloWorld http://www.linuxidc.com/Linux/2013-12/93634.htm
HelloWorld之Hibernate版 http://www.linuxidc.com/Linux/2014-04/99294.htm
在Ubuntu上編寫Qt HelloWorld程序 http://www.linuxidc.com/Linux/2014-06/103671.htm
Tiny6410內核模塊編譯之HelloWorld http://www.linuxidc.com/Linux/2013-12/93634.htm
用Pthreads進行共享內存編程----HelloWorld http://www.linuxidc.com/Linux/2013-04/83103.htm
Hadoop實例之HelloWorld http://www.linuxidc.com/Linux/2012-12/75406.htm
Qt Creator for PlayBook上的HelloWorld (Windows版) http://www.linuxidc.com/Linux/2012-05/60653.htm
Tiny6410 簡單的交叉編譯helloworld http://www.linuxidc.com/Linux/2012-03/56732.htm