转(JAVA的JNI调用)
转载于:https://www.cnblogs.com/GDUT/p/3806771.html
由于JNI调用C和调用C++差不多,而且C++中可以混合写C代码,所以这里主要是写关于JNI调用C++的部分。
一般步骤:
- 先是写普通的Java类,其中包括本地方法调用。
- 然后编译这个Java类,调用javah命令,生成.h头文件
- 接着,就是实现头文件中的函数;实现过程中有点比较麻烦,要知道JNI中JAVA和C/C++的类型转换,比如数组类型的转换,基本类型的转换等,最好是看文档,或者网上找相关资料。
源代码链接:http://files.cnblogs.com/GDUT/jni-demo.rar
JNI的调用效果图:
下面是调用JNI的具体过程:
1. 普通Java类(包含测试方法):MyJNI.java
1 public class MyJNI {2 3 //加载动态链接库4 static {5 System.out.println("开始加载动态链接库");6 System.loadLibrary("MyJNI");7 System.out.println("动态链接库加载完毕。");8 }9 10 public native void go(); 11 12 public native void run(); 13 14 public native String getName(); 15 16 public native int[] sort(int[] array); 17 18 //测试 19 public static void main(String[] args) { 20 MyJNI jni = new MyJNI(); 21 int[] array = {5, 3, 6, 35, 74, 8}, sortedArray; 22 23 jni.run(); 24 jni.go(); 25 jni.getName(); 26 sortedArray = jni.sort(array); 27 //由于这是本地方法调用,这里的数组和平常的数组的引用不太一样。 28 29 for(int i=0; i<sortedArray.length; i++){ 30 System.out.print(sortedArray[i] + "\t"); 31 } 32 33 } 34 }
2. 由Java类编译后生成的C++头文件:MyJNI.h
1 /* DO NOT EDIT THIS FILE - it is machine generated */2 #include <jni.h>3 /* Header for class MyJNI */4 5 #ifndef _Included_MyJNI6 #define _Included_MyJNI7 #ifdef __cplusplus8 extern "C" {9 #endif 10 /* 11 * Class: MyJNI 12 * Method: go 13 * Signature: ()V 14 */ 15 JNIEXPORT void JNICALL Java_MyJNI_go 16 (JNIEnv *, jobject); 17 18 /* 19 * Class: MyJNI 20 * Method: run 21 * Signature: ()V 22 */ 23 JNIEXPORT void JNICALL Java_MyJNI_run 24 (JNIEnv *, jobject); 25 26 /* 27 * Class: MyJNI 28 * Method: getName 29 * Signature: ()Ljava/lang/String; 30 */ 31 JNIEXPORT jstring JNICALL Java_MyJNI_getName 32 (JNIEnv *, jobject); 33 34 /* 35 * Class: MyJNI 36 * Method: sort 37 * Signature: ([I)[I 38 */ 39 JNIEXPORT jintArray JNICALL Java_MyJNI_sort 40 (JNIEnv *, jobject, jintArray); 41 42 #ifdef __cplusplus 43 } 44 #endif 45 #endif
3. 需要调用的C++函数的相关文件:MyJNIImpl.cpp
1 #include <jni.h>2 #include "MyJNI.h"3 #include <stdio.h>4 5 6 /*7 * Class: MyJNI8 * Method: go9 * Signature: ()V 10 */ 11 JNIEXPORT void JNICALL Java_MyJNI_go 12 (JNIEnv * env, jobject jobj){ 13 14 printf("I am going....\n"); 15 } 16 17 /* 18 * Class: MyJNI 19 * Method: run 20 * Signature: ()V 21 */ 22 JNIEXPORT void JNICALL Java_MyJNI_run 23 (JNIEnv * env, jobject jobj){ 24 25 printf("I am running....\n"); 26 } 27 28 /* 29 * Class: MyJNI 30 * Method: getName 31 * Signature: ()Ljava/lang/String; 32 */ 33 JNIEXPORT jstring JNICALL Java_MyJNI_getName 34 (JNIEnv * env, jobject job){ 35 36 printf("I am GDUTtiantian, go with me.\n"); 37 //将字符串转化为jstring类型 38 //jstring就是对应java的String类型 39 jstring p = env->NewStringUTF("GDUTtiantian"); 40 return p; 41 } 42 43 /* 44 * Class: MyJNI 45 * Method: sort 46 * Signature: ([I)[I 47 */ 48 JNIEXPORT jintArray JNICALL Java_MyJNI_sort 49 (JNIEnv * env, jobject jobj, jintArray array){ 50 51 jint* arr;//定义一个整形指针 52 int sum=0; 53 //对于整形数组的处理,主要有GetIntArrayElements与GetIntArrayRegion 54 //第一种方法 55 arr = env->GetIntArrayElements(array, NULL);//得到一个指向原始数据类型内容的指针 56 jint length = env->GetArrayLength(array);//得到数组的长度 57 58 for(int i=0; i<length; i++){ 59 for(int j=i+1; j<length; j++){ 60 if(arr[i] > arr[j]){ 61 jint temp = arr[i]; 62 arr[i] = arr[j]; 63 arr[j] = temp; 64 } 65 } 66 } 67 68 69 for(int i=0; i<length; i++){ 70 printf("%d ", arr[i]); 71 } 72 73 printf("\n排序完成\n"); 74 75 jintArray javaArray = env->NewIntArray(length); 76 env->SetIntArrayRegion(javaArray, 0, length, arr); 77 78 return javaArray;//返回排序后的数组 79 }
编译之后,生成一个动态链接库文件:MyJNI.dll
在Java类中就是通过加载这个库文件,调用其中的相关函数。
调用的相关命令:
- javac *.java
- javah MyJNI
- set JAVA_HOME=D:\SoftwareDeveloping\jdk32bit_1.6
- g++ -Wl,--add-stdcall-alias -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -shared -o MyJNI.dll MyJNIImpl.cpp
- java MyJNI
在操作过程中可能会出现的异常:
- 第一个异常
1 C:\Users\Administrator\Desktop>java HelloJNI2 Exception in thread "main" java.lang.UnsupportedClassVersionError: HelloJNI : Unsupported major.minor version 51.03 at java.lang.ClassLoader.defineClass1(Native Method)4 at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)5 at java.lang.ClassLoader.defineClass(ClassLoader.java:615)6 at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)7 at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)8 at java.net.URLClassLoader.access$000(URLClassLoader.java:58)9 at java.net.URLClassLoader$1.run(URLClassLoader.java:197) 10 at java.security.AccessController.doPrivileged(Native Method) 11 at java.net.URLClassLoader.findClass(URLClassLoader.java:190) 12 at java.lang.ClassLoader.loadClass(ClassLoader.java:306) 13 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) 14 at java.lang.ClassLoader.loadClass(ClassLoader.java:247) 15 Could not find the main class: HelloJNI. Program will exit.
这个是JAVA虚拟机的版本低于编译器的问题,如果你用一个编译编译之后,然后把.class文件移动到另一个环境下执行,可能会出现这个问题。
2. 第二个异常
1 C:\Users\Administrator\Desktop>javac *.java2 3 C:\Users\Administrator\Desktop>java HelloJNI4 Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\Users\Administrator\Desktop\hello.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform5 at java.lang.ClassLoader$NativeLibrary.load(Native Method)6 at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1807)7 at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1732)8 at java.lang.Runtime.loadLibrary0(Runtime.java:823)9 at java.lang.System.loadLibrary(System.java:1028) 10 at HelloJNI.<clinit>(HelloJNI.java:3) 11 Could not find the main class: HelloJNI. Program will exit.
动态链接库.dll是32位,而JVM是64位,不匹配;可以安装一个32位的JVM;或者在64位环境下重新编译一个新的.dll文件。
3. 第三个异常
1 C:\Users\Administrator\Desktop\jni>g++ -Wl,--add-stdcall-alias -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -shared -o MyJNI.dll MyJNIImpl.cpp2 In file included from MyJNIImpl.cpp:1:3 MyJNI.h:2:17: jni.h: No such file or directory4 In file included from MyJNIImpl.cpp:1:5 MyJNI.h:15: error: expected constructor, destructor, or type conversion before "void"6 MyJNI.h:15: error: expected `,' or `;' before "void"7 MyJNI.h:23: error: expected constructor, destructor, or type conversion before "void"8 MyJNI.h:23: error: expected `,' or `;' before "void"9 MyJNI.h:31: error: `JNIEXPORT' does not name a type 10 MyJNI.h:39: error: `JNIEXPORT' does not name a type 11 MyJNIImpl.cpp:10: error: expected constructor, destructor, or type conversion before "void" 12 MyJNIImpl.cpp:10: error: expected `,' or `;' before "void" 13 MyJNIImpl.cpp:21: error: expected constructor, destructor, or type conversion before "void" 14 MyJNIImpl.cpp:21: error: expected `,' or `;' before "void" 15 MyJNIImpl.cpp:32: error: `JNIEXPORT' does not name a type 16 MyJNIImpl.cpp:47: error: `JNIEXPORT' does not name a type
这个报错主要是找不到jni.h文件,一般的原因:JAVA_HOME的路径有问题,注意这个路径是安装路径。用命令设置下,如果设置还是报这个错误,那么就到环境变量那里修改。
参考资料:http://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html
JNI类型转换:http://www.cnblogs.com/lgydqy/archive/2012/02/28/2371592.html
函数
Java 数组类型
本地类型
GetBooleanArrayElements
jbooleanArray
jboolean
GetByteArrayElements
jbyteArray
jbyte
GetCharArrayElements
jcharArray
jchar
GetShortArrayElements
jshortArray
jshort
GetIntArrayElements
jintArray
jint
GetLongArrayElements
jlongArray
jlong
GetFloatArrayElements
jfloatArray
jfloat
GetDoubleArrayElements
jdoubleArray
jdouble
转(JAVA的JNI调用)相关推荐
- Java通过JNI调用C++动态链接库dll,并打在jar包内 ——JNA-JNI(一)
Java通过JNI调用C++动态链接库dll,并打在jar包内--JNA-JNI(一) 系列文章: Java通过JNI调用C++动态链接库dll,并打在jar包内 --JNA-JNI(一) Java使 ...
- JAVA通过JNI调用C++动态链接库CLL(二)
简介 使用Visual Studio 2017新建c++动态链接库dll项目 编写JniDemo.h中getName实现并生成DLL 编写JniDemo.h在JniDemo.c实现getName方法 ...
- JAVA通过JNI调用C++动态链接库CLL(一)
简介 使用eclipse新建JAVA项目并生成.h头文件 新建项目JniDemo 新建测试类JniTest并声明一个native的方法 使用Javah命令生成native方法的声明的C/C++头文件 ...
- Java通过-jni调用c语言
Java通过-jni调用c语言 一.编写JAVA程序 二.编译h头文件 三.编写C方法实现 四.生成对象文件 五.生成动态链接库 六.执行 一.编写JAVA程序 public class TestNa ...
- java在主程序修改函数输出,Java通过JNI调用CUDA
--NG 这段时间因为工作需要,要用到在java中调用cuda程序,但是令人蛋疼的是网上这方面的资料几乎没有,所以只好我自己摸索.我的想法是通过java的JNI接口调用cuda,但是很明显正常情况下是 ...
- Java通过JNI调用C++的DLL库
2019独角兽企业重金招聘Python工程师标准>>> Java通过JNI实现调用C++程序 好久没碰JNI这个东西了,刚工作的时候自己写过点东西,这么些年很少用到,最近一个项目又用 ...
- java通过jni调用虚拟游戏控制器vjoy
这几天打算做个游戏方向盘之类的,找到了vjoy,安装后会虚拟出1到16个游戏控制器,每个游戏控制器最多支持8轴128键,还有力反馈什么的,提供有skd可以编写client端控制这些游戏控制器的各个轴. ...
- 用java的jni调用C语言的API,实现带图形界面的一元稀疏多项式计算器
实现步骤: 1) 完成Java代码,编写好Java调用类. 2) 编译你的Java类. 3) 用javah生成编译好的class文件对应的C/C++ 函数的头文件. 4) 实现头文件中的函数原型,编写 ...
- Java利用JNI调用c++代码简易例子演示
点击打开链接 (提取码:8676) 一.首先简单交代一下两个问题: 1.什么是JNI - - - JNI的全名为Java Native Interface(Jav ...
最新文章
- 线程的生命周期其实没有我们想象的那么简单!!
- UA MATH567 高维统计 专题1 Supervised PCA Regression概述
- 洛谷P1040 加分二叉树运用区间DP(动态规划)求解
- 【新功能,新插件】-全新来袭,CSDN浏览器助手这一款无广告干净界面插件你值得拥有!
- 【深度】阿里巴巴万级规模 K8s 集群全局高可用体系之美
- 使用 .toLocaleString() 轻松实现多国语言价格数字格式化
- STL源码剖析 关联式容器 树 红黑树、二叉搜索树、平衡二叉搜索树
- 飞秋(FeiQ)2012版择日发布
- 修手机时创意被剽窃,男子向苹果索赔7万亿!是认真的吗?
- P1828 香甜的黄油 Sweet Butter (spfa)
- java jframe 设置背景图片_JAVA怎样设置JFrame的背景图片呢?谁能教教我怎么弄背景图片...
- Extjs4.x (MVC)Controller中refs以及Ext.ComponentQuery解析
- python语言的主网址-Python爬取网址中多个页面的信息
- Extjs基础入门视频教程
- 鸟哥的Linux私房菜基础学习篇(第四版)
- C语言炫酷的文件操作
- 樱(桜) - 堀江由衣 (日语-中文-罗马)
- 未来IT行业前景如何?
- Material Design实战
- IDEA使用database时,连接MySQL后schemas不显示数据库名的情况
热门文章
- ui设计是干啥的: ui设计师主要是做什么的呢
- 问题记录:Ubuntu中source运行.sh shell脚本报错:command not found 未找到命令
- 明翰英语教学系列之方法篇
- 108.【RabbitsMQ】
- brpc源码解析(二)—— brpc收到请求的处理过程
- 初级计算机信息处理员笔试题,初级信息处理技术员计算机系统基础知识考试卷模拟考试^题...
- Application应用程序
- 计算机小学数学辅助教学缺点及对策 论文,小学数学第二学段图形与几何领域的作业设计研究...
- 云计算基础知识培训讲义
- Apollo使用篇 - Apollo客户端的使用