此文章写于2015.02.03,发布于网易博客,于2020.03.25迁移至此。
前言:记录学习过程便于记忆。经过多次尝试发现Java环境下的JNI调用与Andriod环境下的JNI调用有所不同,不知道是否正确。先记录一下Java环境下的JNI调用。
参考文章:http://www.cnblogs.com/youxilua/archive/2011/09/16/2178554.html
开始使用JNI:
先写一个Java文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package com.example.myjni; public class MyJni {
//使用JNI的关键字native,决定我们那些方法能在我们的C文件中使用,只须声明,不必实现
public native void display(); public native double sum(double x,double y);
//
用来读取我们写好的C语言编译好的dll,后缀是系统自己辨认
static { System.loadLibrary("myjni"); } public static void main(String[] args) { new MyJni().display(); System.out.println(new MyJni().sum(2.0, 3.0)); } }
|
把写好的类转换成.class文件
javac com\example\myjni\MyJni.java
把.class文件转换成头文件,成功的话就会在src目录下看到.h文件了
javah com.example.myjni.MyJni
打开.h文件可以看到
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h>
/* Header for class com_example_myjni_MyJni */ #ifndef _Included_com_example_myjni_MyJni #define _Included_com_example_myjni_MyJni #ifdef __cplusplus extern "C" { #endif
/* * Class: com_example_myjni_MyJni * Method: display * Signature: ()V */ JNIEXPORT void JNICALL Java_com_example_myjni_MyJni_display (JNIEnv *, jobject);
/* * Class: com_example_myjni_MyJni * Method: sum * Signature: (DD)D */ JNIEXPORT jdouble JNICALL Java_com_example_myjni_MyJni_sum (JNIEnv *, jobject, jdouble, jdouble); #ifdef __cplusplus } #endif #endif
|
native方法名称组成详解:
Java_为前缀 + 类的全名标识(包名+类名) + “_” + 方法名
写与.h文件对应的.c文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#include <jni.h> #include <stdio.h> #include "com_example_myjni_MyJni.h" JNIEXPORT void JNICALL Java_com_example_myjni_MyJni_display (JNIEnv *env, jobject obj) { printf("Hello MyJni!"); return; } JNIEXPORT jdouble JNICALL Java_com_example_myjni_MyJni_sum (JNIEnv *env, jobject obj, jdouble a, jdouble b) { return a + b; }
|
windows下编译成dll文件,linux下编译成so文件.这里只讲dll的,.so的以后尝试了再说
首先查看我们的jdk文件夹,查看其include文件夹下是否存在Jni.h头文件。在的话,继续,否则重新安装jdk。
使用mingw编译.c文件(确保前面已经安装了mingw)
gcc -Wall -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -I"C:\Program Files\Java\jdk1.6.0_45\include" -I"C:\Program Files\Java\jdk1.6.0_45\include\win32" -shared myjni.c -o myjni.dll
命令 | 简单介绍 |
-Wall -D_JNI_IMPLEMENTATION_ | 把我们的C文件编译成dll |
-Wl,--kill-at | 因为mingw默认是用@来进行分隔,会导致JNI机制不能读取,所以要删掉.. mingw官网解释 |
-I"C:\Program Files\Java\jdk1.6.0_45\include" -I"C:\Program Files\Java\jdk1.6.0_45\include\win32" | 导入我们用的的jni需要的头文件…盘符,文件夹自己修改 |
-shared -o | 输出配置,第一个参数为我们输出的名字(随便起),第二个参数为我们的C文件(随便起) |
没出什么提示的话就是成功的了…
运行我们的JNI(用eclipse的话,我们把编译好的dll放到项目根目录,注意不是代码根目录)
输出结果
貌似java本身的输出,优先级比较高?