1.参考资料
- 韦东山Java JNI视频
- The Java™ Native Interface Programmer’s Guide and Specification
2.c 调用java的基本流程
3. C call Java static method(c调用java的静态方法)
- Java代码
- Java代码
/*Hello.java*/ public class Hello { public static void main(String args[]){ //static method System.out.println("Hello, world"); } public static void sayhello_to(String name){ } public static void sayhello_to(){ } }
- 编译和生成signation
- 编译Java
javac Hello.java
- 生成Signature
javap -p -s Hello.class
- 编译Java
- Java代码
- c代码
- c 代码
/*caller.c*/ #include <stdio.h> #include <jni.h> /*init jvm*/ jint create_vm(JavaVM** jvm, JNIEnv** env){ JavaVMInitArgs args; JavaVMOption options[1]; args.version = JNI_VERSION_1_6; args.nOptions = 1; options[0].optionString = "-Djava.class.path=./"; args.options = options; args.ignoreUnrecognized = JNI_FALSE; return JNI_CreateJavaVM(jvm, (void **)env, &args); } int main(int argc, char **argv) { JavaVM* jvm; //virtual machine JNIEnv* env; //environment jclass cls; //class int ret = 0; jmethodID mid; //method /*1. create java virtual machine*/ if(create_vm(&jvm, &env)){ printf("can not create jvm\n"); return -1; } /*2. get class*/ cls = (*env)->FindClass(env, "Hello"); if(cls == NULL){ printf("can not find Hello class\n"); ret = -1; goto destroy; } /*3. create object*/ //static method do not need to create object /*4. call method*/ /*4.1 get static method*/ mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V"); if (mid == NULL) { ret = -1; printf("can not get method\n"); goto destroy; } /*4.2 create parameter*/ //main method don't have parameter /*4.3 call static method*/ (*env)->CallStaticVoidMethod(env, cls, mid, NULL); destroy: (*jvm)->DestroyJavaVM(jvm); return ret; }
- 编译
gcc -I/usr/lib/jvm/java-7-openjdk-i386/include/ -o caller caller.c -L /usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/server/ -ljvm
-I : 表示<jni.h>头文件路径
-L : 表示链接库的路径
-ljvm : 表示要链接的库是libjvm.so
- 执行
LD_LIBRARY_PATH=/usr/lib/jvm/java-7-openjdk-i386/jre/lib/i386/server/ ./caller
LD_LIBRARY_PATH
是Linux环境变量名
,该环境变量主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径。它在运行应用程序(已经被编译和链接完成)时指定动态库的路径。- 参考链接:LD_LIBRARY_PATH
- c 代码
4. C call Java non-static method(c调用java的非静态方法)
-
Java代码
/*Hello.java*/ public class Hello { public static void main(String args[]){ //static method System.out.println("Hello, world!"); } public int sayhello_to(String name){ //non-static method System.out.println("Hello, "+name); return 123; } public static void sayhello_to(){ } }
-
c 代码
/*caller.c*/ #include <stdio.h> #include <jni.h> /*init jvm*/ jint create_vm(JavaVM** jvm, JNIEnv** env){ JavaVMInitArgs args; JavaVMOption options[1]; args.version = JNI_VERSION_1_6; args.nOptions = 1; options[0].optionString = "-Djava.class.path=./"; args.options = options; args.ignoreUnrecognized = JNI_FALSE; return JNI_CreateJavaVM(jvm, (void **)env, &args); } int main(int argc, char **argv) { JavaVM* jvm; //virtual machine JNIEnv* env; //environment jclass cls; int ret = 0; jmethodID mid; jmethodID cid; jobject jobj; jstring jstr; int r; /* 1. create java virtual machine*/ if(create_vm(&jvm, &env)){ printf("can not create jvm\n"); return -1; } /* 2. get class*/ cls = (*env)->FindClass(env, "Hello"); if(cls == NULL){ printf("can not find Hello class\n"); ret = -1; goto destroy; } /* 3. create object */ /* 3.1 get constructor method */ /* Get the method ID for the String constructor */ cid = (*env)->GetMethodID(env, cls, "<init>", "()V"); if (cid == NULL) { ret = -1; printf("can not get constructor method"); goto destroy; } /* 3.2 NewObject */ jobj = (*env)->NewObject(env, cls, cid); if (jobj == NULL) { ret = -1; printf("can not create object"); goto destroy; } /* 4. call public method*/ /* 4.1 get public method ID*/ mid = (*env)->GetMethodID(env, cls, "sayhello_to","(Ljava/lang/String;)I"); if (mid == NULL) { ret = -1; printf("can not get method\n"); goto destroy; } /*4.2 create parameter for public method*/ jstr = (*env)->NewStringUTF(env, "girl"); /*4.3 call public method*/ r = (*env)->CallIntMethod(env, jobj, mid, jstr); printf("ret = %d\n", r); destroy: (*jvm)->DestroyJavaVM(jvm); return ret; }
-
编译和执行
- java和c的编译和执行方法和上面一样
- java和c的编译和执行方法和上面一样
5. C set Java field(c设置java的属性)
-
Java代码
/*Hello.java*/ public class Hello { private String name; //private private int age; //private public static void main(String args[]){ //static method System.out.println("Hello, world!"); } public int sayhello_to(String name){ //non-static method System.out.println("Hello, "+name+"! I am "+this.name+", "+age+" years old."); return 123; } public static void sayhello_to(){ } }
-
c代码
/* caller.c */ #include <stdio.h> #include <jni.h> /*init jvm*/ jint create_vm(JavaVM** jvm, JNIEnv** env){ JavaVMInitArgs args; JavaVMOption options[1]; args.version = JNI_VERSION_1_6; args.nOptions = 1; options[0].optionString = "-Djava.class.path=./"; args.options = options; args.ignoreUnrecognized = JNI_FALSE; return JNI_CreateJavaVM(jvm, (void **)env, &args); } int main(int argc, char **argv) { JavaVM* jvm; //virtual machine JNIEnv* env; //environment jclass cls; int ret = 0; jmethodID mid; jmethodID cid; jobject jobj; jstring jstr; jfieldID nameID; jfieldID ageID; int r; /* 1. create java virtual machine*/ if(create_vm(&jvm, &env)){ printf("can not create jvm\n"); return -1; } /* 2. get class*/ cls = (*env)->FindClass(env, "Hello"); if(cls == NULL){ printf("can not find Hello class\n"); ret = -1; goto destroy; } /* 3. create object */ /* 3.1 get constructor method */ /* Get the method ID for the String constructor */ cid = (*env)->GetMethodID(env, cls, "<init>", "()V"); if (cid == NULL) { ret = -1; printf("can not get constructor method"); goto destroy; } /* 3.2 NewObject */ jobj = (*env)->NewObject(env, cls, cid); if (jobj == NULL) { ret = -1; printf("can not create object"); goto destroy; } /* 4. get/set field */ /* 4.1. get field id */ /* 4.2. get/set field */ /* name */ nameID = (*env)->GetFieldID(env, cls, "name", "Ljava/lang/String;"); if (nameID == NULL) { ret = -1; printf("can not get field name"); goto destroy; } jstr = (*env)->NewStringUTF(env, "Bill"); (*env)->SetObjectField(env, jobj, nameID, jstr); /* age */ ageID = (*env)->GetFieldID(env, cls, "age", "I"); if (ageID == NULL) { ret = -1; printf("can not get field age"); goto destroy; } (*env)->SetIntField(env, jobj, ageID, 10); /* 5. call public method */ /* 5.1 get public method ID */ mid = (*env)->GetMethodID(env, cls, "sayhello_to","(Ljava/lang/String;)I"); if (mid == NULL) { ret = -1; printf("can not get method\n"); goto destroy; } /* 5.2 create parameter for public method */ jstr = (*env)->NewStringUTF(env, "girl"); /* 5.3 call public method */ r = (*env)->CallIntMethod(env, jobj, mid, jstr); printf("ret = %d\n", r); destroy: (*jvm)->DestroyJavaVM(jvm); return ret; }
-
编译和执行