JNI学习—errorlink错误

最近在重构代码时遇到了native 函数,一直找不见源码,问了一下老员工,他们告诉我那是JNI,才知道JNI是干什么的

JNI其实是Java Native Interface的简称,也就是java本地接口。它提供了若干的API实现了和Java和其他语言的通信(主要是C&C++)。也许不少人觉得Java已经足够强大,为什么要需要JNI这种东西呢?我们知道Java是一种平台无关性的语言,平台对于上层的java代码来说是透明的,所以在多数时间我们是不需要JNI的,但是假如你遇到了如下的三种情况之一呢?

  1. 你的Java代码,需要得到一个文件的属性。但是你找遍了JDK帮助文档也找不到相关的API。
  2. 在本地还有一个别的系统,不过他不是Java语言实现的,这个时候你的老板要求你把两套系统整合到一起。
  3. 你的Java代码中需要用到某种算法,不过算法是用C实现并封装在动态链接库文件(DLL)当中的。

对于上述的三种情况,如果没有JNI的话,那就会变得异常棘手了。就算找到解决方案了,也是费时费力。其实说到底还是会增加开发和维护的成本。

在网上搜了一下,现在主要在两种情况下经常用到JNI。一种是,在游戏处理图形算法中,用java调用native提高性能;还有一种就是要获取计算机硬件信息,例如在视频通话中要获取计算机的摄像头数据等。这两种情况经常用到JNI来调用其他语言。

回归正题,我本来计划重构一下项目包名的,可是更改项目中的包名之后,发现跑不通了,一直出现errorlink的错误,提示找不见native函数,我很郁闷,后来大哥告诉我,这种类应该是不能修改类名和包名的,修改之后JNI可能无法查找到要调用的函数。

于是我就实验了一下

1、新建java类

package com.yang.jnitest;

public class Test {

	public native void dispaly();
}

2、将java类编译成class文件

3、利用javah命令将class类文件转换成.h头文件

javah -jni com.yang.jnitest.test

如果类文件是在层次目录结构中,执行javah命令的时候要在com目录执行,否则会提示找不见类文件。执行成功后会看到响应的h文件。我的文件内容如下com_yang_jnitest_Test.h

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

#ifndef _Included_com_jnitest_Test
#define _Included_com_jnitest_Test
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_yang_jnitest_Test
 * Method:    dispaly
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_yang_jnitest_Test_dispaly
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

4、接下来构件Cpp文件实现头文件中的方法。我用的VS2010新建的CPP工程

在VS2010中新建win32项目,选择dll工程(空项目)

将上面的头文件拷贝到项目目录下,同时在java安装目录下找到jni.h和jni_md.h两个文件,也拷贝到项目目录下。

新建cpp文件,名字随便起

#include "jni.h"
#include "com_yang_jnitest_Test.h"
#include <iostream>

using namespace std;

JNIEXPORT void JNICALL Java_com_yang_jnitest_Test_dispaly
  (JNIEnv *env, jobject obj)
{
    cout << "Hello World" << endl;
    return;
}

项目目录如下:

在项目Priject的Debug目录下有Project.dll文件

5、修改原java类,让其加载dll库

package com.yang.jnitest;

public class Test {

	static
	{
		System.loadLibrary("Project");
	}
	public native void dispaly();
}

6、配置环境,测试运行

新建测试类

package com.yang.jnitest;

public class Display {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Test test = new Test();
		test.dispaly();
	}

}

我是在Eclipse中创建的java工程,在run configuration中配置Environment路径就可以了,将dll库的路径直接配置到java的运行环境中



运行java类,console中出现

Hello World

上面的项目比较简单,只是为了测试使用

无论修改java的类名包名还是修改VS项目的头文件的方法名,只要java类的完整包名+类名和头文件中的方法名称不对应,程序就无法执行

JNI调用native方法时会根据名称查找,例如我们的java类中的方法名为 com.yang.jnitest.Test.display,在dll文件中的方法名就是Java_com_yang_jnitest_Test_dispaly。两个方法名要是不对应就会出现errorlink的错误




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值