JNI实现java调用C语言实现底层代码
在class="superseo">java中,很多sun公司定义的java代码中, 都有native方法, 它没有方法体,只有参数和返回值。这个方法究竟是什么呢?它其还是一个java和C/C++的一个接口方法。通过native方法, java可是实现调用C/C++的函数。
多数人是通过JNI和NIO的方法实现。当前我学习的是JNI
JNI: java native interface (java本地接口调用)。java代码中,使用native方法,我们就以所有学习程序设计语言第一个程序HelloWorld来做介绍。
具体实现:
1)java部分代码:
public class HelloWorld{
static{
System.loadLibrary("src/test1");
}
public native void display();
public static void main(String[] args){
new HelloWorld().display();
}
}
jvm机制简单介绍一下,jvm采用懒加载机制,在调用一个类的时候,采取加载。在HelloWorld类中, static静态块加载进内存中,
System.loadLibrary("src/test1");会自动调用src/test1这个文件,该文件就是C/C++生成的.dll依赖文件。这里是test1.dll。当加载的时候,就会调用.dll文件,调用C代码。
那么我们先将Helloworld.java 通过javac编译,然后使用javah命令,会生成HelloWorld.h头文件,用于C/C++中加入到代码中。使用 :javah HelloWorld
HelloWorld.h头文件,会看到是一些宏定义什么的。
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloWorld
* Method: display
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloWorld_display
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
这里的 NIEXPORT void JNICALL Java_HelloWorld_display (JNIEnv *, jobject);就是生成的C类型的java方法。
2)编写C/C++,,使用visual stuio 2010
新建cpp文件,文件名和java中 System.loadLibrary("src/test1");这个test1文件名相同, 因为到时候生成的dll文件时以CPP文件名命名。
新建步骤:win32项目--->dll(这里输出符号打钩)
JNIEXPORT void JNICALL Java_HelloWorld_display(JNIEnv *, jobject);
函数是写了,但是函数从哪儿来??当然是HelloWorld.h中声明咯,就在cpp文件中引入该头文件。而 JNIEnv *,等这些类型,都是哪里定义的呢?看Helloworld.h头文件,,它引入了个jni.h头文件,这个头文件其实在JDK安装目录下%JAVA_HOME%\include 而jni.h又引用了jni_md.h 这个在 %JAVA_HOME%\include\win32目录下,然后把这2个头文件拷贝到C工程下。
运行,生成dll,将它拷贝到java目录中, 但是运行的时候发现报异常, java.lang.UnsatisfiedLinkError: Couldn ‘t load testcpp: findLibrary returned 。。Can't load IA 32-bit .dll on a AMD 64-bit platform,,是dll的格式为32位的,而平台式64位的, 百度,,然后知道了,将运行那里本身是win32,改成x64就OK。编译,重新拷贝一次dll,运行,就可以输出Hellowolrd这个字符串,,是不是很神奇?