C程序控制Java端代码
整个示例程序有 JniFuncMain类(包含本地方法声明)、JniTest对象和jnifunc.dll(包含本地方法的具体实现)三部分组成。在JniFuncMain类的本地方法中调用JniTest对象的方法和成员变量,具体由C++代码实现,包含在jnifunc.dll中。
1、 编写
Java代码
JniFuncMain.java和JniTest.java
JniFuncMain.java
-
public class JniFuncMain
-
{
-
private static int staticIntField = 300;
-
-
//加载本地库jnifunc.dll
-
static { System.loadLibrary("jnifunc");}
-
-
//本地方法声明
-
public static native JniTest createJniObject();
-
-
public static void main(String[] args)
-
{
-
//从本地代码生成JniTest对象
-
System.out.println("[Java] createJniObject()调用本地方法");
-
try{
-
JniTest jniObj = createJniObject();
-
-
//调用JNiTest对象的方法
-
jniObj.callTest();
-
}catch(Exception e)
-
{
-
System.out.println(e.getMessage());
-
}
-
-
}
-
}
JniTest.java
-
class JniTest
-
{
-
private int intField;
-
-
//构造方法
-
public JniTest(int num)
-
{
-
intField = num;
-
System.out.println("[Java}调用JniTest对象的构造方法:intField = " + intField);
-
}
-
//此方法由JNI本地函数调用
-
public int callByNative(int num)
-
{
-
System.out.println("[Java] JniTest对象的callByNative(" + num + ")调用");
-
return num;
-
}
-
-
-
public void callTest()
-
{
-
System.out.println("[Java] JniTest对象的callTest方法调用:intField = " + intField);
-
}
-
}
2、 编译Java代码
D:\Users\lusi\JNI\JNI-2>
Javac JniFuncMain.java
3、 生成C语言需要包含的头文件JniFuncMain.h
D:\Users\lusi\JNI\JNI-2>
Javah JniFuncMain
JniFuncMain.h:
-
* DO NOT EDIT THIS FILE - it is machine generated */
-
#include <jni.h>
-
/* Header for class JniFuncMain */
-
-
#ifndef _Included_JniFuncMain
-
#define _Included_JniFuncMain
-
#ifdef __cplusplus
-
extern "C" {
-
#endif
-
/*
-
* Class: JniFuncMain
-
* Method: createJniObject
-
* Signature: ()LJniTest;
-
*/
-
JNIEXPORT jobject JNICALL Java_JniFuncMain_createJniObject
-
(JNIEnv *, jclass);
-
-
#ifdef __cplusplus
-
}
-
#endif
-
#endif
4、 编写C++代码 jnifunc.cpp
-
#include "JniFuncMain.h"
-
#include <stdio.h>
-
-
JNIEXPORT jobject JNICALL Java_JniFuncMain_createJniObject(JNIEnv * env, jclass clazz)
-
{
-
jclass targetClass;
-
jmethodID mid;
-
jobject newObject;
-
jstring helloStr;
-
jfieldID fid;
-
jint staticIntField;
-
jint result;
-
-
// C程序控制Java端代码
-
-
//1、访问类静态成员域,获取JniFuncMain类的staticIntField变量值
-
fid = env->GetStaticFieldID(clazz, "staticIntField", "I");
-
staticIntField = env->GetStaticIntField(clazz, fid);
-
printf("[CPP]获取JniFuncMain类的staticIntField值\n");
-
-
//查找生成对象的类
-
targetClass = env->FindClass("JniTest");
-
//该函数用于加载本地定义的类。它将搜索由CLASSPATH 环境变量为具有指定名
-
//称的类所指定的目录和 zip 文件
-
// FindClass的参数名必须是:类全名(即包名后跟类名,之间由“/”分隔)
-
-
//2、查找构造方法
-
mid = env->GetMethodID(targetClass, "", "(I)V");
-
// 1."(I)V"是用javap反编译工具反编译JniTest的成员
-
// 获得的签名。GetMethodID方法会根据此签名找到该方法。
-
// 反编译class文件命令,例子: javap -s -p 类名
-
// 2. 第一个参数不是JNIEnv*类型是因为此代码是c++代码。原理类似于this指针。
-
// 3. 只有获得构造方法时第2个参数是<init>,其他的,直接传入方法名称即可。
-
//3、生成JniTest对象(返回对象的引用)
-
printf("[CPP]JniTest对象生成\n");
-
newObject = env->NewObject(targetClass, mid, 100);
-
-
//4、调用对象的方法
-
mid = env->GetMethodID(targetClass, "callByNative", "(I)I");
-
result = env->CallIntMethod(newObject, mid, 200);
-
-
//5、访问对象的成员变量,设置JniObject对象的intField值
-
fid = env->GetFieldID(targetClass, "intField", "I");
-
printf("[CPP]设置JniTest对象的intField值为200\n");
-
env->SetIntField(newObject, fid, result);
-
-
//返回对象的引用
-
return newObject;
-
}
5、 生成C共享库
D:\Users\lusi\JNI\JNI-2>
cl -I "D:\Program
Files\Java\jdk1.8.0_25\include" -I "D
\Program Files\Java\jdk1.8.0_25\include\win32" –LD jnifunc.cpp -Fejnifunc.dll
6、 执行Java程序
D:\Users\lusi\JNI\JNI-2> java JniFuncMain
阅读(1557) | 评论(0) | 转发(0) |