初次看见native关键字是自己在看Scanner类源码中传递System.in参数实现打印,之后转到System观看源码时看见native关键字,关于native关键字笔者表示,是Java与C语言的通讯接口,因为Java语言没有操作底层的条件,所以Java语言只好用C语言来操作底层部件,定义了native关键字。
System出现的native方法:
public final class System {
private static native void registerNatives();
.......
}
笔者观看代码时一脸懵,开始认为怎么会有这种方法,没有方法体。之后笔者也试了以下。顺便搜索一些前者资料。自己实现了一个。基于native关键字的加减法。
package com.java.jvm.demo;
public class JVMDemo {
public native int add(int i,int j);
public native int sub(int i,int j);
public native int mul(int i,int j);
public native int div(int i,int j);
}
因为native关键字时要用C去实现的方法,在编译时尤其注意,需要将类编译成C语言的头文件。
1、首先将类编译为.class的字节码文件
2、第一种方法是在.class的目录下使用javah命令编译,还有一种方法是在eclipse中配置编译器。具体就不详细说明。
3、类与包名一旦定义好不能随意更改,因为编译好的头文件会附带包、类名
之后编译的头文件代码:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_java_jvm_demo_JVMDemo */
#ifndef _Included_com_java_jvm_demo_JVMDemo
#define _Included_com_java_jvm_demo_JVMDemo
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_java_jvm_demo_JVMDemo
* Method: add
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_java_jvm_demo_JVMDemo_add
(JNIEnv *, jobject, jint, jint);
/*
* Class: com_java_jvm_demo_JVMDemo
* Method: sub
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_java_jvm_demo_JVMDemo_sub
(JNIEnv *, jobject, jint, jint);
/*
* Class: com_java_jvm_demo_JVMDemo
* Method: mul
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_java_jvm_demo_JVMDemo_mul
(JNIEnv *, jobject, jint, jint);
/*
* Class: com_java_jvm_demo_JVMDemo
* Method: div
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_java_jvm_demo_JVMDemo_div
(JNIEnv *, jobject, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
直接使用#include 去引用头文件编译时肯定会报错,因为C语言解释不了这个头文件,所以需要去Java JDK中寻找这个头文件解释器,头文件解释器在Java JDK安装目录:
D:\Program Files (x86)\Java\jdk1.7.0_72\include\jni.h
D:\Program Files (x86)\Java\jdk1.7.0_72\include\win32\jawt_md.h
D:\Program Files (x86)\Java\jdk1.7.0_72\include\win32\jni_md.h
将这三个文件复制在VC头文件库中,VC的头文件库位于VC的安装目录下:
D:\softwere\Microsoft Visual Studio\VC98\Include
将三个头文件解释器放入这里面之后,就可以进行组件.dll动态链接库了。然后编写的C语言源码:
#include "stdafx.h"
#include "jni.h"
#include "com_java_jvm_demo_JVMDemo.h"
JNIEXPORT jint JNICALL Java_com_java_jvm_demo_JVMDemo_add
(JNIEnv *en, jobject obj, jint x, jint y)
{
printf("hello welcome to add method ! \n");
return (x+y);
}
/*
* Class: com_java_jvm_demo_JVMDemo
* Method: sub
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_java_jvm_demo_JVMDemo_sub
(JNIEnv *en, jobject obj, jint x, jint y)
{
return (x-y);
}
/*
* Class: com_java_jvm_demo_JVMDemo
* Method: mul
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_java_jvm_demo_JVMDemo_mul
(JNIEnv *en, jobject obj, jint x, jint y)
{
return (x*y);
}
/*
* Class: com_java_jvm_demo_JVMDemo
* Method: div
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_com_java_jvm_demo_JVMDemo_div
(JNIEnv *en, jobject obj, jint x, jint y)
{
return (x/y);
}
注意:
1、C语言编译不能是debug版本,需要转换为Release版本
2、如果C语言编译器32位,那么Java必须是32位,不然抛出UnsatisfiedLinkError异常:32 bit …amd 64等解释异常。
编译成功之后
拿到.dll文件复制在java项目中:
之后运行是不可能的,这辈子都不能,还需要配置一个Java的 Native library location
测试:
package com.java.jvm.demo;
public class Demo {
static{
System.loadLibrary("jni");
}
public static void main(String[] args) {
//Scanner
//System
JVMDemo demo = new JVMDemo();
try {
int a = demo.add(2, 3);
int s = demo.sub(3, 2);
int m = demo.mul(2, 3);
int d = demo.div(4, 2);
System.out.println("method add() = " + a);
System.out.println("method sub() = " + s);
System.out.println("method mul() = " + m);
System.out.println("method div() = " + d);
} catch (UnsatisfiedLinkError e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
运行结果:
总结:每次查看JDK源码时候,总是能刷新自己对Java语言的世界观,总是让人吃惊。也有点小惊喜。
有不懂的可以直接回复笔者,笔者不定期回复。欢迎各位侠义之士共同进步。