标签:des style blog http io ar color os sp
目录
二,稍微注意通过javah生成的‘C/C++‘.h头文件和源java代码的关系
三,在C/C++中实现java的native方法(完整C/C++)
1,修改age,即Java_juk_demo_JSay_changeAge方法
2,调用java中的‘javaStatic‘方法,和上面C/C+实现方法相似
从第一篇java JNI 的实现(1)-又进一步加深对JVM实现的理解对JNI有了大致的理解之后,并知道JNI中java如何调用C/C++等,这篇文章我们进一步将JNI中,java和C/C++的相互调用.
一,java代码:
我们稍微对类做了更改,如下:
1 package juk.demo; 2 3 public class JSay { 4 //member/class field. 5 public static String country = "cn"; 6 7 public int age = 20; 8 9 //native method. 10 public native void changeAge(); 11 12 public static native void staticSay(); 13 14 //member method. 15 public void getVoid() { 16 17 } 18 19 public String getString() { 20 return "json"; 21 } 22 23 public int getInt() { 24 return 1; 25 } 26 27 private void getUnknown() { 28 29 } 30 31 public int[] getIntArray() { 32 return new int[]{1,2}; 33 } 34 35 //static method. 36 public static void javaStatic() { 37 System.out.println(country + ", center china");; 38 } 39 40 static { 41 System.loadLibrary("JNITestCCPP"); 42 } 43 44 45 public static void main(String[] args) { 46 //invoke native method. 47 JSay.staticSay(); 48 49 JSay jSay = new JSay(); 50 System.out.println("before invoke native,age=" + jSay.age); 51 jSay.changeAge(); 52 System.out.println("after invoke native,age=" + jSay.age); 53 54 } 55 56 }
这次,java代码有两个native方法(changeAge和staticSay),并且有许多成员和类的普通java方法(主要是研究通过javah产生的.h头文件和源java代码直接的关系),
我们这次的目的,一是在java中调用‘changeAge‘ native方法的时候,在C/C++代码中对其对象的age属性进行更改(当然,一般成员变量都是封装的,这里只是为了测试);二是在java调用‘staticSay‘ native方法的时候,在C/C++代码中,反过来调用java的‘javaStatic‘方法.
二,稍微注意通过javah生成的‘C/C++‘.h头文件和源java代码的关系:
1 /* DO NOT EDIT THIS FILE - it is machine generated */ 2 #include "jni.h" 3 /* Header for class juk_demo_JSay */ 4 5 #ifndef _Included_juk_demo_JSay 6 #define _Included_juk_demo_JSay 7 #ifdef __cplusplus 8 extern "C" { 9 #endif 10 /* 11 * Class: juk_demo_JSay 12 * Method: changeAge 13 * Signature: ()V 14 */ 15 JNIEXPORT void JNICALL Java_juk_demo_JSay_changeAge 16 (JNIEnv *, jobject); 17 18 /* 19 * Class: juk_demo_JSay 20 * Method: staticSay 21 * Signature: ()V 22 */ 23 JNIEXPORT void JNICALL Java_juk_demo_JSay_staticSay 24 (JNIEnv *, jclass); 25 26 #ifdef __cplusplus 27 } 28 #endif 29 #endif
我们发现,通过javah命令生成的C/C++.h头文件,不会在.h头文件中出现(这其实也是很合情理的,但是我们却可以通过java中的native方法对应的.h中的方法的参数‘JNIEnv *‘去获得java中所有的成员).
三,在C/C++中实现java的native方法(完整C/C++):
1 #include <iostream> 2 #include "juk_demo_JSay.h" 3 using namespace std; 4 5 //3 ways to get jclass: 6 /* 7 1,(JNIEnv *)->FindClass(class-name),which find the class by the classpath. 8 2,(JNIEnv *)->GetObjectClass(jobject). 9 3,(JNIEnv *)->GetSuperclass(jobject). 10 */ 11 12 /* 13 * Class: juk_demo_JSay 14 * Method: changeAge 15 * Signature: ()V 16 */ 17 JNIEXPORT void JNICALL Java_juk_demo_JSay_changeAge 18 (JNIEnv *env, jobject obj) { 19 jclass JSayClass = env->GetObjectClass(obj); 20 jfieldID ageId = env->GetFieldID(JSayClass, "age", "I"); 21 //env->GetIntField(obj, ageId); 22 env->SetIntField(obj, ageId, 22); //set the age with a new value. 23 } 24 25 /* 26 * Class: juk_demo_JSay 27 * Method: staticSay 28 * Signature: ()V 29 */ 30 JNIEXPORT void JNICALL Java_juk_demo_JSay_staticSay 31 (JNIEnv *env, jclass clz) { 32 //jclass JSayClass = env->FindClass("juk.demo.JSay"); 33 34 //javaStatic method. 35 //the third argument,can be fetch with ‘javap‘ command. 36 jmethodID getStaticMethodId = env->GetStaticMethodID(clz, "javaStatic", "()V"); 37 env->CallStaticVoidMethod(clz, getStaticMethodId, NULL); 38 39 //get age field. 40 /*jfieldID countryId = env->GetStaticFieldID(JSayClass, "country", "Ljava/lang/String;"); 41 env->GetStaticObjectField(JSayClass, countryId);*/ 42 }
1,修改age,即Java_juk_demo_JSay_changeAge方法,我们首先要获得jclass对象(jclass对应于java中的Class对象),而jclass对象的获得可以根据3中方式:
1,(JNIEnv *)->FindClass(class-name),which find the class by the classpath. 2,(JNIEnv *)->GetObjectClass(jobject). 3,(JNIEnv *)->GetSuperclass(jobject).
然后可以通过(JNIEnv *)获得属性的ID,并修改.稍微注意的是‘env->GetFieldID‘方法中的第3个参数,是为了区别方法的重载问题,
如下表(来自oracle的Chapter 3: JNI Types and Data Structures)
Type Signature | Java Type |
---|---|
Z | boolean |
B | byte |
C | char |
S | short |
I | int |
J | long |
F | float |
D | double |
L fully-qualified-class ; | fully-qualified-class |
[ type | type[] |
( arg-types ) ret-type | method type |
sun为了方便我们程序员,写一个工具(即,jdk中的javap),而不用我们记忆那些类型签名,例如,我们可以在包含该java的class的目录上(通过命令行),输入 ‘javap -s -public juk.demo.JSay‘,即可得到对应的签名,如:
1 Compiled from "JSay.java" 2 public class juk.demo.JSay extends java.lang.Object{ 3 public static java.lang.String country; 4 Signature: Ljava/lang/String; 5 public int age; 6 Signature: I 7 public juk.demo.JSay(); 8 Signature: ()V 9 public native void changeAge(); 10 Signature: ()V 11 public static native void staticSay(); 12 Signature: ()V 13 public void getVoid(); 14 Signature: ()V 15 public java.lang.String getString(); 16 Signature: ()Ljava/lang/String; 17 public int getInt(); 18 Signature: ()I 19 public int[] getIntArray(); 20 Signature: ()[I 21 public static void javaStatic(); 22 Signature: ()V 23 public static void main(java.lang.String[]); 24 Signature: ([Ljava/lang/String;)V 25 }
2,调用java中的‘javaStatic‘方法,和上面C/C+实现方法相似,不过由于在java源码中,native被定义成了类方法,所以不用获得jclass,而直接从参数获取.同理,通过(JNIEnv *)获得java中的javaStatic方法,并调用.
最后,我们再java主函数中进行测试,结果为:
cn, center china before invoke native,age=20 after invoke native,age=22
java JNI 的实现(2)-java和C/C++的相互调用.
标签:des style blog http io ar color os sp
原文地址:http://www.cnblogs.com/listened/p/4136420.html