目录

  概述

  一,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. python getpass模块:隐藏不显示输入的密码

    不知道为什么,本机测试必须要在debug模式下才正常运行.. import getpass #用于隐藏用户输入的字符串,常用来接收密码 def checkuser(user,passwd): ': r ...

  2. Tr A

    Problem Description A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973. Input 数据的第一行是一个T,表示有T组数据. 每组数据的第 ...

  3. C语言字符数组越界现象

    今天在用C的过程中发现一个奇怪的现象.代码如下: ]; chs[] = 'a'; chs[] = 'b'; printf(]); 结果 输出 是  a. 在网上查了一下.有个网友是这样回答的: “ 我 ...

  4. COJN 0484 800502电池的寿命

    800502电池的寿命 难度级别:B: 运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 小S新买了一个掌上游戏机,这个游戏机由两节5号电池供电. ...

  5. Windows 7 中未能从程序集System.ServiceModel

    Windows 7 中未能从程序集System.ServiceModel   “/”应用程序中的服务器错误.   未能从程序集“System.ServiceModel, Version=3.0.0.0 ...

  6. sqlserver如何启动数据库邮件

    可以在 msdb 数据库中停止数据库邮件.若要检查数据库邮件的状态,请执行下面的语句: 复制 EXECUTE dbo.sysmail_help_status_sp; 若要在邮件主机数据库中启动数据库邮 ...

  7. C# 中dataTable中的数据批量增加至数据表中

    /// <summary> /// 批量添加 /// </summary> /// <param name="dt"></param> ...

  8. JDK 和JRE的区别

    JRE:Java Runtime Environment/Java运行时环境目标用户:只需要运行Java程序的用户JRE包含了:Deployment,User Interface Toolkits,I ...

  9. Java程序员的日常—— 垃圾回收中引用类型的作用

    在Java里面,是不需要太过于关乎垃圾回收,但是这并不意味着开发者可以不了解垃圾回收的机制,况且在java中内存泄露也是家常便饭的事情.因此了解垃圾回收的相关知识就显得很重要了. 引用,在垃圾回收中是 ...

  10. ZeroMQ(JAVA)中的数据流,SessionBase与SocketBase

    前面的文章中已经比较的清楚了ZeroMQ(java)中如何在底层处理IO, 通过StreamEngine对象来维护SelectableChannel对象以及IO的事件回调,然后通过Poller对象来维 ...