JNI之C++调用Java类
Java类需要在虚拟机上运行,也就不是原生的,同样.NET Framework也不是原生的。JNI也就是Java原生接口。关于JNI的规范,以及为什么要使用它,它能做些什么,都在http://java.sun.com/j2se/1.4.2/docs/guide/jni/spec/jniTOC.html里记述着。
JNI是规范,它规定了虚拟机的接口,而把具体的实现留给开发者。
JVM的实现不是唯一的,目前存在很多种Java虚拟机,Sun Hotspot,IBM JDK,还有HP的,Kaffe等等。最流行的就是Sun的Hotspot,最复杂的就是IBM JDK,这是IBM的一贯作风。本文不讨论JVM的实现,只关注JNI。如果您安装了Sun的JDK,您就能在[JAVA_HOME]/include目录下找到jni.h。这个头文件就是虚拟机的唯一接口,你可以调用它声明的函数创建一个JVM。
在说明C++调用Java类之前,我想先演示一下如果编写Java Native Method。
1.编写带有Native方法的Java类
org.colimas.jni.test;public class JniTest{ static { System.loadLibrary("JniTestImpl"); } //JVM调用JniTestImpl.dll public JniTest(){ } //原生方法 public native void print(String str); /** *//** * @param args */ public static void main(String[] args){ JniTest test=new JniTest(); test.print("hello JVM"); //调用原生方法 }}
* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/**//* Header for class org_colimas_jni_test_JniTest */#ifndef _Included_org_colimas_jni_test_JniTest#define _Included_org_colimas_jni_test_JniTest#ifdef __cplusplusextern "C" {#endif/**//* * Class: org_colimas_jni_test_JniTest * Method: print * Signature: (Ljava/lang/String;)V */JNIEXPORT void JNICALL Java_org_colimas_jni_test_JniTest_print (JNIEnv *, jobject, jstring);#ifdef __cplusplus}#endif#endif
#include <jni.h>#include "org_colimas_jni_test_JniTest.h" //javah生成的头文件#include <stdio.h>JNIEXPORT void JNICALL Java_org_colimas_jni_test_JniTest_print (JNIEnv *env, jobject object,jstring str){ //获得字符串 const char * txt=(*env)->GetStringUTFChars(env,str,0); printf("%s ",txt); //打印到控制台 return;}
#include "jni.h"class Object{public: static bool BeginJVM(); static bool EndJVM(); Object(); virtual ~Object();protected: static JNIEnv* env; static JavaVM* jvm;};
#include "stdafx.h"#include "JavaClasses.h"#include "Object.h"Object::Object(){}Object::~Object(){}JNIEnv* Object::env=NULL;JavaVM* Object::jvm=NULL;//创建JVMbool Object::BeginJVM(){ JavaVMOption options[3]; JavaVMInitArgs vm_args; //各种参数 options[0].optionString="-Xmx128m"; options[1].optionString="-Verbose:gc"; options[2].optionString="-Djava.class.path=."; vm_args.version=JNI_VERSION_1_2; vm_args.options=options; vm_args.nOptions=3; //创建JVM,获得jvm和env int res = JNI_CreateJavaVM(&jvm,(void **)&env, &vm_args); return true;}bool Object::EndJVM(){ //关闭JVM jvm->DestroyJavaVM(); return true;}
String replaceAll(String regex, String replacement); boolean endsWith(String str); int indexOf(String str); int compareTo(String anotherString); char charAt(int i);
class String :public Object{public://与要调用的Java方法名一致。 const char * replaceAll(char *regex,char *replacement); bool endsWith(char * str); int indexOf(char * str); int compareTo(char *anotherString); char charAt(int i); String(char *str); virtual ~String();};
#include "stdafx.h"#include "String.h"#include "jni.h"using namespace std;jclass clazz; //全局变量,用来传递classjobject object; //全局变量,用来传递objectString::String(char *str){ jstring jstr; if (Object::env ==NULL)...{ cout << "JVM is not created" << endl; exit(-1); } //获得java.lang.String类 clazz=Object::env->FindClass("java/lang/String"); if (clazz ==0 )...{ cout << "Class is not found" << endl; exit(-1); } //获得String(String str)构造体 jmethodID mid= Object::env->GetMethodID(clazz,"<init>", "(Ljava/lang/String;)V"); if (mid==0)...{ cerr<< "GetMethodID Error for class" << endl; exit(-1); } //将字符串封装为jstring。 jstr = Object::env->NewStringUTF(str); if (jstr == 0) ...{ cerr << "Out of memory" <<endl; exit(-1); } cout << "invoking method" << endl; //创建一个java.lang.String对象。 object=Object::env->NewObject(clazz,mid,jstr);}String::~String(){}char String::charAt(int i){ if (Object::env ==NULL)...{ cout << "JVM is not created" << endl; exit(-1); } if (clazz ==0 )...{ cout << "Class is not found" << endl; exit(-1); } if (object ==0 )...{ cout << "String object is not created" << endl; exit(-1); } jmethodID mid; //获得charAt方法,(I)C表示 参数为int型,返回char型。详细参见JNI规范 mid = Object::env->GetMethodID(clazz,"charAt", "(I)C"); if (mid==0)...{ cerr<< "GetMethodID Error for class" << endl; exit(-1); } jint ji=i; cout << "invoking method" << endl; //调用charAt jchar z = Object::env->CallCharMethod(object,mid,i); //返回结果。 return z;}int String::compareTo(char *anotherString){ if (Object::env ==NULL)...{ cout << "JVM is not created" << endl; exit(-1); } if (clazz ==0 )...{ cout << "Class is not found" << endl; exit(-1); } if (object ==0 )...{ cout << "String object is not created" << endl; exit(-1); } jmethodID mid; //(Ljava/lang/String;)I表示参数为java.lang.String,返回int mid= Object::env->GetMethodID(clazz,"compareTo", "(Ljava/lang/String;)I"); if (mid==0)...{ cerr<< "GetMethodID Error for class" << endl; exit(-1); } jstring jstr = Object::env->NewStringUTF(anotherString); cout << "invoking method" << endl; //调用方法 jint z=Object::env->CallIntMethod(object,mid,jstr); //返回结果 return z;}int String::indexOf(char *str){ if (Object::env ==NULL)...{ cout << "JVM is not created" << endl; exit(-1); } if (clazz ==0 )...{ cout << "Class is not found" << endl; exit(-1); } if (object ==0 )...{ cout << "String object is not created" << endl; exit(-1); } jmethodID mid; mid= Object::env->GetMethodID(clazz,"indexOf", "(Ljava/lang/String;)I"); if (mid==0)...{ cerr<< "GetMethodID Error for class" << endl; exit(-1); } jstring jstr = Object::env->NewStringUTF(str); cout << "invoking method" << endl; jint z=Object::env->CallIntMethod(object,mid,jstr); return z;}bool String::endsWith(char *str){ if (Object::env ==NULL)...{ cout << "JVM is not created" << endl; exit(-1); } if (clazz ==0 )...{ cout << "Class is not found" << endl; exit(-1); } if (object ==0 )...{ cout << "String object is not created" << endl; exit(-1); } jmethodID mid; mid= Object::env->GetMethodID(clazz,"endsWith", "(Ljava/lang/String;)Z"); if (mid==0)...{ cerr<< "GetMethodID Error for class" << endl; exit(-1); } jstring jstr = Object::env->NewStringUTF(str); cout << "invoking method" << endl; bool z = Object::env->CallBooleanMethod(object,mid,jstr); return z;}const char * String::replaceAll(char *regex, char *replacement){ if (Object::env ==NULL)...{ cout << "JVM is not created" << endl; exit(-1); } if (clazz ==0 )...{ cout << "Class is not found" << endl; exit(-1); } if (object ==0 )...{ cout << "String object is not created" << endl; exit(-1); } jmethodID mid; mid= Object::env->GetMethodID(clazz,"replaceAll", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); if (mid==0)...{ cerr<< "GetMethodID Error for class" << endl; exit(-1); } jvalue array[2]; jstring jreg = Object::env->NewStringUTF(regex); jstring jstr = Object::env->NewStringUTF(replacement); array[0].l=jreg; array[1].l=jstr; cout << "invoking method" << endl; //传入参数,调用replaceAll方法 jobject z=Object::env->CallObjectMethodA(object,mid,array); const char *result=Object::env->GetStringUTFChars((jstring)z, 0); return (const char *)result;}
using namespace std;int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]){ int nRetCode = 0; if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)){ cerr << _T("Fatal Error: MFC initialization failed") << endl; nRetCode = 1; } else...{ //创建JVM Object::BeginJVM(); String test("hello"); //调用replaceAll const char *result = test.replaceAll("l","z"); //返回结果 cout<< result <<endl; //关闭JVM Object::EndJVM(); } return nRetCode;}