java JNI 的实现(2)-java和C/C++的相互调用.
目录
二,稍微注意通过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代码:
我们稍微对类做了更改,如下:
package juk.demo;
public class JSay {
//member/class field.
public static String country = "cn";
public int age = 20;
//native method.
public native void changeAge();
public static native void staticSay();
//member method.
public void getVoid() {
}
public String getString() {
return "json";
}
public int getInt() {
return 1;
}
private void getUnknown() {
}
public int[] getIntArray() {
return new int[]{1,2};
}
//static method.
public static void javaStatic() {
System.out.println(country + ", center china");;
}
static {
System.loadLibrary("JNITestCCPP");
}
public static void main(String[] args) {
//invoke native method.
JSay.staticSay();
JSay jSay = new JSay();
System.out.println("before invoke native,age=" + jSay.age);
jSay.changeAge();
System.out.println("after invoke native,age=" + jSay.age);
}
}
这次,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代码的关系:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class juk_demo_JSay */ #ifndef _Included_juk_demo_JSay
#define _Included_juk_demo_JSay
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: juk_demo_JSay
* Method: changeAge
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_juk_demo_JSay_changeAge
(JNIEnv *, jobject); /*
* Class: juk_demo_JSay
* Method: staticSay
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_juk_demo_JSay_staticSay
(JNIEnv *, jclass); #ifdef __cplusplus
}
#endif
#endif
我们发现,通过javah命令生成的C/C++.h头文件,不会在.h头文件中出现(这其实也是很合情理的,但是我们却可以通过java中的native方法对应的.h中的方法的参数'JNIEnv *'去获得java中所有的成员).
三,在C/C++中实现java的native方法(完整C/C++):
#include <iostream>
#include "juk_demo_JSay.h"
using namespace std; //3 ways to get jclass:
/*
1,(JNIEnv *)->FindClass(class-name),which find the class by the classpath.
2,(JNIEnv *)->GetObjectClass(jobject).
3,(JNIEnv *)->GetSuperclass(jobject).
*/ /*
* Class: juk_demo_JSay
* Method: changeAge
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_juk_demo_JSay_changeAge
(JNIEnv *env, jobject obj) {
jclass JSayClass = env->GetObjectClass(obj);
jfieldID ageId = env->GetFieldID(JSayClass, "age", "I");
//env->GetIntField(obj, ageId);
env->SetIntField(obj, ageId, ); //set the age with a new value.
} /*
* Class: juk_demo_JSay
* Method: staticSay
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_juk_demo_JSay_staticSay
(JNIEnv *env, jclass clz) {
//jclass JSayClass = env->FindClass("juk.demo.JSay"); //javaStatic method.
//the third argument,can be fetch with 'javap' command.
jmethodID getStaticMethodId = env->GetStaticMethodID(clz, "javaStatic", "()V");
env->CallStaticVoidMethod(clz, getStaticMethodId, NULL); //get age field.
/*jfieldID countryId = env->GetStaticFieldID(JSayClass, "country", "Ljava/lang/String;");
env->GetStaticObjectField(JSayClass, countryId);*/
}
1,修改age,即Java_juk_demo_JSay_changeAge方法,我们首先要获得jclass对象(jclass对应于java中的Class对象),而jclass对象的获得可以根据3中方式:
,(JNIEnv *)->FindClass(class-name),which find the class by the classpath.
,(JNIEnv *)->GetObjectClass(jobject).
,(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',即可得到对应的签名,如:
Compiled from "JSay.java"
public class juk.demo.JSay extends java.lang.Object{
public static java.lang.String country;
Signature: Ljava/lang/String;
public int age;
Signature: I
public juk.demo.JSay();
Signature: ()V
public native void changeAge();
Signature: ()V
public static native void staticSay();
Signature: ()V
public void getVoid();
Signature: ()V
public java.lang.String getString();
Signature: ()Ljava/lang/String;
public int getInt();
Signature: ()I
public int[] getIntArray();
Signature: ()[I
public static void javaStatic();
Signature: ()V
public static void main(java.lang.String[]);
Signature: ([Ljava/lang/String;)V
}
2,调用java中的'javaStatic'方法,和上面C/C+实现方法相似,不过由于在java源码中,native被定义成了类方法,所以不用获得jclass,而直接从参数获取.同理,通过(JNIEnv *)获得java中的javaStatic方法,并调用.
最后,我们再java主函数中进行测试,结果为:
cn, center china
before invoke native,age=
after invoke native,age=
java JNI 的实现(2)-java和C/C++的相互调用.的更多相关文章
- java JNI介绍
java JNI介绍 目录 java JNI介绍 1. Java调用C++代码 2.C++代码调用java代码 JNI是Java Native Interface的全称. oracle文档中是这样描述 ...
- 关于java jni编译javac javah的问题
这篇文章是在安卓教程网http://android.662p.com那边分享过来的,文章说得还不错的,希望能够帮到大家的学习. javac 编译class文件命令,需要注意的是当类B中import类 ...
- java + jni + mingw实例开发(基于命令行窗口模式)
java+ jni + mingw 参考网址: http://wenku.baidu.com/link?url=9aQ88d2ieO7IgKLlNhJi5d3mb3xwzbezLPzSIX3ixz4_ ...
- Jni中C++和Java的参数传递 参数对照
Jni中C++和Java的参数传递 如何使用JNI的一些基本方法和过程在网上多如牛毛,如果你对Jni不甚了解,不知道Jni是做什么的,如何建立一个基本的jni程序,或许可以参考下面下面这些文章:利用V ...
- Jni中C++和Java的参数传递
Jni中C++和Java的参数传递 如何使用JNI的一些基本方法和过程在网上多如牛毛,如果你对Jni不甚了解,不知道Jni是做什么的,如何建立一个基本的jni程序,或许可以参考下面下面这些文章:利用V ...
- 三、Android NDK编程预备之Java jni入门创建C/C++共享库
转自: http://www.eoeandroid.com/thread-264971-1-1.html 应网友回复,答应在两天前要出一篇创建C/C++共享库的,但由于清明节假期,跟朋友出去游玩,丢手 ...
- 二、Android NDK编程预备之Java jni入门Hello World
转自: http://www.eoeandroid.com/forum.php?mod=viewthread&tid=264543&fromuid=588695 昨天已经简要介绍了J ...
- 一、Android NDK编程预备之Java jni简介
转自: http://www.eoeandroid.com/thread-264384-1-1.html 游戏开发 视频教程 博客 淘帖 论坛›eoe·Android应用开发区›Androi ...
- Java JNI调用c语言的dll测试
最近复习C语言和java语言(10年没用了,温习一下),用JNI调用C语言的dll测试,以前没做过,在网上找了很多,总结如下: 环境:windows 10(64位) + JDK(32位,版本1.7.0 ...
随机推荐
- dede密码忘记 的修改方法
DEDE是使用md5加密,但是,它是显示32位md5加密码从第6位开始的20位 进入数据库 找到数据表dede_admin 我们只要把pwd对应的md5加密码修改为c3949ba59abbe56e0 ...
- php中字符串编码
php中抓取网页拼接url的时候经常需要进行编码,这时候就用到两个函数 mb_detect_encoding — 检测字符的编码. mb_convert_encoding — 转换字符的编码 < ...
- 2014 青年歌手大赛 AC
青年歌手大奖赛_评委会打分 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) To ...
- Java中new关键字和newInstance方法的区别
在初始化一个类,生成一个实例的时候,newInstance()方法和new关键字除了一个是方法一个是关键字外,最主要的区别是创建对象的方式不同.newInstance()使用类加载机制,new是创建一 ...
- Delphi新语法
http://www.cnblogs.com/hnxxcxg/category/456344.html
- mysql INNODB_TRX 事务表
demo:/root# mysql -uroot -pkjk7787czcb --socket=/data01/mysql/mysql.sock -e"show processlist&qu ...
- 夏梦竹谈Hive vs. HBase的区别
对于刚接触大数据的用户来说,要想区分Hive与HBase是有一定难度的.本文将尝试从其各自的定义.特点.限制.应用场景等角度来进行分析,以作抛砖引玉之用. Hive是什么? Apache Hive是 ...
- 糟糠之妻下堂,娇俏公主上位——更换宝马三系座椅作业 - 切诺基 Jeep家族 越野e族论坛 越野/SUV/旅行/赛事/改装/互动中心
糟糠之妻下堂,娇俏公主上位--更换宝马三系座椅作业 - 切诺基 Jeep家族 越野e族论坛 越野/SUV/旅行/赛事/改装/互动中心 舒适性没有想象中好.我觉得理想的座椅,应该象是在你最疲倦的时候,把 ...
- Java高级特性之反射学习总结
老规矩我们还是先提出几个问题,一门技术必然要能解决一定的问题,才有去学习掌握它的价值 一. 什么是反射? 二.反射能做什么? 一. 什么是反射? 用在Java身上指的是我们可以于运行时加载.探知.使用 ...
- 四种方法解析JSON数据
(1)使用TouchJSon解析方法:(需导入包:#import "TouchJson/JSON/CJSONDeserializer.h") //使用TouchJson来解析北京的 ...