Java 調用Native Method和Libary,就會丟失Java自己的一些屬性,比如誇平臺運行,除非你確認必須調用Native Method 和Library,否則儘量別用,我們通常這樣用的原因是之前我們寫了很多代碼,希望重用,或者是因爲執行速度的原因我們需要利用Native code去運行特定的功能。
1. 調用Native Method和Library的例子,
public class SimpleFile {
public static final char separatorChar='>';
protected String path;
protected int fd;
public SimpleFile(String path) {
// TODO Auto-generated constructor stub
this.path = path;
}
public String getFileName()
{
int index = path.lastIndexOf(separatorChar);
return index <0? path: path.substring(index +1);
}
public String getPath()
{
return this.path;
}
public native boolean open();
public native void close();
public native int read(byte[] buffer, int length);
public native int write(byte[] buffer, int length);
// run when the class is loaded first time.
static {
System.loadLibrary("Simple"); //simple.dll
}
}
然後正常調用SimpleFile中的open等方法,
SimpleFile sf = new SimpleFile(">some>path>and>filename");
sf.open();
byte[] buffer = new byte[1024];
sf.read(buffer, buffer.length);
fillBufferWithData(buffer, buffer.length);
sf.write(buffer, buffer.length);
sf.close();
2. 寫C代碼,
根據我們的定義,我們需要在DLL(Simple.dll)中實現如上native 函數(open, close, read 等等),那麼首先我們需要通過這個SimpleFile類去產生對應的頭文件,
2.1 利用Javah.exe去產生頭文件,
爲了生成對應的頭文件,我們需要先編譯源文件,比如本例中的SimpleFile.java,編譯爲SimpleFile.class, 然後利用javah + 類名(加上package名字)的形式產生對應的頭文件,
例如本例 javah MySubPackage/SimpleFile,則在目錄下會產生MySubPackage_SimpleFile.h,裏面會有如下具體的定義。
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class MySubPackage_SimpleFile */
#ifndef _Included_MySubPackage_SimpleFile
#define _Included_MySubPackage_SimpleFile
#ifdef __cplusplus
extern "C" {
#endif
#undef MySubPackage_SimpleFile_separatorChar
#define MySubPackage_SimpleFile_separatorChar 62L
/*
* Class: MySubPackage_SimpleFile
* Method: open
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_MySubPackage_SimpleFile_open
(JNIEnv *, jobject);
/*
* Class: MySubPackage_SimpleFile
* Method: close
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_MySubPackage_SimpleFile_close
(JNIEnv *, jobject);
/*
* Class: MySubPackage_SimpleFile
* Method: read
* Signature: ([BI)I
*/
JNIEXPORT jint JNICALL Java_MySubPackage_SimpleFile_read
(JNIEnv *, jobject, jbyteArray, jint);
/*
* Class: MySubPackage_SimpleFile
* Method: write
* Signature: ([BI)I
*/
JNIEXPORT jint JNICALL Java_MySubPackage_SimpleFile_write
(JNIEnv *, jobject, jbyteArray, jint);
#ifdef __cplusplus
}
#endif
#endif
通過分析上面頭文件的名字,就會發現命名格式Java_Package名字_類名_函數名。
2.2 編寫C代碼,
要按照頭文件中的函數聲明去編寫實現C代碼,
3,編譯Java代碼
在實現C代碼之後,編譯C代碼,產生dll(windows 下),將dll 放入對應的目錄下, Java程序在運行過程中去加載該dll(具體加載dll的方式有好幾種,將在後面學習).