本文共 5290 字,大约阅读时间需要 17 分钟。
1. 什么是 JNI JNI是Java Native Interface的缩写。从Java 1.1开始,JNI标准成为java平台的一部分,它允许Java和其他语言进行交互。JNI一开始为C和C++而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。使用java与本地已编译的代码交互,通常会丧失平台可移植性。但是,有些情况下这样做是可以接受的,甚至是必须的,比如,使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。关于 JNI 的用法很简单,有点像 java 里的 reflect 的工作机制,有兴趣的朋友可以参看Java 本地接口规范 2. Jni程序开发的一般操作步骤如下: (1) 编写带有native声明的方法的java类 (2) 使用javac 或 IDE(JBuilder,eclipse等)编译所编写的java类 (3) 使用javah -jni java类名生成扩展名为h的头文件p (4) 使用C++ 实现本地方法,对调用签名可用 javap –s –p [类全名] 查看(开发 C++ 动态链接库本例是用的 VC6) 注意要从 JDK下面的 include 文件夹中把 jni.h和 jni_md.h 两个文件 copy 到你的 VC 工程里 (5) 在 Java 中 load 动态链接库文件,调用 native 方法. 或者说将项目依赖的所有原生库和资源加入到java项目的java.library.path,生成java程序 3. 开发实例 (1). 编写 Java 类:package org.jm.jni; import java.util.ArrayList; public class BackgroundProcess { static { System.loadLibrary(“org_jm_jni_BackgroundProcess”); } // 三个 native 方法和一个 int 变量 public native boolean checkValid(); public native void processData(BackgroundProcess bg); public native void processGarbage(String[] bg); public int num = 5; // C++ 中可以调用的方法 public String backProcess(ArrayList p) { System.out.println(“这是 Java 里的方法,在 C++ 中调用。”); System.out.println(“这个方法,是 java 中 native checkValid 方法调用的。”); return “look up process ->” + p; } public static void main(String[] args) { String[] array = new String[4]; array[0] = “jack”; array[1] = “maggie”; array[2] = “rocket”; array[3] = “tom”; BackgroundProcess bgP = new BackgroundProcess(); // 调用 C++ DLL 中定义的方法。 bgP.checkValid();// 该方法回调 java 中的 backProcess 方法,即java::checkValid->c++::checkValid->java::backProcess bgP.processData(bgP); bgP.processGarbage(array); // C++ DLL 改变了该变量 System.out.println(“number 现在的值是: ” + bgP.num); } }2. 生成 C++ 的头文件(javah 命令生成,用javap –s –p [类全名] 命令查看java 方法签名) /* DO NOT EDIT THIS FILE – it is machine generated */ #include “jni.h” /* Header for class org_jm_jni_BackgroundProcess */ #ifndef _Included_org_jm_jni_BackgroundProcess #define _Included_org_jm_jni_BackgroundProcess #ifdef __cplusplus extern “C” { #endif /* * Class: org_jm_jni_BackgroundProcess * Method: checkValid * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_org_jm_jni_BackgroundProcess_checkValid (JNIEnv *, jobject); /* * Class: org_jm_jni_BackgroundProcess * Method: processData * Signature: (Lorg/jm/jni/BackgroundProcess;)V */ JNIEXPORT void JNICALL Java_org_jm_jni_BackgroundProcess_processData (JNIEnv *, jobject, jobject); /* * Class: org_jm_jni_BackgroundProcess * Method: processGarbage * Signature: ([Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_org_jm_jni_BackgroundProcess_processGarbage (JNIEnv *, jobject, jobjectArray); #ifdef __cplusplus } #endif #endif#include "org_jm_jni_BackgroundProcess.h" #include #include #include "string.h" char* jstringTostring(JNIEnv* env, jstring jstr) { char* rtn = NULL; jclass clsstring = env->FindClass("java/lang/String"); jstring strencode = env->NewStringUTF("utf-8"); jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr, mid, strencode); jsize alen = env->GetArrayLength(barr); jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE); if (alen > 0) { rtn = (char*)malloc(alen + 1); memcpy(rtn, ba, alen); rtn[alen] = 0; } env->ReleaseByteArrayElements(barr, ba, 0); return rtn; } //char* to jstring jstring stoJstring(JNIEnv* env, const char* pat) { jclass strClass = env->FindClass(“Ljava/lang/String;”); jmethodID ctorID = env->GetMethodID(strClass, ““, “([BLjava/lang/String;)V”); jbyteArray bytes = env->NewByteArray(strlen(pat)); env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat); jstring encoding = env->NewStringUTF(“utf-8″); return (jstring)env->NewObject(strClass, ctorID, bytes, encoding); } /* * Class: org_jm_jni_BackgroundProcess * Method: checkValid * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_org_jm_jni_BackgroundProcess_checkValid (JNIEnv *env, jobject obj){ jclass bgpClass=env->GetObjectClass(obj); jmethodID methodId=env->GetMethodID(bgpClass,”backProcess”,”(Ljava/util/ArrayList;)Ljava/lang/String;”); jobject str=env->CallObjectMethod(obj,methodId,NULL); jfieldID fieldId=env->GetFieldID(bgpClass,”num”,”I”); jint number=env->GetIntField(obj,fieldId); cout << "number 值是: " < env->SetIntField(obj,fieldId,100L); return 1; } /* * Class: org_jm_jni_BackgroundProcess * Method: processData * Signature: (Lorg/jm/jni/BackgroundProcess;)V */ JNIEXPORT void JNICALL Java_org_jm_jni_BackgroundProcess_processData (JNIEnv *env, jobject, jobject){ cout<< "this function do nothing " << endl; } /* * Class: org_jm_jni_BackgroundProcess * Method: processGarbage * Signature: ([Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_org_jm_jni_BackgroundProcess_processGarbage (JNIEnv *env, jobject, jobjectArray array){ jint size=env->GetArrayLength(array); cout << "数组大小是: " << size << endl; jstring tempObj=NULL; char *pszSTR1 = NULL; for(int i=0;i cout << "current value is : " << i << endl; tempObj=(jstring)env->GetObjectArrayElement(array,i); const char * chars =env->GetStringUTFChars(tempObj, 0); cout << chars << endl; } } |
转载地址:http://yavti.baihongyu.com/