目录

  概述

  一,java代码

  二,稍微注意通过javah生成的'C/C++'.h头文件和源java代码的关系

  三,在C/C++中实现java的native方法(完整C/C++)

    1,修改age,即Java_juk_demo_JSay_changeAge方法

    2,调用java中的'javaStatic'方法,和上面C/C+实现方法相似

    3,最后测试

概述

  从第一篇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)

Java VM Type Signatures
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++的相互调用.的更多相关文章

  1. java JNI介绍

    java JNI介绍 目录 java JNI介绍 1. Java调用C++代码 2.C++代码调用java代码 JNI是Java Native Interface的全称. oracle文档中是这样描述 ...

  2. 关于java jni编译javac javah的问题

    这篇文章是在安卓教程网http://android.662p.com那边分享过来的,文章说得还不错的,希望能够帮到大家的学习. javac  编译class文件命令,需要注意的是当类B中import类 ...

  3. java + jni + mingw实例开发(基于命令行窗口模式)

    java+ jni + mingw 参考网址: http://wenku.baidu.com/link?url=9aQ88d2ieO7IgKLlNhJi5d3mb3xwzbezLPzSIX3ixz4_ ...

  4. Jni中C++和Java的参数传递 参数对照

    Jni中C++和Java的参数传递 如何使用JNI的一些基本方法和过程在网上多如牛毛,如果你对Jni不甚了解,不知道Jni是做什么的,如何建立一个基本的jni程序,或许可以参考下面下面这些文章:利用V ...

  5. Jni中C++和Java的参数传递

    Jni中C++和Java的参数传递 如何使用JNI的一些基本方法和过程在网上多如牛毛,如果你对Jni不甚了解,不知道Jni是做什么的,如何建立一个基本的jni程序,或许可以参考下面下面这些文章:利用V ...

  6. 三、Android NDK编程预备之Java jni入门创建C/C++共享库

    转自: http://www.eoeandroid.com/thread-264971-1-1.html 应网友回复,答应在两天前要出一篇创建C/C++共享库的,但由于清明节假期,跟朋友出去游玩,丢手 ...

  7. 二、Android NDK编程预备之Java jni入门Hello World

    转自:  http://www.eoeandroid.com/forum.php?mod=viewthread&tid=264543&fromuid=588695 昨天已经简要介绍了J ...

  8. 一、Android NDK编程预备之Java jni简介

    转自:  http://www.eoeandroid.com/thread-264384-1-1.html 游戏开发 视频教程 博客 淘帖     论坛›eoe·Android应用开发区›Androi ...

  9. Java JNI调用c语言的dll测试

    最近复习C语言和java语言(10年没用了,温习一下),用JNI调用C语言的dll测试,以前没做过,在网上找了很多,总结如下: 环境:windows 10(64位) + JDK(32位,版本1.7.0 ...

随机推荐

  1. powerpoint取色器有什么用|ppt取色器使用教程

    在使用powerpoint过程中常常发现一些功能我们很少用到,其实是自己不会用的原因,关于powerpoint取色器有什么用呢?接下来我们一起来学一下ppt取色器使用教程. powerpoint取色器 ...

  2. .net FrameWork4.0安装未成功

    安装了一上午的.net framework 4.0,各种失败,查了好多答案,各种不靠谱,最后终于找到答案了 和Windows Update有关系,给目录名重命名一下再次安装,即安装成功了! 下载地址: ...

  3. Net Core 项目实战之权限管理系统(0)

    0 前言 Net Core 项目实战之权限管理系统(0) 无中生有   0 http://www.cnblogs.com/fonour/p/5848933.html 学习的最好方法就是动手去做,这里以 ...

  4. 转:memset用法详解

    功 能 将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值,   块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作,   其返回值为指向S的指针.   [编辑本段 ...

  5. JavaScript and html的关系

    HTML--------------------------->DOM, BOM, Event Request/Response------------->Ajax 日期处理 http:/ ...

  6. cf C. Hacking Cypher

    http://codeforces.com/contest/490/problem/C 题意:把一个很大的数分成两部分,前一部分可以被a整除,后一部分可以被b整除,如果存在输出这两部分,两部分都不能含 ...

  7. scheme lambda表达式 形参

     lambda表达式 (Lambda (arg1 …) exp1 exp2)从演算来看,(let ((var value) …) exp1 exp2…) == ((lambda (var …) exp ...

  8. 【博弈论】HDU 5754 Life Winner Bo

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5754 题目大意: 4种棋子,象棋中的 1王,2车,3马,4后,选其一,B和G轮流走,不能往左上走,一 ...

  9. 【动态规划】XMU 1583 Sequence

    题目链接: http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1583 题目大意: T组数据,对于n(n<=6000)给定序列Xn(Xn<= ...

  10. 酷派D530刷机指引

    酷派D530是我的第一台智能手机,刚入手的时候是挺激动的,什么Root啦,精简系统删官方应用啦,app2sd啦,杂七杂八的应用装了一堆,折腾得不亦乐乎.但过了那个热度之后,现在我对于智能手机的要求还是 ...