一、实现工具
Eclipse的java工程
vs2010的dll库
二、实现过程
1、在vs中生成dll动态链接库
2、然后在java中使用dll库
三、实现流程
1、在java类中创建native方法
2、使用javah方法生成jni头文件
3、把头文件拷贝到vs项目c文件同目录下,然后添加到头文件中
4、引用头文件,实现对应的jni方法
5、生成dll动态内库
6、调用native方法
四、实现
数据类型
基本数据
Java基本数据类型与JNI数据类型的映射关系(在C/C++中用特定的类型来表示Java的数据类型)
boolean jboolean
byte jbyte
char jchar
short jshort
int jint
long jlong
float jfloat
double jdouble
void void
引用类型(对象)
String jstring
object jobject
基本类型的数组也是引用类型
byte[] jByteArray
Class jclass
java项目目录结构
1、创建native方法
Test.java
package com.test;
import java.util.Random;
import java.util.UUID;
public class Test {
static{
System.loadLibrary("Test1");
}
public String key = "zhangsan";
public static int count = 9;
public native static String getStringFromC();
public native String getString2FromC(int i);
public native String accessField();
public native void accessStaticField();
public native void accessMethod();
public native void accessStaticMethod();
public static void main(String[] args) {
Test t=new Test();
System.out.println(""+t.getStringFromC());
System.out.println(""+t.getString2FromC(6));
System.out.println(""+t.accessField());
t.accessStaticField();
System.out.println("修改之后的count::::"+count);
t.accessMethod();
t.accessStaticMethod();
}
/**
* 产生一个指定大小的随机数
* @param max
* @return
*/
public int genRandomInt(int max){
Random random = new Random();
return random.nextInt(max);
}
/**
* 删除UUID随机字符串
* @return
*/
public static String getUUID(){
UUID uuid = UUID.randomUUID();
return uuid.toString().replaceAll("-", "");
}
}
2、使用javah生成jni头文件
D:\Eclipse\workspaces\TestJni\src>javah com.test.Test
注意:到当前类名即可,不用加.java后缀,否则会提示找不到
有时候类中有中文注释也可能生成失败
com_test_Test.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class com_test_Test */
#ifndef _Included_com_test_Test
#define _Included_com_test_Test
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_test_Test
* Method: getStringFromC
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_test_Test_getStringFromC
(JNIEnv *, jclass);
/*
* Class: com_test_Test
* Method: getString2FromC
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_test_Test_getString2FromC
(JNIEnv *, jobject, jint);
/*
* Class: com_test_Test
* Method: accessField
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_test_Test_accessField
(JNIEnv *, jobject);
/*
* Class: com_test_Test
* Method: accessStaticField
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_test_Test_accessStaticField
(JNIEnv *, jobject);
/*
* Class: com_test_Test
* Method: accessMethod
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_test_Test_accessMethod
(JNIEnv *, jobject);
/*
* Class: com_test_Test
* Method: accessStaticMethod
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_test_Test_accessStaticMethod
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
3、然后拷贝生成的头文件到vs项目下
把拷贝的头文件放入源文件夹下,然后点击头文件,添加->现有项,然后选中jni.h和jni_md.h和生成的头文件即可
注意:1、因为我们是编写jni所以,需要导入jni.h和jni_md.h,文件来自jdk,搜索到拷贝到源文件目录下添加即可
2、修改生成的头文件中的#include <jni.h> 为 #include "jni.h"
3、修改jni.h头文件中的#include <jni_md.h>为 #include "jni_md.h"
4、实线生成的头文件中的方法
test.c
#define _CRT_SECURE_NO_WARNINGS
#include "com_test_Test.h"
#include <string.h>
JNIEXPORT jstring JNICALL Java_com_test_Test_getStringFromC(JNIEnv * env, jclass jclas){
return (*env)->NewStringUTF(env, "C String");
}
JNIEXPORT jstring JNICALL Java_com_test_Test_getString2FromC(JNIEnv *env, jobject jobj, jint num){
return (*env)->NewStringUTF(env, "C String " + num);
}
//1、访问非静态属性
JNIEXPORT jstring JNICALL Java_com_test_Test_accessField(JNIEnv *env, jobject jobj){
//jobj是class的对象
jclass cls = (*env)->GetObjectClass(env, jobj);
//属性名称,属性签名
jfieldID fid = (*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;");
//获取对应的属性
jstring jstr = (*env)->GetObjectField(env, jobj, fid);
//jstring变成c的字符串
char* c_str = (*env)->GetStringUTFChars(env, jstr, JNI_FALSE);
//得到拼接的字符串
char text[20] = "super ";
strcat(text, c_str);
//把c的字符串变为jstring
jstring new_jstr = (*env)->NewStringUTF(env, text);
(*env)->SetObjectField(env, jobj, fid, new_jstr);
return new_jstr;
}
//访问静态属性
JNIEXPORT void JNICALL Java_com_test_Test_accessStaticField(JNIEnv *env, jobject jobj){
jclass cls = (*env)->GetObjectClass(env, jobj);
jfieldID fid = (*env)->GetStaticFieldID(env, cls, "count", "I");
jint count = (*env)->GetStaticIntField(env, cls, fid);
count++;
(*env)->SetStaticIntField(env, cls, fid, count);
}
//2.访问java非静态方法
JNIEXPORT void JNICALL Java_com_test_Test_accessMethod(JNIEnv *env, jobject jobj){
jclass cls = (*env)->GetObjectClass(env, jobj);
jmethodID mid = (*env)->GetMethodID(env, cls, "genRandomInt", "(I)I");
jint random = (*env)->CallIntMethod(env, jobj, mid, 200);
printf("random num:%ld", random);
}
//访问java静态方法
JNIEXPORT void JNICALL Java_com_test_Test_accessStaticMethod(JNIEnv *env, jobject jobj){
jclass cls = (*env)->GetObjectClass(env, jobj);
jmethodID mid = (*env)->GetStaticMethodID(env, cls, "getUUID", "()Ljava/lang/String;");
jstring uuid = (*env)->CallStaticObjectMethod(env, cls, mid);
char* uuid_str = (*env)->GetStringUTFChars(env, uuid, JNI_FALSE);
//拼接
char filename[100];
sprintf(filename, "D://%s.txt", uuid_str);
FILE *fp = fopen(filename, "w");
fputs("i love jason", fp);
fclose(fp);
}
注意:1、使用javap -s 文件路径得到方法的签名
一定要在bin目录下
5、生成dll类库
注意:
默认是Win32如果有x64就直接选择,没有就直接新建
配置类型一定要是动态库,默认为应用程序,否则会提示找不到入口
如果是x64一定要到x64的文件夹去找对应的dll文件
6、然后把dll内库复制到项目的根目录下即可
7、加载类库,调用native方法