本文地址:http://www.cnblogs.com/wavky/p/JNI.html

当你找到并鬼使神差地打开这个博文的时候,我敢肯定你已经知道什么是JNI,基本概念就不粘贴了。

百度出来的JNI调用方法,前三页几乎毫不例外的都是几年前的资料,告诉你如何设置一大堆莫名其妙的参数、如何通过命令行加工出dll并调用出来的,遗憾的是笔主打开的那堆帖子,多少都有些操作上的出入,再一个笔主对嘿嘿的命令行窗口无爱,并且,例外的帖子笔主还木有幸看到...

所以笔主狠心放下公司工作,抛弃领导的绩效奖金,花了大半天时间研究JNI的调用方法(尤其不用写命令那种),终于赶在下班的前三分钟,顺利完全通过eclipse界面调用出自定义的dll方法!那个激动就像中美建交或日本沉没或苍老师来我家做客那一瞬间那么振奋人心!!

简单准备工作:

以下具体操作方法可以直接百度,答案几乎是唯一可信的。

  1. 安装JDK,配置系统环境变量
  2. 准备好一个带CDT插件的Eclipse,笔主使用的是google的ADT Bundle,自带了CDT,对应Eclipse 3.8.0版
  3. 下载一个MinGW(免费的C/C++等语言编译器套件),笔主限于公司垃圾网络,测试时使用mingw-offline-install-20120426 v4.6.2版,安装时仅需勾选(在线安装版下载数据量约50Mb):
  • C Compiler
  • C++ Compiler
  • MinGW Developer Toolkit (Indudes MSYS Basic System)

配置MinGW的环境变量:

  1. 打开环境变量(系统变量),添加 MINGW_HOME 变量,变量值是刚才MinGW的安装地址,如 D:\Program Files\MinGW
  2. 设置path变量,编辑path变量添加 %MINGW_HOME%\bin;%MINGW_HOME%\msys\1.0\bin;
  3. 添加 LIBRARY_PATH 变量,变量值 %MINGW_HOME%\lib
  4. 添加 C_INCLUDE_PATH 变量,变量值 %JAVA_HOME%\include;%JAVA_HOME%\include\win32;%MINGW_HOME%\include
  5. 添加 CPLUS_INCLUDE_PATH 变量,内容 %JAVA_HOME%\include;%JAVA_HOME%\include\win32;%MINGW_HOME%\lib\gcc\mingw32\4.5.2\include\c++
  6. Win7点击确定后立即生效,若未生效请重启系统(参考安装JDK时配置操作)

第4、5步额外添加的%JAVA_HOME%\include;%JAVA_HOME%\include\win32;是为了让eclipse在c/c++项目中自动引入这个目录下的各种头文件,例如 jni.h,也可在具体项目的属性中以下位置进行指定:

调用JNI全过程:

创建一个普通java工程 Test,添加一个专门负责引入调用本地库的类 Native,代码如下:

 public class Native {
// 声明自定义本地库方法接口
native public static void run(); // 自动加载本地库文件,如文件名全称为 myCLib.dll
static{
System.loadLibrary("myCLib");
}
}

打开CMD....好吧,笔主承认标题党了,整个博文仅此一处需要一句简单的命令! CMD导航至项目文件夹下的 src 目录,输入 javah test.Native(需要使用包名.类名的完整限定名称),生成本地方法接口头文件 test_Native.h

刷新eclipse的 Package Explorer 应该会变成这样的目录状态,其中刚才刚才生成的 test_Native.h 文件代码如下图示(笔主抢闸创建了Test类,稍候用于调用Native类的本地方法):

创建一个新的 C 工程 MyC,期待编译成dll的时候,选择 Shared Library 下的模板:

MyC 工程内创建一个文件夹 src ,并将刚才 Test 项目中生成的 test_Native.h 头文件拷贝(或剪切)到 MyC 工程的 src 文件夹下,Test 工程下的 test_Native.h 文件在后面的项目运行过程中将不再起任何作用,可删:

*  打开 MyC 工程下的 test_Native.h ,若 #include <jni.h> 提示 Unresolved inclusion: <jni.h> 的错误警告(如下图所示),则表明目前这个C项目没有指定 jni.h 的头文件位置,参考上文 配置MinGW的环境变量 的第4、5步进行配置:

**  MyC 工程文件中接口函数代码上提示的 Syntax error 可以暂时忽略,据闻是eclipse语法检测的一个bug:

MyC 工程 src 文件夹中,新建一个C的实现类 NativeC.c ,引入接口头文件 jni.htest_Native.h ,并编写接口函数 JNICALL Java_test_Native_run 的实现(函数接口直接从 test_Native.h 中完整拷贝过来,注意加上形参):

 #include <jni.h>
#include "test_Native.h"
#include <stdio.h> JNIEXPORT void JNICALL Java_test_Native_run
(JNIEnv *env, jclass clazz){
puts("Hello JAVA, I am C.");
}

此时工程看起来应该是这样子的:

由于使用 minGW 默认生成的 dll 函数签名带有 @ 分隔符,将导致后面JNI调用时产生 java.lang.UnsatisfiedLinkError: xoxoclass.xoxomethod() 错误,因此需要执行以下步骤消除多余的 @ 符号。

配置 MyC 工程: MyC 工程上右键菜单 Properties ,左侧选择 C/C++ Build -> Settings ,右侧 Configuration 中显示的为当前正在显示的编译模板,[ Active ] 表示通过 Project->Build Project 菜单编译时使用的默认编译版本, minGW 将根据这些模板的属性设置,编译生成多套版本的 dll 或 exe ,有洁癖的同学可通过最右侧的 Manage Configurations... 按钮增删编译模板:

为了对比效果,笔主决定增加一套新模板 ReleaseNoAt ,继承默认的 Release 模板属性参数,并设置为Active,决不是因为洁癖或什么奇怪的原因:

 

OK返回刚才的编译模板属性配置界面,在 ReleaseNoAt 模板下,Tool Settins 页中的 MinGW C Linker -> Miscellaneous ,Linker flags 框中输入 -Wl,--kill-at,点击最下方的 Apply:

点击 MinGW C Linker ,显示的参数结果应该是这样的:

如果之前建立的C工程不是使用 Shared Library 模板,并且默认编译出的不是 dll 文件,可以在此选择 Build Artifact 页进行修改配置,Artifact Type 中选择 Shared Library ,Artifact extension 中选择 dll 即可,Output prefix 可指定输出 dll 文件的命名前缀:

OK确定返回代码编辑界面,在 MyC 工程上右键菜单,Build Configurations->Build All,生成所有模板的dll文件版本:

各版本 dll 如下图所示,控制台中可以见到每个 dll 生成所用的命令参数(现在显示的是 ReleaseNoAt 版本,即唯一配置了去掉@符号的模板):

为了验证默认 ReleaseReleaseNoAt 版本的区别,可用 dllexp 这个工具打开这两个 dll 文件进行查看(具体方法不告诉你):

Release版(下面这个 @8 就是一切麻烦的罪魁祸首)

ReleaseNoAt版(干净了)

回到eclipse,在 Test 工程中新建文件夹 dll (命名随意),并将上面生成的 ReleaseNoAt版 libMyC.dll 拷贝到这个dll文件夹中,重命名为 myCLib.dll(因为上文 Native类 中通过 System.loadLibrary("myCLib"); 加载了这个名字的dll文件,当然你也可以修改代码变成 System.loadLibrary("libMyC"); 来取代重命名),此后 MyC 工程将不再起任何作用,可删:

配置 Test工程 属性,指定工程的本地库目录,直接看图:

Test工程 test包中新建 Test类 (由于时间关系,笔主已经事先偷偷违建了),在main方法中引用 Native类 的本地方法run():

 public class Test {

     public static void main(String[] args) {
Native.run();
}
}

最后一步,运行起来...好吧,上面已经偷跑了,最终结果如上图所示,Hello, I am Wavky.

手把手教你通过Eclipse工程配置调用JNI完全攻略的更多相关文章

  1. 手把手教你学Dapr - 4. 服务调用

    上一篇:手把手教你学Dapr - 3. 使用Dapr运行第一个.Net程序 介绍 通过使用服务调用,您的应用程序可以使用标准的gRPC或HTTP协议与其他应用程序可靠.安全地通信. 为什么不直接用Ht ...

  2. Eclipse 工程配置与目录结构及各种文件夹(常用插件)

    .classpath..project 是 Eclipse 工程所必须的文件. OpenExplorer: 该 jar 包的下载地址:samsonw/OpenExplorer 安装配置方法:eclip ...

  3. 手把手教你使用eclipse+qemu+gdb来单步调试ARM内核【学习笔记】

    平台信息:linux4.0 平台:qemu 作者:庄泽彬 说明:笨叔叔的Linux视频的笔记 一.编译linux源码 export CROSS_COMPILE=arm-linux-gnueabi- e ...

  4. 手把手教你用Eclipse+TestNG搭建接口自动化测试框架

    转载于:http://qa.blog.163.com/blog/static/190147002201510275306185/ 把群博里关于接口自动化的文章都看了一遍,都是关于测试过程中遇到的问题及 ...

  5. Eclipse——手把手教新手安装Eclipse

    一.准备工作:安装JRE和JDK. 全名分别为:Java Runtime Environmen和Java SE Development Kit,推荐直接在某度软件中心下载即可,注意区分64位和32位. ...

  6. 手把手教你安装Eclipse最新版本的详细教程 - 大佬的鸡肋,菜鸟的盛宴(非常详细,非常实用)

    简介 首先声明此篇文章主要是针对测试菜鸟或者刚刚入门的小伙们或者童鞋们,大佬就没有必要往下看了. 写这篇文章的由来是因为后边要用这个工具,但是由于某些原因有部分小伙伴和童鞋们可能不会安装此工具,为了方 ...

  7. 手把手教你在Eclipse中使用CVS Branch功能

    Brach 的作用: 开发新版本的人员就基于 main trunk 工作,而 fix bug 的人员就基于 branch 工作. 一旦在 branch上将 Release_1_0的 bug修复了,我们 ...

  8. httpd-2.2 配置及用法完全攻略

    导读 apache是一款稳定的流行的web软件,是linux操作系统中默认的web管理软件.在RHEL/Centos系列中可以用rpm直接进行安装,服务名为httpd.apache有很多设置和调优 的 ...

  9. 手把手教你webpack、react和node.js环境配置(上篇)

    很多人刚学习react的时候,往往因为繁琐的配置而头疼,这里我将手把手教大家怎么用webpack配置react和redux的环境,这篇教程包括前端react和后台node整个网站的环境配置,对node ...

随机推荐

  1. laravel 中出现SQLSTATE[HY000] [2002] 如何解决?

    在日常开发中总是难免遇到各式各样的错误,还有许多错误常常是重复出现的 以下是报错信息! SQLSTATE[HY000] [2002] ������ӷ���һ��ʱ���û���ȷ�

  2. Nodejs 使用 addons 调用c++ 初体验(一)

    纠结很久,决定写一点遇到的“坑”. 基础环境:win7-64bit  node(v7.5.0)   这些安装实在是太方便了,自行准备吧. 1. 安装 python(2.7.x ),用npm安装 nod ...

  3. linux 热替换so文件

    http://www.zhaoch.top/操作系统/linux/热替换so文件.html 热替换so文件 www.zhaoch.top > 操作系统 > linux 发现nginx的动态 ...

  4. HDU暑假多校第三场H.Monster Hunter

    一.题意 给定一个树状地图,每个树节点上有一只怪物,打死一只怪物的过程中将会消耗A点HP,打死之后将会获得B点HP.因为树状结构,所以每只怪物必须先打死父节点的怪兽之后在打死子节点的怪物.现在,给定每 ...

  5. Lucene如何实现多条件搜索?

    有两种方式可以实现, 一是:Lucene搜索API中提供了一个布尔查询器(BooleanQuery),它可以包含多个查询器,每个查询器Occur枚举控制是“and” 还是“or” BooleanQue ...

  6. PHP HashTable总结

    本篇文章主要是对 PHP HashTable 总结,下面的参考链接是很好的学习资料. 总结 HashTable 又叫做散列表,是一种用于以常数平均时间执行插入.删除和查找的技术.不能有效的支持元素之间 ...

  7. 什么是 Cookie

    什么是 Cookie? Cookie 是一小段文本信息,伴随着用户请求和页面在 Web 服务器和浏览器之间传递.Cookie 包含每次用户访问站点时 Web 应用程序都可以读取的信息. 例如,如果在用 ...

  8. 在Ubuntu Server 16.04 LTS下安装VMware Tools

    1.开启ubuntu server虚拟机 2.vmware workstation菜单项,选取虚拟机(M) --> 安装VMware Tools 3.mkdir /mnt/cdrom  #创建一 ...

  9. 谷歌面试官经典作品(CTCI)目录

    1.1 判断一个字符串中的字符是否唯一 1.2 字符串翻转 1.3 去除字符串中重复字符 1.8 利用已知函数判断字符串是否为另一字符串的子串 2.1 从链表中移除重复结点 2.2 实现一个算法从一个 ...

  10. JavaScript---设计模式之迭代器模式

    迭代器模式提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该方法中的内部表示. jQuery中我们经常会用到一个each函数就是迭代器模式 作用 为遍历不同的集合结构提供一个统一的接口,从而 ...