装载自:http://blog.csdn.net/chenjin_zhong/article/details/5870305

一、JNI简介
  
JNI:Java Native Interface,是Java语言提供的一种通用接口,用于Java代码与本地化代码的交互。所谓本地化代码是指直接编译成的与机器相关的二进制代码,而非Java字节码之类的中间代码。Windows下面的可执行文件,DLL等,Linux下面的可执行文件和SO文件等,都是二进制代码。
  JNI允许Java语言编写的程序与其他语言编写的程序库(DLL, SO)或可执行文件进行互操作,包括汇编、C、C++。JNI产生的原因在于以下几种需求:
  (1)、你的应用程序需要使用系统相关的功能,而Java代码不支持或是难以办到。这个比较典型的是实现托盘图标,有几种现成的方案都是用的JNI做的,名字好像是叫做TrayIcon和StayOnTop。当然啦,如果是用的Java1.6,那就要另当别论了。
  (2)、已有其他语言写好的类库或程序,希望Java程序可以使用它们。
  (3)、出于更高的性能要求,希望使用汇编或是C/C++语言来实现部分功能。
  下图出自JNI Tutorial,展示了JNI的地位:

二.在JAVA中调用C++的基本步骤

(1)、编写带有native方法的java类
  (2)、使用javac命令编译所编写的java类
  (3)、使用javah命令处理类文件,生成C/C++头文件
  (4)、使用C/C++实现本地方法
  (5)、将C/C++编写的文件生成动态连接库

(6)把生成的.dll库放到c:/windows/system32目录下

下面详解这些步骤:

(1)不用说了,就是在java中写一个带有native的方法。如:private native void sum(int x, int y);

(2)进入类所在的目录,用javac进行编译,生成.class文件。

(3)这一步很重要,很多时候都生不成c++的头文件,总是提示找不到相应的类,这时,你得检查所配置的环境变量.如果还是不行,就使用下面的命令:javah -classpath .  jni com.chnic.service.business,这个命令一般情况下都会好使。

com.chnic.service是包名,business是类名。测试的类的目录是:C:/Documents and Settings/Administrator/workspace/JNI2/src/com/chnic/service下。这样你编译生成的C++头文件会出现在src目录下。

(4)打开VC++6.0建立Win32 Dynamic-Link Library.然后把你刚才生成的头文件copy到工程的目录下。例如我新建的工作目录是:D:/Program Files/Microsoft Visual Studio/MyProjects/FruitFactory, 同时还要把jni.h,jni_md.h复制到这个目录下,因为你的C++头文件中包含了这两个头文件。它们可以从jdk目录中找到,C:/Program Files/Java/jdk1.6.0_21/include目录下和C:/Program Files/Java/jdk1.6.0_21/include/win32目录下。然后你就可以在C++中实现你想要的功能了。

(5)编译,运行,生成动态链接库,例如:Business.dll

(6)然后把动态链接库放到c:/windows/system32下。这样在java中就可以执行C++中的函数了。

示例演示:

编译生成Business.dll,即可在JAVA下运行了。 
java代码:

package com.chnic.service;

public class Business {
 public Business(){}
 static {
 
 System.loadLibrary("FruitFactory");
 
 
 }
 
 public native double getPrice(String name);
 public native Order getOrder(String name,int amount);
 public native Order getRamdomOrder();
 public native static void analyzeOrder(Order order);

public void notification(){
  
  
  System.out.println("Got a notification");
  
 }
 
 public static void notificationByStatic(){
  
  System.out.println("Got a notification in a static method");
  
  
 }
 
 
 
}

java代码:

package com.chnic.service;

public class Order {
 private String name="Fruit";
   private double price;
   private int amount=30;
  public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public double getPrice() {
  return price;
 }
 public void setPrice(double price) {
  this.price = price;
 }
 public int getAmount() {
  return amount;
 }
 public void setAmount(int amount) {
  this.amount = amount;
 }

}

c++代码:

#include <iostream.h>
#include <string.h>
#include "com_chnic_service_Business.h"
jobject getInstance(JNIEnv* env,jclass obj_class);

JNIEXPORT jdouble JNICALL Java_com_chnic_service_Business_getPrice
(JNIEnv* env, jobject obj, jstring name){
const char* pname=env->GetStringUTFChars(name,NULL);
if(strcmp(pname,"Apple")==0){
 env->ReleaseStringUTFChars(name,pname);
 cout<<"After release:"<<pname<<endl;
 return 1.2;
}

else{

env->ReleaseStringUTFChars(name,pname);
cout<<"After release:"<<pname<<endl;
return 2.1;

}

}
JNIEXPORT jobject JNICALL Java_com_chnic_service_Business_getOrder
(JNIEnv* env, jobject obj, jstring name, jint amount){

jclass order_class=env->FindClass("com/chnic/service/Order");
jobject order=getInstance(env,order_class);
jmethodID setName_method=env->GetMethodID(order_class,"setName","(Ljava/lang/String;)V");
env->CallVoidMethod(order,setName_method,name);

jmethodID setAmount_method=env->GetMethodID(order_class,"setAmount","(I)V");
env->CallVoidMethod(order,setAmount_method,amount);

return order;

}

JNIEXPORT jobject JNICALL Java_com_chnic_service_Business_getRamdomOrder
(JNIEnv* env, jobject obj){

jclass business_class = env->GetObjectClass(obj);  
    jobject business_obj = getInstance(env, business_class);  
  
    jmethodID notification_method = env->GetMethodID(business_class, "notification", "()V");  
    env->CallVoidMethod(business_obj, notification_method);

jclass order_class=env->FindClass("com/chnic/service/Order");

jobject order=getInstance(env,order_class);

jfieldID amount_field=env->GetFieldID(order_class,"amount","I");
jint amount=env->GetIntField(order,amount_field);
cout<<"amount:"<<amount<<endl;
return order;

}

JNIEXPORT void JNICALL Java_com_chnic_service_Business_analyzeOrder
(JNIEnv* env, jclass cls, jobject obj){

jclass order_class = env->GetObjectClass(obj);  
    jmethodID getName_method = env->GetMethodID(order_class, "getName", "()Ljava/lang/String;");  
    jstring name_str = static_cast<jstring>(env->CallObjectMethod(obj, getName_method));  
    const char* pname = env->GetStringUTFChars(name_str, NULL);  
  
    cout << "Name in Java_com_chnic_service_Business_analyzeOrder: " << pname << endl;  
    jmethodID notification_method_static = env->GetStaticMethodID(cls, "notificationByStatic", "()V");  
    env->CallStaticVoidMethod(cls, notification_method_static);

}
jobject getInstance(JNIEnv* env, jclass obj_class)  
{  
    jmethodID construction_id = env->GetMethodID(obj_class, "<init>", "()V");

//得到构造方法的ID
    jobject obj = env->NewObject(obj_class, construction_id);

//根据构造方法得到相应的类的对象
    return obj;  
}

主要解释一下C++中的方法:

GetStringUTFChars:把字符串类型(jstring)转换成char。

ReleaseStringUTFChars:释放字符串空间。因为创建时需要分配内存,所以释放一下。

FindClass:根据类名找到相应的类对象。需要完整的包名+类名。

GetObjectClass:传入的参数是对象,根据对象找到相应的class.

GetFieldID,GetMethodID:找到相应的成员变量与成员方法的ID。由于对成员变量的取值与设置值分成两个步骤,第一步是得到相应的ID,第二步是根据ID号取值或设置值。传入的参数有:class,成员变量(方法名),变量(方法签名)。签名可由:javap -s 类名(business)得到。

GetIntField得到相应变量的值,传入的参数是obj,与变量的id.

GetStaticIntField得到静态变量的值。传入的参数是class,变量的id.

SetIntField设置变量的值。

SetStaticIntField设置静态变量的值。

GetObjectField,SetObjectField如果想得到字符串的值,与设置字符串的值。如:

jfieldID fid;//store the field ID
jstring jstr;
const char* str;

jclass cls=env->GetObjectClass(obj);//get class
fid=env->GetFieldID(cls,"s","Ljava/lang/String;");
if(fid==NULL){
 return;
}

jstr=(jstring)(env->GetObjectField(obj,fid));//分为两步,第一步得到的是field
//的id,第二步才能得到field的值
str=env->GetStringUTFChars(jstr,NULL);//转换成char类型

if(str==NULL){
return;
}
cout<<"In C:"<<endl;
cout<<"c.s="<<str<<endl;

//创建一个string然后赋值给field
jstr=env->NewStringUTF("123");
if(jstr==NULL){
 return;
}

env->SetObjectField(obj,fid,jstr);//给这个field赋值

CallVoidMethod:调用非静态方法,传入的参数是obj,方法的ID。

CallStaticVoidMethod:调用的是静态方法,传入的参数是class,方法的ID。

NewStringUTF(string str):用来构造一下字符串对象

关于JNI基本的内容就介绍到这了。

一步一步教会你JAVA中调用C++相关推荐

  1. java中调用python

    在Java中调用Python </h1><div class="clear"></div><div class="postBod ...

  2. java 调用 go_实践总结:在 Java 中调用 Go 代码

    在 Java 中调用 Go 的大致过程如下go --> cgo --> jna --> java 整个过程要解决的问题主要两个:数据类型在两种语言中如何转化 何时清理无用的数据 下面 ...

  3. 在Java中调用Python,java面试题,java初级笔试题

    写在最前面,我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家.扫码加微信好友进[程序员面试学习交流群],免费领取.也欢迎各位一起在群里探讨技术. 写在 ...

  4. 在Java中调用Python

    写在前面 参考:https://www.cnblogs.com/nuccch/p/8435693.html 在微服务架构大行其道的今天,对于将程序进行嵌套调用的做法其实并不可取,甚至显得有些愚蠢.当然 ...

  5. 如何在java中调用js方法

    [java] view plain copy/* * 加载脚本引擎,并在java中调用js方法 */ public void test2() { ScriptEngineManager manager ...

  6. java 中调用 Matlab 的函数

    一.matlab版本必须支持java 在command 模式下面运行deploytool,如果支持该命令即可使用 二.matlab中function的书写 %定义一个函数operation(a,b), ...

  7. java执行python脚本_使用Runtime.getRuntime().exec()在java中调用python脚本

    举例有一个Python脚本叫test.py,现在想要在Java里调用这个脚本.假定这个test.py里面使用了拓展的包,使得pythoninterpreter之类内嵌的编译器无法使用,那么只能采用ja ...

  8. java oracle sql 参数_oracle pl/sql之在java中调用带有输入输出参数的oracle存储过程...

    只需注意一点输出参数是用CallableStatement里面的registerOutParameter方法注册进去 存储过程: import java.sql.CallableStatement; ...

  9. 如何通过JNI在Java中调用C库函数

    使用Java语言进行开发时,可能由于处理速度.硬件控制或者复用既有的C/C++模块等方面的原因,需要Java层与使用C/C++编写的应用.模块或库进行交互,共同完成某些任务.在两者之间充当连接桥梁作用 ...

最新文章

  1. HttpHandler与HttpModule区别
  2. HDU 2191 - 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 (多重背包)
  3. @产品部 -- 腾讯策划部是如何培养用户的《王者荣耀》“瘾”的
  4. 软件设计模式—控制反转
  5. HDU - 5788 Level Up(主席树+dfs序+树状数组)
  6. nginx 二进制包安装mysql_二进制安装mysql5.7
  7. 图像分割——迭代式阈值分割
  8. edit with idle 没反应_搬个家,猫咪不吃不喝甚至猝死?可能是你没做好“前戏”...
  9. 《Android游戏编程入门经典》——14.4节问与答
  10. html5在线加密,HTML技巧——加密网页
  11. SpringBoot整合ureport2
  12. mysql能上传程序吗_利用mysql上传和执行文件
  13. 计算机智能的技术的应用,计算机人工智能技术的应用与发展(1)
  14. 小程序 获取地理位置
  15. glassfish插件_Maven嵌入式Glassfish插件-未启动
  16. 用友U8案例教程销售管理后台配置
  17. c语言字符串atoi函数,C++_C语言中一些将字符串转换为数字的函数小结,C语言atoi()函数:将字符串转换 - phpStudy...
  18. 好年货不用多等 拼多多30亿红包聚焦全国全球尖货好物
  19. #### mysql联合索引 注意事项 ####
  20. 蚂蚁金服开源-SofaRpc源码学习篇

热门文章

  1. excel2016html,教大家Excel2016表格数据要怎么添加迷你图
  2. 便签加密设置取消指纹解密
  3. 固态硬盘多大合适 php,固态硬盘(SSD)显示容量为何比真实容量小?
  4. (转载)如何设计一个百万级用户的抽奖系统?
  5. 华为智慧屏v65鸿蒙系统评测,【华为智慧屏V65评测】从荣耀智慧屏到华为智慧屏 大屏时代已经拉开-中关村在线...
  6. 越读越有味的句子 绝对经典语录 人生感悟格言
  7. 计算机应用网线接口亮红灯,网线插在电脑上网口灯不亮是为什么?
  8. xbox手柄接收器驱动_新手有什么PC电脑手柄推荐?简单易懂5分钟教会你做出选择...
  9. 学历高 机器学习_找一份机器学习的工作,学历有多重要?
  10. 【C语言】sizeof和strlen的区别