1, Java app code :
package test.sample.jni.run;
public class Sample {
static int staticint = 0;
String strField="default";
int intField=0;
public native int intMethod(int n);
public native boolean booleanMethod(boolean bool);
public native String stringMethod(String text);
public native int intArrayMethod(int[] intArray);
public native boolean callJavaMethod(String text);
public String callmethod(String c,int a){
String s = "intput value is "+String.valueOf(a)+":"+c;
System.out.println(s);
return s;
}
public void perf()
{
System.out.println(this.intMethod(5));
boolean bool = this.booleanMethod(true);
this.callJavaMethod("abc");
for(int i=0 ; i<10000;i++)
//System.out.println(this.stringMethod("Java"));
this.callJavaMethod("abc");
int sum = this.intArrayMethod(new int[]{1,2,3,4});
System.out.println(this.strField+":"+this.intField);
}
/**
* @param args
*/
public static void main(String[] args) {
System.loadLibrary("sample");
for(int j= 0 ; j < 10; j++){
new Sample().perf();
}
}
}
2. Native library header file
javah test.sample.jni.run.Sample at bin folder. there will be following .h generated:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class test_sample_jni_run_Sample */
#ifndef _Included_test_sample_jni_run_Sample
#define _Included_test_sample_jni_run_Sample
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: test_sample_jni_run_Sample
* Method: intMethod
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_test_sample_jni_run_Sample_intMethod
(JNIEnv *, jobject, jint);
/*
* Class: test_sample_jni_run_Sample
* Method: booleanMethod
* Signature: (Z)Z
*/
JNIEXPORT jboolean JNICALL Java_test_sample_jni_run_Sample_booleanMethod
(JNIEnv *, jobject, jboolean);
/*
* Class: test_sample_jni_run_Sample
* Method: stringMethod
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_test_sample_jni_run_Sample_stringMethod
(JNIEnv *, jobject, jstring);
/*
* Class: test_sample_jni_run_Sample
* Method: intArrayMethod
* Signature: ([I)I
*/
JNIEXPORT jint JNICALL Java_test_sample_jni_run_Sample_intArrayMethod
(JNIEnv *, jobject, jintArray);
/*
* Class: test_sample_jni_run_Sample
* Method: callJavaMethod
* Signature: (Ljava/lang/String;)Z
*/
JNIEXPORT jboolean JNICALL Java_test_sample_jni_run_Sample_callJavaMethod
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
3. Native library
create one dll project and implement the header file with following c++ file:
//#include "stdafx.h"
#include "test_sample_jni_run_Sample.h"
#include <string.h>
JNIEXPORT jint JNICALL Java_test_sample_jni_run_Sample_intMethod
(JNIEnv *env, jobject ojb, jint num){
jclass cls = env->GetObjectClass(ojb);
jfieldID intfid = env->GetFieldID(cls,"intField","I");
if(intfid)
{
jint intvalue = (jint)env->GetObjectField(ojb,intfid);
printf("intfield value is %d \n", intvalue);
env->SetIntField(ojb,intfid,100);
}
return num * num;
}
JNIEXPORT jboolean JNICALL Java_test_sample_jni_run_Sample_booleanMethod
(JNIEnv *env, jobject ojb, jboolean boolean){
return !boolean;
}
JNIEXPORT jboolean JNICALL Java_test_sample_jni_run_Sample_callJavaMethod
(JNIEnv *env, jobject ojb, jstring string){
jclass cls = env->GetObjectClass(ojb);
jfieldID strfid = env->GetFieldID(cls,"strField","Ljava/lang/String;");
//call java method
jmethodID mid = env->GetMethodID(cls,"callmethod","(Ljava/lang/String;I)Ljava/lang/String;");
if (mid)
{
jstring inputS = env->NewStringUTF("from nativefrom nativefrom nativefrom nativefrom nativefrom nativefrom nativefrom native");
jint inputV = 1;
jstring strvalue = (jstring )env->CallObjectMethod(ojb,mid,inputS,inputV);
const char *str;
str = env->GetStringUTFChars(strvalue, 0);
printf("call java method return value is %s \n", str);
env->DeleteLocalRef(inputS);
}
return true;
}
JNIEXPORT jstring JNICALL Java_test_sample_jni_run_Sample_stringMethod
(JNIEnv *env, jobject ojb, jstring string){
jclass cls = env->GetObjectClass(ojb);
jfieldID strfid = env->GetFieldID(cls,"strField","Ljava/lang/String;");
//call java feild
if(strfid)
{
jstring strvalue = (jstring )env->GetObjectField(ojb,strfid);
const char *str;
str = env->GetStringUTFChars(strvalue, 0);
printf("strField value is %s \n", str);
strvalue = env->NewStringUTF("from nativefrom nativefrom nativefrom nativefrom nativefrom nativefrom nativefrom native");
env->SetObjectField(ojb,strfid,(jobject)strvalue);
env->DeleteLocalRef(strvalue);
}
//call java method
jmethodID mid = env->GetMethodID(cls,"callmethod","(Ljava/lang/String;I)Ljava/lang/String;");
if (mid)
{
jstring inputS = env->NewStringUTF("from nativefrom nativefrom nativefrom nativefrom nativefrom nativefrom nativefrom native");
jint inputV = 1;
jstring strvalue = (jstring )env->CallObjectMethod(ojb,mid,inputS,inputV);
const char *str;
str = env->GetStringUTFChars(strvalue, 0);
printf("call java method return value is %s \n", str);
env->DeleteLocalRef(inputS);
}
//return str;
const char *str = env->GetStringUTFChars(string, 0);
char cap[128];
strcpy(cap, str);
env->ReleaseStringUTFChars(string, str);
return env->NewStringUTF(strupr(cap));
}
JNIEXPORT jint JNICALL Java_test_sample_jni_run_Sample_intArrayMethod
(JNIEnv *env, jobject obj, jintArray array) {
int i, sum = 0;
jsize len = env->GetArrayLength(array);
jint *body = env->GetIntArrayElements(array, 0);
for (i=0; i<len; i++)
{
sum += body[i];
}
env->ReleaseIntArrayElements(array, body, 0);;// avoid mem leaks
return sum;
}
void main(){}
4. Java call native lib
place the native lib to the class path at Java application run time. and explicitly call system load like this: System.loadLibrary("sample"); //don't add extension.
5.Native Application call Java class
Project setting:
1. link following lib :
C:\Program Files (x86)\Java\jdk1.6.0_11\lib\jvm.lib
2. include following head file:
C:\Program Files (x86)\Java\jdk1.6.0_11\include;C:\Program Files (x86)\Java\jdk1.6.0_11\include\win32
3. add jvm.dll to dll search path by modify environment path :
C:\Program Files (x86)\Java\jdk1.6.0_11\jre\bin\client\jvm.dll
In the following source code, C++ create jvm and call the specified the java class:
#include <jni.h>
#include <string.h>
#ifdef _WIN32
#define PATH_SEPARATOR ';'
#else
#define PATH_SEPARATOR ':'
#endif
static jmethodID gmid;
void checkGloabalMethod()
{
}
int main()
{
JavaVMOption options [1];
JNIEnv *env;
JavaVM *jvm;
JavaVMInitArgs vm_args;
long status;
jclass cls;
jmethodID mid;
jint square;
jboolean not;
options[0].optionString = "-Djava.class.path=.;C:/Users/jiali/Documents/Visual Studio 2010/Projects/sample/Debug";
memset(&vm_args, 0, sizeof(vm_args));
vm_args.version = JNI_VERSION_1_6;
vm_args.nOptions = 1;
vm_args.options = options;
status = JNI_CreateJavaVM(&jvm,(void**)&env,&vm_args);
if (status != JNI_ERR)
{
cls = env->FindClass("CalledbyNative");
if (cls)
{
jfieldID a = env->GetStaticFieldID(cls,"a","I");
if(a)
{
jint avalue = env->GetStaticIntField(cls,a);
printf("field a value is %d \n",avalue);
}
mid = env->GetStaticMethodID(cls,"intMethod","(I)I");
gmid = (jmethodID)env->NewGlobalRef((jobject)mid);
if (mid)
{
square = env->CallStaticIntMethod(cls,mid,5);
printf("square is %d \n",square);
}
mid = env->GetStaticMethodID(cls, "booleanMethod","(Z)Z");
if(mid)
{
not = env->CallStaticBooleanMethod(cls,mid,1);
printf("Result of booleanmethod is %d \n",not);
}
}
status = JNI_CreateJavaVM(&jvm,(void**)&env,&vm_args);
square = env->CallStaticIntMethod(cls,gmid,6);
printf("square is %d \n",square);
jvm->DestroyJavaVM();
return 0;
}
return -1;
}