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 与硬件对接 java软硬件交互_native

然后我们编译这个java文件得到.class文件

java 与硬件对接 java软硬件交互_交互_02


再用.class文件+jni+javah得到一个c文件头 :

java 与硬件对接 java软硬件交互_java 与硬件对接_03


效果如下:

java 与硬件对接 java软硬件交互_交互_04


头文件内容(对比jni数据类型,能看的出来都是与java的基本类型对应的):

java 与硬件对接 java软硬件交互_native_05

2.在c编译一个dll,包含上面的头与其实现。

我用的dev-c++,创建一个新dll项目,

将jni.h和jni_md.h包含到项目里(在jdk-include目录下)

然后实现头文件方法

java 与硬件对接 java软硬件交互_java_06

编译执行生成dll

java 与硬件对接 java软硬件交互_java_07


复制dll到项目根目录

java 与硬件对接 java软硬件交互_c语言_08


再执行.class文件就能实现JAVA与C的交互:效果如下

java 与硬件对接 java软硬件交互_native_09

这样在不同平台的虚拟机上,就能通过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框架来实现调用。