java JNI调用C++代码(给出一个简单java application示例和实际java web项目过程及错误解决)(一)

一、简单java application示例篇

转载请注明:https://blog.csdn.net/xitie8523/article/details/79926948

    本科毕业设计是图像分割相关的,在vs2013上写好了算法,需要用手机传图片到服务器,在服务器进行分割,服务器是用java写的,因此需要用java调用C++。刚来的菜鸟,一步一步走的,网上找了一篇博客跟着操作一下https://blog.csdn.net/lovesummerforever/article/details/25827199 以下为具体操作过程(和前面链接基本一致),可看前面链接的博客,懒得换页面的可以直接看下面

1、编写java源码

    新建一个工程(工程名字可以随意取,testJNI之类的 ),在src下建立com包,在com包下面建立java类Reliability.java。代码如下:

package com;
public class Reliability {
		  public native static int shanfei(int i); //声明方法,该方法用C++实现,定义为native,而static是为了
		  					//main里面调用时不用实例化,也可以不加static然后实例化调用方法
		  public static void main(String[] args) {  
			  System.loadLibrary("Reliability"); // 这里是加载dll
		     System.out.print(Reliability.shanfei(6));  //main里面调用了方法,该方法会用C++实现 
   }  
}

2、编译成.class和.h文件

将源文件编译成.class文件可以直接进入文件位置用javac命令编译,此时在.java文件同目录生成.class文件

 

进入编译成class文件的上一级目录(在这里是src下)用javah命令生成.h文件,命令行是:javah -classpath . -jni com.Reliability,将在src下生成com_Reliability.h文件



或者如果用myeclipse写的代码,保存后会自动生成.class文件,在bin目录下面的包com文件夹下,可在myeclipse中设置

              

同样转到上一级目录,这里是bin目录,用javah -classpath . -jni com.Reliability生成.h文件,上面两种方法选择哪一种都无关紧要,主要是为了生成.h文件。


3、C++新建dll

以上myeclipse这边就准备好了,打开vs2013,文件——>新建——>项目——>选择win32控制台程序(或者win32项目都可)——>改名称——>确定



点击下一步,选中Dll和空项目,然后完成


4、生成Dll文件

将com_Reliability.h作为头文件添加到工程里面,新建Reliability.cpp源文件,并将jni.h和jni_md.h(我是在myeclipse文件夹里找的)作为外部依赖文件导入工程,具体如下:

打开属性管理器——>右击——>点击属性——>转到VC++/常规/附加包含目录 ——>添加文件夹,这里我是把两个.h文件新建一个external_h(随便起的名)文件夹,然后将这个文件夹添加到附加包含目录里



生成的com_Relability.h文件(不用我们写,但是这段代码是有规律的)

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_Reliability */

#ifndef _Included_com_Reliability
#define _Included_com_Reliability
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_Reliability
 * Method:    shanfei
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_com_Reliability_shanfei
  (JNIEnv *, jclass, jint);

#ifdef __cplusplus
}
#endif
#endif

Reliability.cpp源文件:

#include<stdio.h>
#include<jni.h> 
#include<jni_md.h>
#include "com_Reliability.h"

JNIEXPORT jint JNICALL Java_com_Reliability_shanfei   //这是从.h文件中copy过来的方法声明
(JNIEnv *, jclass, jint p){
	int j = 2 * p;
	return j;

}

生成解决方案,然后会在相应的文件夹生成dll文件,进入文件夹将Reliability.dll拷贝到jdk下jre的bin目录下,然后运行myeclipse程序即可得到结果




5、一系列问题的总结:

(1)当我将Reliability.dll拷到工程目录下,或者拷到system32,将抛出 java.lang.UnsatisfiedLinkError:  no Reliability in java.library.path 异常,找不到这个dll,说明无法加载.dll文件,一般是放的位置不对,可用System.out.println( System.getProperty("java.library.path") );输出路径,然后选择其中一个,可能有些还是加载不了,可以多试几个,或者在file——>properties——>java build path 添加native library location。


(2)当我在myeclipse中编写Reliability.java,加载dll时采用了try  catch捕捉异常时,同样也是将Reliability.dll直接放在工程文件下面,将抛出一个找不到方法的异常java.lang.UnsatisfiedLinkError:  com.Reliability.shanfei(I)I,如下图。这有可能是dll放的位置不对,也可能是生成的.h文件的问题,要检查一下.h文件,特别在有包的时候,注意函数名是java__一级包__二级包__类名__方法名。即如果是package a.b.c;  类名是testJNI,方法是fun();  则应为java_a_b_c_testJNI_fun()


(3)我的电脑是64位,jdk配置的也是64位的,当我的vs2013采用的是debug32或者Release32时,出现以下情况(此时dll文件是放在jdk下jre的bin目录下)


上图表明我的dll是32位的,因为我是在vs2013 debug32下生成的解决方案,但是我的myeclipse环境是64位的,而这有冲突了,因此我就在debug64 位下编译生成了dll文件,将其放在jre下的bin目录下,就能得到结果了,注意生成的dll文件具体是在哪个文件夹,这个在vs2013的输出里面会有写,不要直接在放着代码的文件夹里直接复制。同理也会遇到64位的dll,32位的环境等问题,按照上面的思路统一就好了。

下一篇是图像处理的C++算法用到java  tomcat服务器的实战过程和遇到的莫名其妙的问题。


猜你喜欢

转载自blog.csdn.net/xitie8523/article/details/80314950