1、native关键字简介
原则上来说,100%纯的Java代码是非常好的,但你有时也想使用其他语言的代码,这种代码被称为本地代码。本地代码的提供可以让我们在Java中使用(c/c++)编写的代码,而这种功能的实现要依靠Java平台提供的与本地(c/c++)代码进行互操的API——JNI(Java Native Interface),它被称之为Java本地接口。
2、native关键字使用的一些小建议
- 你的应用需要访问的系统特性和设备通过Java平台是无法实现的。
- 你已经有了大量的测试过和调试过的用另一种语言编写的代码 , 并且知道如何将其导出到所有的目标平台上。
- 通过基准测试,你发现所编写的 Java 代码比用其他语言编写的等价代码要慢得多。
3、native使用的一个例子
为简单说明native的用法,我们以输出Hello World!为例。
(1)操作前的准备:
- 本实例使用Windows 10系统进行操作。
- JDK版本:14.0.2
- MinGW版本: 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project)
- 本实例的所有文件将组织在
D:\Native
中。
(2)在D:\Native
中创建Java文件HelloNative.java
,并在文件中写入如下内容:
class HelloNative {
public static native void green();
}
(3)编译以上文件,查看目录可以发现产生了一个class文件。
D:\Native>javac HelloNative.java
D:\Native>dir
驱动器 D 中的卷是 WPKY
卷的序列号是 1C7F-A8C8
D:\Native 的目录
2021/04/17 17:27 <DIR> .
2021/04/17 17:27 <DIR> ..
2021/04/17 17:27 212 HelloNative.class
2021/04/17 17:25 59 HelloNative.java
2 个文件 271 字节
2 个目录 73,375,858,688 可用字节
(4)使用javac -h . file
命令在父目录下自动产生头文件。
注意:
.
和-h
、file
之间都有一个空格。- 如果你的JDK版本是JDK 10以下的本版要使用
javah
替换java -h
,因为在JDK10及以上版本已经删除了javah
。 - 如果
-h
和file
之间没有.
,将提示以下信息:
D:\Native>javac -h HelloNative.java
错误: 无源文件
- 必须加上文件后缀名
.java
,否则将提示以下信息:
D:\Native>javac -h . HelloNative
错误: 仅当显式请求注释处理时才接受类名称 'HelloNative'
1 个错误
正确使用javac -h . HelloNative.java
命令后将在父目录下自动产生一个头文件,如下图:
头文件内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloNative */
#ifndef _Included_HelloNative
#define _Included_HelloNative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloNative
* Method: green
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloNative_green
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
(5)在同级目录下创建一个C源文件,并将头文件中的以下代码复制到刚才创建的源文件中。
JNIEXPORT void JNICALL Java_HelloNative_green
(JNIEnv *, jclass);
#ifdef __cplusplus
}
创建的C源文件的最后内容如下:
#include "HelloNative.h"
#include<stdio.h>
JNIEXPORT void JNICALL Java_HelloNative_green(JNIEnv * env, jclass cl){
printf("Hello World!");
}
注意:
- 要将
(JNIEnv *, jclass);
的分号换成{
,同时在参数列表中加上env
和cl
,否则进行编译产生共享文件时将提示以下信息:
D:\Native>gcc -m64 -Wl,--add-stdcall-alias -I
HelloNative.dll HelloNative.c
HelloNative.c: In function 'Java_HelloNative_green':
HelloNative.c:3:47: error: parameter name omitted
JNIEXPORT void JNICALL Java_HelloNative_green(JNIEnv *, jclass){
^~~~~~~~
HelloNative.c:3:57: error: parameter name omitted
JNIEXPORT void JNICALL Java_HelloNative_green(JNIEnv *, jclass){
(6)编译产生共享文件。
使用命令gcc -m64 -Wl,--add-stdcall-alias -I jdk\include -I jdk\include\win32\ -shared -o HelloNative.dll HelloNative.c
生成共享文件,其中jdk
代表你的JDK安装路径,也即JDK中bin目录的父目录,不要选中bin目录。正确编译后将在同级目录下产生HelloNative.dll
文件。如图:
(7)创建一个java文件进行测试。
class HelloNativeTest{
static
{
System.loadLibrary("HelloNative");
}
public static void main(String[] args){
HelloNative.green();
}
}
(8)编译并运行文件。
最后将在控制台中输出"Hello World!"。