GetMethodID函数声明如下:
jmethodID (JNICALL *GetMethodID) (JNIEnv *env, jclass clazz, const char *name, const char *sig);
获取Java对象方法的jmethodID。包括构造方法,构造方法是一种特殊的方法,但在JVM层面和其他的方式是一样的。
参数说明:
env: 上面已经说明
clazz:表示对象类,如Object.class。
name:方法名,如果是得到构造方法的jmethodID,该参数固定为<init>。
sig:方法签名,形式如下:
(参数类型签名列表)返回类型签名。
如无参构造方法:public JniNewTestObjectX()
或者public void testMethod()方法定义,它的签名为:
()V
如无参构造方法:public JniNewTestObjectX(int i, String s)
或者public void testMethod(int i, String s)方法定义,它的签名为:
(ILjava/lang/String;)V
Java JNI: Java 本机接口可以采用C开发,也支持C++。
例子:
C开发的例子。
public class JniCallMethodReturnVoidTest { static { System.loadLibrary("libjnitest"); } public static void main(String[] args) { JniNewTest obj = new JniNewTest(); obj.testMethod(); } } class JniNewTest { public native void testMethod(); }
>javac JniCallMethodReturnVoidTest.java
>javah -jni -d . JniNewTest
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class JniNewTest */ #ifndef _Included_JniNewTest #define _Included_JniNewTest #ifdef __cplusplus extern "C" { #endif /* * Class: JniNewTest * Method: testMethod * Signature: ()V */ JNIEXPORT void JNICALL Java_JniNewTest_testMethod (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
实现:
#include "JniNewTest.h" JNIEXPORT void JNICALL Java_JniNewTest_testMethod (JNIEnv *env, jobject jobj) { printf("debug: Java_JniNewTest_testMethod.\n"); }
>cl /GR /GX /W3 /ID:\usr\bin\jdk1.6.0_12\include /ID:\usr\bin\jdk1.6.0_12\include\win32 /c /Fo.\ JniNewTest.c
>link /DLL /OUT:.\libjnitest.dll .\JniNewTest.obj
>java JniCallMethodReturnVoidTest debug: Java_JniNewTest_testMethod.
Java native开发
目录结构:
>tree /F .
Folder PATH listing for volume D
Volume serial number is F075-351A
└───com
└───jx
com_jx_Object.c
com_jx_Object.dll
com_jx_Object.exp
com_jx_Object.h
com_jx_Object.lib
com_jx_Object.obj
libobj.dll
libobj.exp
libobj.lib
Object.class
Object.java
ObjectTest.java
Object:
package com.jx; public class Object { public native int addr(); static { System.loadLibrary("libobj"); } }
>javac com\jx\Object.java
>javah -jni -d com\jx com.jx.Object
com_jx_Object.h:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_jx_Object */ #ifndef _Included_com_jx_Object #define _Included_com_jx_Object #ifdef __cplusplus extern "C" { #endif /* * Class: com_jx_Object * Method: addr * Signature: ()I */ JNIEXPORT jint JNICALL Java_com_jx_Object_addr (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
com_jx_Object.c:
#include <stdio.h> #include "com_jx_Object.h" JNIEXPORT jint JNICALL Java_com_jx_Object_addr (JNIEnv *env, jobject jobj) { printf("Java_com_jx_Object_addr.\n"); return 0; }
编译:
>cl /GX /W3 /ID:\usr\bin\jdk1.8.0_101\include /ID:\usr\bin\jdk1.8.0_101\include\win32 /c /Fo.\ *.c连接生成库文件:
>link /DLL /OUT:.\libobj.dll .\*.obj
也可以使用以下命令一次就生成库文件
# 也可以使用以下命令一次就生成库文件: >cl /ID:\usr\bin\jdk1.8.0_101\include /ID:\usr\bin\jdk1.8.0_101\include\win32 /LD com_jx_Object.c
将生成的库文件libobj.dll放在path目录下:
public static void main(String[] args) { String libPath = System.getProperty("java.library.path"); System.out.println(libPath); Object obj = new Object(); obj.addr(); }
<java.library.path> Java_com_jx_Object_addr.Java JNI开发实例:实例化Java对象
class JniNewTestObject { public String toString() { return super.toString() + ": jni new object."; } }
class JniNewTestObjectX { private int i; private String s; public JniNewTestObjectX() { } public JniNewTestObjectX(int i, String s) { this.i = i; this.s = s; } public int i() { return i; } public String s() { return s; } public String toString() { return super.toString() + ": jni new object."; } }
abstract class JniNewTestAbstractObject { public String toString() { return super.toString() + ": jni new object."; } }
class JniNewTestObjectConstructor { public native JniNewTestObject constructJniNewTestObject(Class<?> clazz); public native JniNewTestObjectX constructJniNewTestObjectX(Class<?> clazz); public native JniNewTestObjectX constructJniNewTestObjectX(Class<?> clazz, int i, String s); public native JniNewTestAbstractObject constructJniNewTestAbstractObject(Class<?> clazz); }
public class JniNewObjectTest { static { System.loadLibrary("libjnitest"); } public static void main(String[] args) { JniNewTestObjectConstructor constructor = new JniNewTestObjectConstructor(); JniNewTestObject obj = constructor.constructJniNewTestObject(JniNewTestObject.class); if (obj == null) { System.out.println("construct fail."); } else { System.out.println(obj.toString()); } JniNewTestObjectX objx1 = constructor.constructJniNewTestObjectX(JniNewTestObjectX.class); if (objx1 == null) { System.out.println("construct fail."); } else { System.out.println(objx1.toString()); System.out.println(objx1.i()); System.out.println(objx1.s()); } JniNewTestObjectX objx2 = constructor.constructJniNewTestObjectX(JniNewTestObjectX.class, 1234, "this is 1234."); if (objx2 == null) { System.out.println("construct fail."); } else { System.out.println(objx2.toString()); System.out.println(objx2.i()); System.out.println(objx2.s()); } JniNewTestAbstractObject aobj = constructor.constructJniNewTestAbstractObject(JniNewTestAbstractObject.class); if (aobj == null) { System.out.println("construct fail."); } else { System.out.println(aobj.toString()); } } }
>javac JniNewObjectTest.java为JniNewTestObjectConstructor生成本机接口:JniNewTestObjectConstructor.h
>javah -jni -d . JniNewTestObjectConstructor
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class JniNewTestObjectConstructor */ #ifndef _Included_JniNewTestObjectConstructor #define _Included_JniNewTestObjectConstructor #ifdef __cplusplus extern "C" { #endif /* * Class: JniNewTestObjectConstructor * Method: constructJniNewTestObject * Signature: (Ljava/lang/Class;)LJniNewTestObject; */ JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestObject (JNIEnv *, jobject, jclass); /* * Class: JniNewTestObjectConstructor * Method: constructJniNewTestObjectX * Signature: (Ljava/lang/Class;)LJniNewTestObjectX; */ JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestObjectX__Ljava_lang_Class_2 (JNIEnv *, jobject, jclass); /* * Class: JniNewTestObjectConstructor * Method: constructJniNewTestObjectX * Signature: (Ljava/lang/Class;ILjava/lang/String;)LJniNewTestObjectX; */ JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestObjectX__Ljava_lang_Class_2ILjava_lang_String_2 (JNIEnv *, jobject, jclass, jint, jstring); /* * Class: JniNewTestObjectConstructor * Method: constructJniNewTestAbstractObject * Signature: (Ljava/lang/Class;)LJniNewTestAbstractObject; */ JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestAbstractObject (JNIEnv *, jobject, jclass); #ifdef __cplusplus } #endif #endif
#include "JniNewTestObjectConstructor.h" JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestObject(JNIEnv *env, jobject jobj, jclass jclazz) { jmethodID m_id = NULL; jobject obj = NULL; m_id = (*env)->GetMethodID(env, jclazz, "<init>", "()V"); if (m_id == NULL) { printf("err: GetMethodID, no constructor with no args."); return NULL; } obj = (*env)->NewObject(env, jclazz, m_id); // public JniNewTestObject() if (obj == NULL) { printf("err: NewObject, return null."); return NULL; } return obj; } JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestObjectX__Ljava_lang_Class_2(JNIEnv *env, jobject jobj, jclass jclazz) { jmethodID m_id = NULL; jobject obj = NULL; m_id = (*env)->GetMethodID(env, jclazz, "<init>", "()V"); if (m_id == NULL) { printf("err: GetMethodID, no constructor with no args."); return NULL; } obj = (*env)->NewObject(env, jclazz, m_id); // public JniNewTestObjectX() if (obj == NULL) { printf("err: NewObject, return null."); return NULL; } return obj; } JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestObjectX__Ljava_lang_Class_2ILjava_lang_String_2(JNIEnv *env, jobject jobj, jclass jclazz, jint i, jstring s) { jmethodID m_id = NULL; jobject obj = NULL; m_id = (*env)->GetMethodID(env, jclazz, "<init>", "(ILjava/lang/String;)V"); if (m_id == NULL) { printf("err: GetMethodID, no constructor with no args."); return NULL; } obj = (*env)->NewObject(env, jclazz, m_id, i, s); // public JniNewTestObjectX(int i, String s) if (obj == NULL) { printf("err: NewObject, return null."); return NULL; } return obj; } JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestAbstractObject(JNIEnv *env, jobject jobj, jclass jclazz) { jmethodID m_id = NULL; jobject obj = NULL; m_id = (*env)->GetMethodID(env, jclazz, "<init>", "()V"); if (m_id == NULL) { printf("err: GetMethodID, no constructor with no args."); return NULL; } obj = (*env)->NewObject(env, jclazz, m_id); // public JniNewTestAbstractObject(), class JniNewTestAbstractObject declares abstract. if (obj == NULL) { printf("err: NewObject, return null."); return NULL; } return obj; }
>cl /GR /GX /W3 /ID:\usr\bin\jdk1.6.0_12\include /ID:\usr\bin\jdk1.6.0_12\include\win32 /c /Fo.\ *.c
>link /DLL /OUT:.\libjnitest.dll .\*.obj运行结果:
>java JniNewObjectTest JniNewTestObject@1fb8ee3: jni new object. JniNewTestObjectX@14318bb: jni new object. 0 null JniNewTestObjectX@ca0b6: jni new object. 1234 this is 1234. err: NewObject, return null.Exception in thread "main" java.lang.InstantiationEx ception: JniNewTestAbstractObject at JniNewTestObjectConstructor.constructJniNewTestAbstractObject(Native Method) at JniNewObjectTest.main(JniNewObjectTest.java:33)
Java native开发
目录结构:
>tree /F .
Folder PATH listing for volume D
Volume serial number is F075-351A
└───com
└───jx
com_jx_Object.c
com_jx_Object.dll
com_jx_Object.exp
com_jx_Object.h
com_jx_Object.lib
com_jx_Object.obj
libobj.dll
libobj.exp
libobj.lib
Object.class
Object.java
ObjectTest.java
Object:
package com.jx; public class Object { public native int addr(); static { System.loadLibrary("libobj"); } }
>javac com\jx\Object.java
>javah -jni -d com\jx com.jx.Object
com_jx_Object.h:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_jx_Object */ #ifndef _Included_com_jx_Object #define _Included_com_jx_Object #ifdef __cplusplus extern "C" { #endif /* * Class: com_jx_Object * Method: addr * Signature: ()I */ JNIEXPORT jint JNICALL Java_com_jx_Object_addr (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
com_jx_Object.c:
#include <stdio.h> #include "com_jx_Object.h" JNIEXPORT jint JNICALL Java_com_jx_Object_addr (JNIEnv *env, jobject jobj) { printf("Java_com_jx_Object_addr.\n"); return 0; }
编译:
>cl /GX /W3 /ID:\usr\bin\jdk1.8.0_101\include /ID:\usr\bin\jdk1.8.0_101\include\win32 /c /Fo.\ *.c连接生成库文件:
>link /DLL /OUT:.\libobj.dll .\*.obj
也可以使用以下命令一次就生成库文件
# 也可以使用以下命令一次就生成库文件: >cl /ID:\usr\bin\jdk1.8.0_101\include /ID:\usr\bin\jdk1.8.0_101\include\win32 /LD com_jx_Object.c
将生成的库文件libobj.dll放在path目录下:
public static void main(String[] args) { String libPath = System.getProperty("java.library.path"); System.out.println(libPath); Object obj = new Object(); obj.addr(); }运行结果
<java.library.path> Java_com_jx_Object_addr.Java JNI开发实例:实例化Java对象 在这个例子中,在Java Runtime(Java运行时环境)层面通过NewObject函数创建Java对象(对象实例化),这种方式和在Java层面实例化对象(如new ... ...)效果是一样的。 NewObject函数定义如下: jobject (JNICALL *NewObject) (JNIEnv *env, jclass clazz, jmethodID methodID, ...); Java通过构造方法 实例化对象, 构造方法是一种特殊的方法,但在JVM层面和其他的方式是一样的,所以在 Java Runtime(Java运行时环境)层面通过NewObject函数创建Java对象(对象实例化)需要指定构造方法。 参数说明: env:上面已经说明 clazz:表示构造对象的类 methodID:表示函数标识,这里是 构造函数,通过 GetMethodID得到函数标识(包括构造函数)。 最后一个 不定长参数列表表示传给 构造函数的参数列表。 变体: jobject (JNICALL *NewObjectV) (JNIEnv *env, jclass clazz, jmethodID methodID, va_list args); NewObjectV和 NewObject不同的是在调用构造函数的传参上,也就是最后一个参数, NewObjectV在 构造函数的参数传参上采用的是不定长参数列表: va_list。 jobject (JNICALL *NewObjectA) (JNIEnv *env, jclass clazz, jmethodID methodID, const jvalue *args); NewObjectV和 NewObject不同的是在调用构造函数的传参上,也就是最后一个参数, NewObjectV在 构造函数的参数传参上采用的是jvalue指针 。
class JniNewTestObject { public String toString() { return super.toString() + ": jni new object."; } }
class JniNewTestObjectX { private int i; private String s; public JniNewTestObjectX() { } public JniNewTestObjectX(int i, String s) { this.i = i; this.s = s; } public int i() { return i; } public String s() { return s; } public String toString() { return super.toString() + ": jni new object."; } }
abstract class JniNewTestAbstractObject { public String toString() { return super.toString() + ": jni new object."; } }
class JniNewTestObjectConstructor { public native JniNewTestObject constructJniNewTestObject(Class<?> clazz); public native JniNewTestObjectX constructJniNewTestObjectX(Class<?> clazz); public native JniNewTestObjectX constructJniNewTestObjectX(Class<?> clazz, int i, String s); public native JniNewTestAbstractObject constructJniNewTestAbstractObject(Class<?> clazz); }
public class JniNewObjectTest { static { System.loadLibrary("libjnitest"); } public static void main(String[] args) { JniNewTestObjectConstructor constructor = new JniNewTestObjectConstructor(); JniNewTestObject obj = constructor.constructJniNewTestObject(JniNewTestObject.class); if (obj == null) { System.out.println("construct fail."); } else { System.out.println(obj.toString()); } JniNewTestObjectX objx1 = constructor.constructJniNewTestObjectX(JniNewTestObjectX.class); if (objx1 == null) { System.out.println("construct fail."); } else { System.out.println(objx1.toString()); System.out.println(objx1.i()); System.out.println(objx1.s()); } JniNewTestObjectX objx2 = constructor.constructJniNewTestObjectX(JniNewTestObjectX.class, 1234, "this is 1234."); if (objx2 == null) { System.out.println("construct fail."); } else { System.out.println(objx2.toString()); System.out.println(objx2.i()); System.out.println(objx2.s()); } JniNewTestAbstractObject aobj = constructor.constructJniNewTestAbstractObject(JniNewTestAbstractObject.class); if (aobj == null) { System.out.println("construct fail."); } else { System.out.println(aobj.toString()); } } }
>javac JniNewObjectTest.java为JniNewTestObjectConstructor生成本机接口:JniNewTestObjectConstructor.h
>javah -jni -d . JniNewTestObjectConstructor
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class JniNewTestObjectConstructor */ #ifndef _Included_JniNewTestObjectConstructor #define _Included_JniNewTestObjectConstructor #ifdef __cplusplus extern "C" { #endif /* * Class: JniNewTestObjectConstructor * Method: constructJniNewTestObject * Signature: (Ljava/lang/Class;)LJniNewTestObject; */ JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestObject (JNIEnv *, jobject, jclass); /* * Class: JniNewTestObjectConstructor * Method: constructJniNewTestObjectX * Signature: (Ljava/lang/Class;)LJniNewTestObjectX; */ JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestObjectX__Ljava_lang_Class_2 (JNIEnv *, jobject, jclass); /* * Class: JniNewTestObjectConstructor * Method: constructJniNewTestObjectX * Signature: (Ljava/lang/Class;ILjava/lang/String;)LJniNewTestObjectX; */ JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestObjectX__Ljava_lang_Class_2ILjava_lang_String_2 (JNIEnv *, jobject, jclass, jint, jstring); /* * Class: JniNewTestObjectConstructor * Method: constructJniNewTestAbstractObject * Signature: (Ljava/lang/Class;)LJniNewTestAbstractObject; */ JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestAbstractObject (JNIEnv *, jobject, jclass); #ifdef __cplusplus } #endif #endif实现 本机接口(JniNewTestObjectConstructor.h):JniNewTestObjectConstructor.c
#include "JniNewTestObjectConstructor.h" JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestObject(JNIEnv *env, jobject jobj, jclass jclazz) { jmethodID m_id = NULL; jobject obj = NULL; m_id = (*env)->GetMethodID(env, jclazz, "<init>", "()V"); if (m_id == NULL) { printf("err: GetMethodID, no constructor with no args."); return NULL; } obj = (*env)->NewObject(env, jclazz, m_id); // public JniNewTestObject() if (obj == NULL) { printf("err: NewObject, return null."); return NULL; } return obj; } JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestObjectX__Ljava_lang_Class_2(JNIEnv *env, jobject jobj, jclass jclazz) { jmethodID m_id = NULL; jobject obj = NULL; m_id = (*env)->GetMethodID(env, jclazz, "<init>", "()V"); if (m_id == NULL) { printf("err: GetMethodID, no constructor with no args."); return NULL; } obj = (*env)->NewObject(env, jclazz, m_id); // public JniNewTestObjectX() if (obj == NULL) { printf("err: NewObject, return null."); return NULL; } return obj; } JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestObjectX__Ljava_lang_Class_2ILjava_lang_String_2(JNIEnv *env, jobject jobj, jclass jclazz, jint i, jstring s) { jmethodID m_id = NULL; jobject obj = NULL; m_id = (*env)->GetMethodID(env, jclazz, "<init>", "(ILjava/lang/String;)V"); if (m_id == NULL) { printf("err: GetMethodID, no constructor with no args."); return NULL; } obj = (*env)->NewObject(env, jclazz, m_id, i, s); // public JniNewTestObjectX(int i, String s) if (obj == NULL) { printf("err: NewObject, return null."); return NULL; } return obj; } JNIEXPORT jobject JNICALL Java_JniNewTestObjectConstructor_constructJniNewTestAbstractObject(JNIEnv *env, jobject jobj, jclass jclazz) { jmethodID m_id = NULL; jobject obj = NULL; m_id = (*env)->GetMethodID(env, jclazz, "<init>", "()V"); if (m_id == NULL) { printf("err: GetMethodID, no constructor with no args."); return NULL; } obj = (*env)->NewObject(env, jclazz, m_id); // public JniNewTestAbstractObject(), class JniNewTestAbstractObject declares abstract. if (obj == NULL) { printf("err: NewObject, return null."); return NULL; } return obj; }
>cl /GR /GX /W3 /ID:\usr\bin\jdk1.6.0_12\include /ID:\usr\bin\jdk1.6.0_12\include\win32 /c /Fo.\ *.c
>link /DLL /OUT:.\libjnitest.dll .\*.obj运行结果:
>java JniNewObjectTest JniNewTestObject@1fb8ee3: jni new object. JniNewTestObjectX@14318bb: jni new object. 0 null JniNewTestObjectX@ca0b6: jni new object. 1234 this is 1234. err: NewObject, return null.Exception in thread "main" java.lang.InstantiationEx ception: JniNewTestAbstractObject at JniNewTestObjectConstructor.constructJniNewTestAbstractObject(Native Method) at JniNewObjectTest.main(JniNewObjectTest.java:33)