« | August 2025 | » | 日 | 一 | 二 | 三 | 四 | 五 | 六 | | | | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | | | | | | | |
| 公告 |
戒除浮躁,读好书,交益友 |
Blog信息 |
blog名称:邢红瑞的blog 日志总数:523 评论数量:1142 留言数量:0 访问次数:9696504 建立时间:2004年12月20日 |

| |
[jvm]jni中访问java类 原创空间, 软件技术, 电脑与网络
邢红瑞 发表于 2005/6/25 10:51:55 |
一.访问对象的字段class InstanceFieldAccess { private String s;
private native void accessField(); public static void main(String args[]) { InstanceFieldAccess c = new InstanceFieldAccess(); c.s = "邢红瑞"; c.accessField(); System.out.println("In Java:"); System.out.println(" c.s = \"" + c.s + "\""); } static { System.loadLibrary("jnistudy"); }}jni代码#include <jni.h>#include <stdio.h>#include "jni_util.h"#include "InstanceFieldAccess.h"
JNIEXPORT void JNICALL Java_InstanceFieldAccess_accessField(JNIEnv *env, jobject obj){ static jfieldID fid_s = NULL; /* cached field ID for s */
jclass cls = (*env)->GetObjectClass(env, obj); jstring jstr; const char *str;
if (fid_s == NULL) { fid_s = (*env)->GetFieldID(env, cls, "s", "Ljava/lang/String;"); if (fid_s == 0) { return; /* exception already thrown */ } }
printf("In C:\n");
jstr = (*env)->GetObjectField(env, obj, fid_s); str = GetStringPlatformChars(env, jstr, NULL); if (str == NULL) { return; /* out of memory */ } printf(" c.s = \"%s\"\n", str);
jstr = NewStringPlatform(env, "何伍燕"); (*env)->SetObjectField(env, obj, fid_s, jstr);}
访问对象的字段,必须使用GetFieldID根据类的引用,字段名,字段描述得到从实例那里得到field ID,fid = (*env)->GetFieldID(env, cls, "s", "Ljava/lang/String;");然后传递对象引用和field ID就可得到字段的值。因为string和array是对象,所以使用GetObjectField,对于基本类型,还可以使用GetIntField和SetFloatField。"Ljava/lang/String;"是字段描述,L是letter的所写,后面是java的类型,int使用I,float使用F,double使用D,boolean使用Z。数组使用[,整型数组int[]使用[I,使用javap -s -p InstanceFieldAccess可以看到。二 访问静态字段class StaticFieldAccess { private static int si;
private native void accessField(); public static void main(String args[]) { StaticFieldAccess c = new StaticFieldAccess(); StaticFieldAccess.si = 100; c.accessField(); System.out.println("In Java:"); System.out.println(" StaticFieldAccess.si = " + si); } static { System.loadLibrary("jnistudy"); }}jni#include <jni.h>#include <stdio.h>#include "StaticFieldAccess.h"
JNIEXPORT void JNICALL Java_StaticFieldAccess_accessField(JNIEnv *env, jobject obj){ jfieldID fid; /* store the field ID */ jint si;
/* Get a reference to obj苨 class */ jclass cls = (*env)->GetObjectClass(env, obj);
printf("In C:\n");
/* Look for the static field si in cls */ fid = (*env)->GetStaticFieldID(env, cls, "si", "I"); if (fid == 0) { return; /* field not found */ } /* Access the static field si */ si = (*env)->GetStaticIntField(env, cls, fid); printf(" StaticFieldAccess.si = %d\n", si); (*env)->SetStaticIntField(env, cls, fid, 200);}唯一不同的是使用GetStaticFieldID,而不是GetFieldID。三 调用类的静态方法class StaticMethodCall { private native void nativeMethod(); private static void callback() { System.out.println("In Java"); } public static void main(String args[]) { StaticMethodCall c = new StaticMethodCall(); c.nativeMethod(); } static { System.loadLibrary("jnistudy"); }}jni#include <jni.h>#include <stdio.h>#include "jni_util.h"#include "StaticMethodCall.h"
JNIEXPORT void JNICALL Java_StaticMethodCall_nativeMethod(JNIEnv *env, jobject obj){ jclass cls = (*env)->GetObjectClass(env, obj); jmethodID mid = (*env)->GetStaticMethodID(env, cls, "callback", "()V"); if (mid == NULL) { return; /* method not found */ } printf("In C\n"); (*env)->CallStaticVoidMethod(env, cls, mid); JNU_CallStaticMethodByName( env, NULL, "StaticMethodCall", "callback", "()V" ).l;}调用静态方法使用GetStaticMethodID,然后CallStaticVoidMethod,建议使用 JNU_CallStaticMethodByName。四 调用实例的方法class InstanceMethodCall { private native void nativeMethod(); private void callback() { System.out.println("In Java"); } public static void main(String args[]) { InstanceMethodCall c = new InstanceMethodCall(); c.nativeMethod(); } static { System.loadLibrary("jnistudy"); }}jni#include <jni.h>#include <stdio.h>#include "InstanceMethodCall.h"
JNIEXPORT void JNICALL Java_InstanceMethodCall_nativeMethod(JNIEnv *env, jobject obj){ jclass cls = (*env)->GetObjectClass(env, obj); jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "()V"); if (mid == NULL) { return; /* method not found */ } printf("In C\n"); (*env)->CallVoidMethod(env, obj, mid); JNU_CallMethodByName(env,NULL,obj,"callback", "()V");}使用JNI提供的GetMethodID.GetMethodID寻找给定类的特定方法,寻找依据名字和类型描述符,如果没有这个方法,GetMethodID返回NULL,如果调用引起NoSuchMethodError错误。使用CallVoidMethod调用实例的方法,必选传递对象引用,方法名和相应参数。jni也提供其他类型的调用方法CallIntMethod.对于数组和string使用CallObjectMethod,其实还可以调用接口的,调用java.lang.Thread的Runnable.run方法。jobject thd = ...; /* a java.lang.Thread instance */jmethodID mid;jclass runnableIntf =(*env)->FindClass(env, "java/lang/Runnable");if (runnableIntf == NULL) {... /* error handling */}mid = (*env)->GetMethodID(env, runnableIntf, "run", "()V");if (mid == NULL) {... /* error handling */}(*env)->CallVoidMethod(env, thd, mid);... /* check for possible exceptions */
建议使用JNU_CallMethodByName。其实方法描述符和类似字段描述符,方法描述符包括参数类型和返回类型,参数之间没有分隔符,没有参数就是用()表示,返回值放在()的后面,(I)V表示一个int参数,返回值为空,()D表示没有参数,返回值为double,native private String getLine(String);表示为"(Ljava/lang/String;)Ljava/lang/String;"main函数public static void main(String[] args);的参数表示为"([Ljava/lang/String;)V",使用javap -s -p InstanceMethodCall查看信息,-s输出字符串类型,-p输出基本类型。 |
|
|