java跨平台是java一个具有十分优势的语言特性,为什么能跨平台?我想除了java的jvm本身在语言设计时,采用了字节码这样一种能运行在虚拟机上的指令占了50的功劳,还有50%来自基于C的对不同平台硬件的优良支持。
今天我了解学习了java的一个关键字:native,让我对java的理解又多了一些。
从概念上:native是一个修饰方法的关键字,被修饰的方法叫本地方法。这些方法都是非JAVA语言实现的方法,可以去调其它语言的库类,与abstract关键字相似却又相反。
为什么要有native关键字呢,因为java并不能真正的与硬件设备的底层交互,这些工作一向是交给c或c++实现的。
java 通过jni把java代码转化成c语言头文件,在让C去实现具体的交互工作,实现真正的跨平台。
C语言对硬件的交互结果又通过JNI与C的dll动态加载库传递到java应用层。
今天我主要学习一个dll与java间的交互。
我们实现一个把字符串带到c语言,又让c带到java来,
用dll做动态加载库。
1.首先编写一个带有native的方法的类。
并指定一个dll的加载名称。
如下:
然后我们编译这个java文件得到.class文件
再用.class文件+jni+javah得到一个c文件头 :
效果如下:
头文件内容(对比jni数据类型,能看的出来都是与java的基本类型对应的):
2.在c编译一个dll,包含上面的头与其实现。
我用的dev-c++,创建一个新dll项目,
将jni.h和jni_md.h包含到项目里(在jdk-include目录下)
然后实现头文件方法
编译执行生成dll
复制dll到项目根目录
再执行.class文件就能实现JAVA与C的交互:效果如下
这样在不同平台的虚拟机上,就能通过java实现真正意义上的跨平台了。
附上代码:
java
/**
* @author
* @version 1.0
* @description 通过native向C语言说hello
* @date 2021-12-27 16:56
**/
public class JavaNativeToC {
static {
System.loadLibrary("helloWorldToJavaDll");
}
public static void main(String[] args) {
System.out.println("C say: " + JavaNativeToC.sayHelloToCByNative("hello C,I'm an STATIC NATIVE from JAVA !"));
}
/**
* 通过native向C语言说hello,c会返回什么呢
*
* @author
* @date 2021/12/27 16:57
**/
native private static String sayHelloToCByNative(String oneWords);
}
c-dll
/* Replace "dll.h" with the name of your header */
#include "JavaNativeToC.h"
#include <windows.h>
JNIEXPORT jstring JNICALL Java_JavaNativeToC_sayHelloToCByNative(JNIEnv *env, jclass cls, jstring jstr) {
const char *pstr = NULL;
jboolean isCopy; // 返回JNI_TRUE表示原字符串的拷贝,返回JNI_FALSE表示返回原字符串的指针
pstr = (*env)->GetStringUTFChars(env, jstr, &isCopy);
printf("JAVA-native-static say: %s \n", pstr);
(*env)->ReleaseStringChars(env, jstr, pstr);
return (*env)->NewStringUTF(env, "hello JAVA-native-static,I'm C,welcome to you!");
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
switch (fdwReason) {
case DLL_PROCESS_ATTACH: {
break;
}
case DLL_PROCESS_DETACH: {
break;
}
case DLL_THREAD_ATTACH: {
break;
}
case DLL_THREAD_DETACH: {
break;
}
}
/* Return TRUE on success, FALSE on failure */
return TRUE;
}
在java中还可以通过JNI框架来实现调用。