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 ...
随机推荐
- python getpass模块:隐藏不显示输入的密码
不知道为什么,本机测试必须要在debug模式下才正常运行.. import getpass #用于隐藏用户输入的字符串,常用来接收密码 def checkuser(user,passwd): ': r ...
- Tr A
Problem Description A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973. Input 数据的第一行是一个T,表示有T组数据. 每组数据的第 ...
- C语言字符数组越界现象
今天在用C的过程中发现一个奇怪的现象.代码如下: ]; chs[] = 'a'; chs[] = 'b'; printf(]); 结果 输出 是 a. 在网上查了一下.有个网友是这样回答的: “ 我 ...
- COJN 0484 800502电池的寿命
800502电池的寿命 难度级别:B: 运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 小S新买了一个掌上游戏机,这个游戏机由两节5号电池供电. ...
- Windows 7 中未能从程序集System.ServiceModel
Windows 7 中未能从程序集System.ServiceModel “/”应用程序中的服务器错误. 未能从程序集“System.ServiceModel, Version=3.0.0.0 ...
- sqlserver如何启动数据库邮件
可以在 msdb 数据库中停止数据库邮件.若要检查数据库邮件的状态,请执行下面的语句: 复制 EXECUTE dbo.sysmail_help_status_sp; 若要在邮件主机数据库中启动数据库邮 ...
- C# 中dataTable中的数据批量增加至数据表中
/// <summary> /// 批量添加 /// </summary> /// <param name="dt"></param> ...
- JDK 和JRE的区别
JRE:Java Runtime Environment/Java运行时环境目标用户:只需要运行Java程序的用户JRE包含了:Deployment,User Interface Toolkits,I ...
- Java程序员的日常—— 垃圾回收中引用类型的作用
在Java里面,是不需要太过于关乎垃圾回收,但是这并不意味着开发者可以不了解垃圾回收的机制,况且在java中内存泄露也是家常便饭的事情.因此了解垃圾回收的相关知识就显得很重要了. 引用,在垃圾回收中是 ...
- ZeroMQ(JAVA)中的数据流,SessionBase与SocketBase
前面的文章中已经比较的清楚了ZeroMQ(java)中如何在底层处理IO, 通过StreamEngine对象来维护SelectableChannel对象以及IO的事件回调,然后通过Poller对象来维 ...