项目中由于mail送信部分要求使用C实现,但缺要求使用JAVA的LOG输出。 因此这就需要使用C语言调用JAVA的LOG类进行输出。C语言如何调用JAVA,这就使用到了JAVA提供的JNI接口。查看了很多资料,发现都是JAVA调用C的实例较多,而C调用JAVA却使用很少,终于在官方网查看了些资料,
发现其实对于接口的使用还得求助于官网, 可惜那些都是英文,要是英文能好点,就不能看那么累了。痛苦啊。
作成了Demo。包含
JAVA通过JNI调用C,以及C通过JNII调用JAVA。
以下是C通过JNI调用JAVA。 用户LOG输出。
JAVA调用C:
无非如下步骤:
1.启动JVM,加载相应的class。
2..取得包含该CLASS的 env 环境。
3. 分别取得对应于JAVA中的method ID.
4. 实现对应于JAVA中的metho。 将每个类的方法,都作成相应的C函数。实现同样的功能。
(这样实现,函数清晰。功能明确)。 JAVA和C 能一一对应上。
其中要注意的是。JAVA类型到C类型的转换。
Env中的类型为 比如。JAVA: string ENV :jstring C: char*
JAVA: int ENV: jint C: int
1. LogJni.java JAVA的LOG输出类
/*
* 説明 :
*/
import java.util.*;
/**
* LogJni
*
* @version $Revision:.*$Date:$.*
*/
public class LogJni {
public LogJni() {
}
/**
* 送信?始
* @param obj ?用源?象(=this)
* @param iintLoginId 利用者ID
* @param istrSecondUserName ??先名
* @param gamenID 画面・功能ID
* @param excCnt ?理件数
* @param message Message
*/
public void startMail (Object obj, int iintLoginId, String istrSecondUserName, String gamenID,int excCnt, String message) {
System.out.println("startMail-Date:"+ new Date() + "LoginUser:" + iintLoginId
+ "--" + istrSecondUserName
+ " gamenID:" + gamenID
+ " excCnt: " + excCnt
+ " message:" + message);
}
/**
* 送信?了
* @param obj ?用源?象(=this)
* @param iintLoginId 利用者ID
* @param istrSecondUserName ??先名
* @param gamenID 画面・功能IDshi
* @param excCnt ?理件数
* @param message Message
*/
public void endMail (Object obj, int iintLoginId, String istrSecondUserName, String gamenID,int excCnt, String message) {
System.out.println("endMail-Date:"+ new Date() + "LoginUser:" + iintLoginId
+ "--" + istrSecondUserName
+ " gamenID:" + gamenID
+ " excCnt: " + excCnt
+ " message:" + message);
}
/**
* DB???始
* @param obj ?用源?象(=this)
* @param iintLoginId 利用者ID
* @param istrSecondUserName ??先名
* @param gamenID 画面・功能ID
* @param SQL ?行SQL
* @param message Message
*/
public void startDBAccess(Object obj, int iintLoginId, String istrSecondUserName, String gamenID, String SQL, String message) {
System.out.println("startDBAccess-Date:"+ new Date() + "LoginUser:" + iintLoginId
+ "--" + istrSecondUserName
+ " gamenID:" + gamenID
+ " SQL: " + SQL
+ " message:" + message);
}
/**
* DB???了
* @param obj ?用源?象(=this)
* @param iintLoginId 利用者ID
* @param istrSecondUserName ??先名
* @param gamenID 画面・功能ID
* @param SQL ?行SQL
* @param message Message
*/
public void endDBAccess(Object obj, int iintLoginId, String istrSecondUserName, String gamenID, String SQL, String message) {
System.out.println("endDBAccess-Date:"+ new Date() + "LoginUser:" + iintLoginId
+ "--" + istrSecondUserName
+ " gamenID:" + gamenID
+ " SQL: " + SQL
+ " message:" + message);
}
/**
*
* @param loginID 利用者ID
* @param gamenID 画面・功能ID
* @param errorMessage Error情?
* @param message Message
*/
public void logError(String loginID, String gamenID, String errorMessage, String message) {
System.out.println("Error- Date:"+ new Date() + "loginID:" + loginID + "gamenID:" + gamenID + " errorMessage:" + errorMessage + "message:" + message);
}
/**
*
* @param loginID 利用者ID
* @param gamenID 画面・功能ID
* @param message Message
*/
public void logStartApplication(String loginID, String gamenID, String message) {
System.out.println("logStartApplication-Date:"+ new Date() + " loginID:" + loginID + " gamenID:" + gamenID + " message:" + message);
}
/**
*
* @param loginID 利用者ID
* @param gamenID 画面・功能ID
* @param message Message
*/
public void logEndApplication(String loginID, String gamenID, String message) {
System.out.println("logEndApplication-Date:"+ new Date() + " loginID:" + loginID + " gamenID:" + gamenID + " message:" + message);
}
/**
* 送信?了
* @param obj ?用源?象(=this)
* @param iintLoginId 利用者ID
* @param istrSecondUserName ??先名
* @param gamenID 画面・功能ID
* @param mail Mail数据
* @param message Message
*/
public void mail (Object obj, int iintLoginId, String istrSecondUserName, String gamenID, String mail, String message) {
System.out.println("mail-Date:"+ new Date() + "LoginUser:" + iintLoginId
+ "--" + istrSecondUserName
+ " gamenID:" + gamenID
+ " mail: " + mail
+ " message:" + message);
}
}
2. java_jvm.h (启动JVM的。C头文件)
#ifndef JAVA_JVM_H_
#define JAVA_JVM_H_
#include
#include
#define PATH_SEPARATOR ';' /* define it to be ':' on Solaris */
#define USER_CLASSPATH "." /* װ�ص�CLASS·��*/
JavaVM *jvm; /* Pointer to a Java VM */
JNIEnv *env; /* Pointer to native method interface */
void envError();
int JvmCreate() {
jint res;
#ifdef JNI_VERSION_1_2
JavaVMInitArgs vm_args;
JavaVMOption options[2];
options[0].optionString ="-Djava.class.path=" USER_CLASSPATH;
options[1].optionString = "-verbose:jni";
vm_args.version = JNI_VERSION_1_2;
vm_args.options = options;
vm_args.nOptions = 1;
vm_args.ignoreUnrecognized = JNI_TRUE;
/* Create the Java VM */
res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
#else
JDK1_1InitArgs vm_args;
char classpath[1024];
vm_args.version = 0x00010001;
JNI_GetDefaultJavaVMInitArgs(&vm_args);
/* Append USER_CLASSPATH to the default system class path */
sprintf(classpath, "%s%c%s",
vm_args.classpath, PATH_SEPARATOR, USER_CLASSPATH);
vm_args.classpath = classpath;
/* Create the Java VM */
res = JNI_CreateJavaVM(&jvm, &env, &vm_args);
#endif /* JNI_VERSION_1_2 */
if (res < 0) {
fprintf(stderr, "Can't create Java VMn");
exit(1);
}
return 1;
}
void envError() {
if ((*env)->ExceptionOccurred(env)) {
(*env)->ExceptionDescribe(env);
}
}
void destoryJvm () {
(*jvm)->DestroyJavaVM(jvm);
}
#endif /*JAVA_JVM_H_*/
3. logjni.h 对应于 LogJni类的,C函数头文件。每个函数都对应于类中的一个方法实现。
#ifndef LOGJNI_H_
#define LOGJNI_H_
#include "./java_jvm.h"
jclass logcls; /* logClass */
jmethodID startMailId;
jmethodID endMailId;
jmethodID startDBAccessId;
jmethodID endDBAccessId;
jmethodID logErrorId;
jmethodID logStartApplicationId;
jmethodID logEndApplicationId;
jmethodID mailId;
void initClass() {
logcls = (*env)->FindClass(env, "LogJni");
if (logcls == 0) {
envError();
}
}
void initMethod() {
startMailId = (*env)->GetMethodID(env, logcls, "startMail", "(Ljava/lang/Object;ILjava/lang/String;Ljava/lang/String;ILjava/lang/String;)V");
if (startMailId == 0) {
envError();
}
endMailId = (*env)->GetMethodID(env, logcls, "endMail", "(Ljava/lang/Object;ILjava/lang/String;Ljava/lang/String;ILjava/lang/String;)V");
if (endMailId == 0) {
envError();
}
startDBAccessId = (*env)->GetMethodID(env, logcls, "startDBAccess", "(Ljava/lang/Object;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
if (startDBAccessId == 0) {
envError();
}
endDBAccessId = (*env)->GetMethodID(env, logcls, "endDBAccess", "(Ljava/lang/Object;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
if (endDBAccessId == 0) {
envError();
}
logErrorId = (*env)->GetMethodID(env, logcls, "logError", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
if (logErrorId == 0) {
envError();
}
logStartApplicationId = (*env)->GetMethodID(env, logcls, "logStartApplication", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
if (logStartApplicationId == 0) {
envError();
}
logEndApplicationId = (*env)->GetMethodID(env, logcls, "logEndApplication", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
if (logEndApplicationId == 0) {
envError();
}
mailId = (*env)->GetMethodID(env, logcls, "mail", "(Ljava/lang/Object;ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
if (mailId == 0) {
envError();
}
}
void logStartApplication(char *loginID, char *gamenID, char *message) {
jstring jstrLoginID;
jstring jstrGamenID;
jstring jstrMessage;
jstrLoginID = (*env)->NewStringUTF(env, loginID);
jstrGamenID = (*env)->NewStringUTF(env, gamenID);
jstrMessage = (*env)->NewStringUTF(env, message);
if (jstrLoginID == 0 || jstrGamenID == 0 || jstrMessage == 0) {
envError();
}
(*env)->CallStaticVoidMethod(env, logcls, logStartApplicationId, jstrLoginID, jstrGamenID, jstrMessage);
}
void logEndApplication(char *loginID, char *gamenID, char *message) {
jstring jstrLoginID;
jstring jstrGamenID;
jstring jstrMessage;
jstrLoginID = (*env)->NewStringUTF(env, loginID);
jstrGamenID = (*env)->NewStringUTF(env, gamenID);
jstrMessage = (*env)->NewStringUTF(env, message);
if (jstrLoginID == 0 || jstrGamenID == 0 || jstrMessage == 0) {
envError();
}
(*env)->CallStaticVoidMethod(env, logcls, logEndApplicationId, jstrLoginID, jstrGamenID, jstrMessage);
}
void logError(char *loginID, char *gamenID, char *errorMessage, char *message) {
jstring jstrLoginID;
jstring jstrGamenID;
jstring jstErrorMessage;
jstring jstrMessage;
jstrLoginID = (*env)->NewStringUTF(env, loginID);
jstrGamenID = (*env)->NewStringUTF(env, gamenID);
jstErrorMessage = (*env)->NewStringUTF(env, errorMessage);
jstrMessage = (*env)->NewStringUTF(env, message);
if (jstrLoginID == 0 || jstrGamenID == 0 || jstErrorMessage == 0 || jstrMessage == 0) {
envError();
}
(*env)->CallStaticVoidMethod(env, logcls, logErrorId, jstrLoginID, jstrGamenID, jstErrorMessage, jstrMessage);
}
void startMail(jobject obj, int loginId, char *secUsrName, char *gamenID, int excCnt, char *message) {
jstring jstrGamenID;
jstring jstrMessage;
jstring jstrSecUsrName;
jstrGamenID = (*env)->NewStringUTF(env, gamenID);
jstrMessage = (*env)->NewStringUTF(env, message);
jstrSecUsrName = (*env)->NewStringUTF(env, secUsrName);
if (jstrGamenID == 0 || jstrMessage == 0 || jstrSecUsrName == 0) {
envError();
}
(*env)->CallStaticVoidMethod(env, logcls, startMailId, obj, loginId, jstrSecUsrName, jstrGamenID, excCnt, jstrMessage);
}
void endMail(jobject obj, int loginId, char *secUsrName, char *gamenID, int excCnt, char *message) {
jstring jstrGamenID;
jstring jstrMessage;
jstring jstrSecUsrName;
jstrGamenID = (*env)->NewStringUTF(env, gamenID);
jstrMessage = (*env)->NewStringUTF(env, message);
jstrSecUsrName = (*env)->NewStringUTF(env, secUsrName);
if (jstrGamenID == 0 || jstrMessage == 0 || jstrSecUsrName == 0) {
envError();
}
(*env)->CallStaticVoidMethod(env, logcls, endMailId, obj, loginId, jstrSecUsrName,jstrGamenID, excCnt, jstrMessage);
}
void startDBAccess(jobject obj, int loginId, char *secUsrName, char *gamenID, char *sql, char *message) {
jstring jstrGamenID;
jstring jstrMessage;
jstring jstrSecUsrName;
jstring jstrSql;
jstrGamenID = (*env)->NewStringUTF(env, gamenID);
jstrMessage = (*env)->NewStringUTF(env, message);
jstrSecUsrName = (*env)->NewStringUTF(env, secUsrName);
jstrSql = (*env)->NewStringUTF(env, sql);
if (jstrGamenID == 0 || jstrMessage == 0 || jstrSecUsrName == 0 || jstrSql == 0) {
envError();
}
(*env)->CallStaticVoidMethod(env, logcls, startDBAccessId, obj, loginId, jstrSecUsrName,jstrGamenID, jstrSql, jstrMessage);
}
void endDBAccess(jobject obj, int loginId, char *secUsrName, char *gamenID, char *sql, char *message) {
jstring jstrGamenID;
jstring jstrMessage;
jstring jstrSecUsrName;
jstring jstrSql;
jstrGamenID = (*env)->NewStringUTF(env, gamenID);
jstrMessage = (*env)->NewStringUTF(env, message);
jstrSecUsrName = (*env)->NewStringUTF(env, secUsrName);
jstrSql = (*env)->NewStringUTF(env, sql);
if (jstrGamenID == 0 || jstrMessage == 0 || jstrSecUsrName == 0 || jstrSql == 0) {
envError();
}
(*env)->CallStaticVoidMethod(env, logcls, endDBAccessId, obj, loginId, jstrSecUsrName,jstrGamenID, jstrSql, jstrMessage);
}
void mail(jobject obj, int loginId, char *secUsrName, char *gamenID, char *mail, char *message) {
jstring jstrGamenID;
jstring jstrMessage;
jstring jstrSecUsrName;
jstring jstrMail;
jstrGamenID = (*env)->NewStringUTF(env, gamenID);
jstrMessage = (*env)->NewStringUTF(env, message);
jstrSecUsrName = (*env)->NewStringUTF(env, secUsrName);
jstrMail = (*env)->NewStringUTF(env, mail);
if (jstrGamenID == 0 || jstrMessage == 0 || jstrSecUsrName == 0 || jstrMail == 0) {
envError();
}
(*env)->CallStaticVoidMethod(env, logcls, mailId, obj, loginId, jstrSecUsrName,jstrGamenID, jstrMail, jstrMessage);
}
void initLogJni() {
JvmCreate();
initClass();
initMethod();
printf("the logjni.h initted the method of LogJni.classn");
}
#endif /*LOGJNI_H_*/
4. testjvm.c 测试demo的实现,检查输出。
#include
#include
#include "./logjni.h"
int main() {
initLogJni();
logStartApplication("1000", "00001", "start app");
logEndApplication("1000", "00001", "end app");
logError("1000", "00001", "error messages ", "logError");
startMail(NULL, 2000, "yunchat", "1000", 2, "startMail");
endMail(NULL, 1001, "yunchat", "1000", 2, "endMail");
startDBAccess(NULL, 1001, "yunchat", "1000", "select * from", "startDBAccess");
endDBAccess(NULL, 1001, "yunchat", "1000", "select * from", "endDBAccess");
mail(NULL, 1001, "yunchat", "1000", "error mail message", "mail");
destoryJvm();
return 0;
}
Makefile 我就不叙述了。 一定要注意。Jvm lib包的引入。