我用的ubuntu,需要用c调用java程序,现在将编写好没问题的java程序打包乘jar文件,jni直接调用的方法是edu.unika.aifb.jnikernel.KernelManager里的initialize,initialize里有一句Class backendClass = Class.forName(kernelClassString);这个kernelClassString值为“
edu.unika.aifb.kernels.examples.Linear”,这个类我确保确确实实已经写好放那了,但是这个问题一直解决不掉。希望有过这方面经验的同仁能拉小弟一把,不深感激。
如果需要的话 c程序在此,java程序和异常在附件里
[code="c"]
/**
- JNI Kernel Extension for SVMlight - http://www.aifb.uni-karlsruhe.de/WBS/sbl/software/jnikernel/
- v0.9 (c) 19.01.2007 Stephan Bloehdorn, Institute AIFB, University of Karlsruhe, Germany
- v1.0 (c) 25.05.2007 Stephan Bloehdorn, Institute AIFB, University of Karlsruhe, Germany
- v1.1 (c) 29.05.2007 Stephan Bloehdorn, Institute AIFB, University of Karlsruhe, Germany
- v1.2 (c) 04.07.2007 Stephan Bloehdorn, Institute AIFB, University of Karlsruhe, Germany */
extern "C" {
include "svm_common.h"
include "kernel.h"
}
#include
#include
#include "jni.h"
#include
#include
#define __VERSION "v1.2"
#define __MAX_LINE 1024
#define __MANAGERCLASS "edu/unika/aifb/jnikernel/KernelManager"
#define __CLASS_PARAM "jnikernel.class"
#define __OPTION_PARAM "jvm.option"
#define __NORMALIZE_PARAM "jnikernel.normalize"
using namespace std;
bool initialized = false;
//jvm references
JNIEnv *env;
JavaVM *jvm;
//backend references
jclass backend;
jmethodID m_initialize;
jmethodID m_evaluate;
// cosine normalization options and cache
bool normalize = false;
//REMOVE map norms;
//functions
void initialize(char* param);
void printErrorAndExit(char* message);
void printFileErrorAndExit(char* param);
extern "C" double custom_kernel(KERNEL_PARM *kernel_parm, SVECTOR *a, SVECTOR *b) {
if(!initialized) initialize(kernel_parm->custom);
//determine number of array elements...
int anum = 0;
int bnum = 0;
WORD *wordpointer;
wordpointer=a->words;
while (wordpointer->wnum) {
anum++;
wordpointer++;
}
wordpointer=b->words;
while (wordpointer->wnum) {
bnum++;
wordpointer++;
}
//create java arrays and copy values
jlongArray arg1indicesJ = env->NewLongArray(anum);
jfloatArray arg1valuesJ = env->NewFloatArray(anum);
jlongArray arg2indicesJ = env->NewLongArray(bnum);
jfloatArray arg2valuesJ = env->NewFloatArray(bnum);
if (arg1indicesJ==NULL||arg2indicesJ==NULL||arg1valuesJ==NULL||arg2valuesJ==NULL) {
if (env->ExceptionCheck()) {
printf("\n");
env->ExceptionDescribe();
}
printErrorAndExit("Error when creating JNI array(s).");
}
jlong * arg1indices = env->GetLongArrayElements(arg1indicesJ, 0);
jlong * arg2indices = env->GetLongArrayElements(arg2indicesJ, 0);
float * arg1values = env->GetFloatArrayElements(arg1valuesJ, 0);
float * arg2values = env->GetFloatArrayElements(arg2valuesJ, 0);
for (int i=0;i<anum;i++) {
arg1indices[i]=a->words[i].wnum;
arg1values[i]=a->words[i].weight;
}
for (int i=0;i<bnum;i++) {
arg2indices[i]=b->words[i].wnum;
arg2values[i]=b->words[i].weight;
}
//release the changes back to java arrays
env->ReleaseLongArrayElements(arg1indicesJ, arg1indices, 0);
env->ReleaseLongArrayElements(arg2indicesJ, arg2indices, 0);
env->ReleaseFloatArrayElements(arg1valuesJ, arg1values, 0);
env->ReleaseFloatArrayElements(arg2valuesJ, arg2values, 0);
//construct java strings out of userdefined fields
jstring arg1stringJ = env->NewStringUTF(a->userdefined);
jstring arg2stringJ = env->NewStringUTF(b->userdefined);
if (arg1stringJ==NULL||arg2stringJ==NULL) {
if (env->ExceptionCheck()) {
printf("\n");
env->ExceptionDescribe();
}
printErrorAndExit("Java exception when creating JNI string(s) (see stderr).");
}
// jclass cls=env->FindClass("\home\zhenchao\workspace\svm_light\HW");
// if (!cls) {
// printf("Class %s not found\n");
// return -1;
// }
//
// jmethodID mid=env->GetStaticMethodID(cls,"get","()I");
// if (!mid) {
// printf("Method %s of Class %s not found\n");
// return -1;
// }
// double test_result=env->CallStaticDoubleMethod(cls,mid);
// printf("%f\n",test_result);
//call backend kernel evaluation, check for java exceptions
double result = env->CallStaticDoubleMethod(backend,m_evaluate,arg1indicesJ,arg1valuesJ,arg1stringJ,arg2indicesJ,arg2valuesJ,arg2stringJ);
if (env->ExceptionCheck()) {
printf("\n");
env->ExceptionDescribe();
printErrorAndExit("Java exception when computing kernel (see stderr).");
}
if(result!=0&&normalize) {
/*
* NOTE:
* Internally, we "abuse" the "twonorm_sq" field of the SVECTOR to allow
* for fast retrieval of the squared norms.
* To indicate that the value is not the original vector length but
* the squared kernel norm supplied by this kernel, we store inverted
* (i.e. negative) values.
*
* This is obviously a hack, but we do not want to meddle with the SVMlight
* code. It won't affect your application unless you use SVMlight as a library
* and apply different kernels to the same dataset loaded only once. So this does
* not seem critical ;-)
*/
double norm_sq_negativeA,norm_sq_negativeB;
if (a->twonorm_sq<0) {
norm_sq_negativeA = a->twonorm_sq;
}
else {
norm_sq_negativeA=-1*env->CallStaticDoubleMethod(backend,m_evaluate,arg1indicesJ,arg1valuesJ,arg1stringJ,arg1indicesJ,arg1valuesJ,arg1stringJ);
a->twonorm_sq=norm_sq_negativeA;
}
if (b->twonorm_sq<0) {
norm_sq_negativeB = b->twonorm_sq;
}
else {
norm_sq_negativeB=-1*env->CallStaticDoubleMethod(backend,m_evaluate,arg2indicesJ,arg2valuesJ,arg2stringJ,arg2indicesJ,arg2valuesJ,arg2stringJ);
b->twonorm_sq=norm_sq_negativeB;
}
//multiplication is ok, as *both* values will be negative.
result = result/sqrt(norm_sq_negativeA*norm_sq_negativeB);
}
//clean up
env->DeleteLocalRef(arg1indicesJ);
env->DeleteLocalRef(arg2indicesJ);
env->DeleteLocalRef(arg1valuesJ);
env->DeleteLocalRef(arg2valuesJ);
env->DeleteLocalRef(arg1stringJ);
env->DeleteLocalRef(arg2stringJ);
return 0.0;
}
void printErrorAndExit(char* message) {
fflush(stdout);
fflush(stderr);
printf("An error occured in custom kernel module: ");
printf("%s\n", message);
printf("exiting...\n");
exit(1);
}
void printFileErrorAndExit(char* file, char* message) {
fflush(stdout);
fflush(stderr);
printf("Error reading from parameter file: %s\n", file);
printf("%s\n", message);
printf("exiting...\n");
exit(1);
}
void initialize(char* param) {
fflush(stdout);
printf("Using custom kernel module: JNI kernel version "__VERSION".\n");
FILE * pFile;
char line[__MAX_LINE ];
char classname[__MAX_LINE ];
char option[__MAX_LINE ];
//first pass: count... (needed for determining number of options)
pFile = fopen(param, "r");
if (pFile == NULL)
printFileErrorAndExit(param, "Can not open file.");
int optioncount = 0;
int classcount = 0;
while (fgets(line, __MAX_LINE, pFile)) {
if (sscanf(line, __CLASS_PARAM" %[^\n]", &classname))
classcount++;
if (sscanf(line, __OPTION_PARAM" %[^\n]", &option) > 0)
optioncount++;
}
fclose(pFile);
if (classcount != 1)
printFileErrorAndExit(param, "Invalid number of classes.");
//second pass: read content
char** optionstrings = (char**) malloc(optioncount * sizeof(char *));
int optionindex = 0;
pFile = fopen(param, "r");
if (pFile == NULL)
printFileErrorAndExit(param, "Can not open file.");
while (fgets(line, __MAX_LINE, pFile)) {
sscanf(line, __CLASS_PARAM" %[^\n]", &classname);
if (sscanf(line, __OPTION_PARAM" %[^\n]", &option) > 0) {
optionstrings[optionindex] = (char*) malloc(
__MAX_LINE * sizeof(char));
strcpy(optionstrings[optionindex], option);
optionindex++;
} else if (strncmp(line, __NORMALIZE_PARAM, strlen(__NORMALIZE_PARAM))
== 0)
normalize = true;
}
fclose(pFile);
//prepare Java Virtual Machine, locate classes and methods
//class specification needs to follow corresponding KernelManager Java class...
if (verbosity > 0)
printf(
"Preparing Java backend... (increase verbosity to see more details)\n");
JavaVMOption * options = (JavaVMOption *) malloc(
sizeof(JavaVMOption) * optioncount);
for (int i = 0; i < optioncount; i++) {
if (verbosity > 1)
printf("JVM option: %s\n", optionstrings[i]);
options[i].optionString = optionstrings[i];
}
/*
JavaVMOption options[4];
options[0].optionString = "-Xmx512M";
options[1].optionString = "-Xms128M";
options[2].optionString = "-Djava.class.path=" USER_CLASSPATH;
options[3].optionString = "-Djava.library.path=.";
*/
JavaVMInitArgs vm_args;
vm_args.version = JNI_VERSION_1_2;
vm_args.options = options;
vm_args.nOptions = optioncount;
vm_args.ignoreUnrecognized = JNI_TRUE;
jint status;
status = JNI_CreateJavaVM(&jvm, (void**) &env, &vm_args);
if (status < 0) {
char message[__MAX_LINE ];
sprintf(message, "Can't create Java VM (err %d)\n", status);
printErrorAndExit(message);
} else if (verbosity > 1)
printf("Java VM ok.\n");
backend = env->FindClass(__MANAGERCLASS);
if (backend == NULL)
printErrorAndExit("Can't locate KernelManager class.");
else if (verbosity > 1)
printf("KernelManager class ok.\n");
m_initialize = env->GetStaticMethodID(backend, "initialize",
"(Ljava/lang/String;Ljava/lang/String;)V");
if (m_initialize == NULL)
printErrorAndExit("Can't locate initialization method.");
else if (verbosity > 1)
printf("Init method ok.\n");
m_evaluate = env->GetStaticMethodID(backend, "evaluate",
"([J[FLjava/lang/String;[J[FLjava/lang/String;)D");
if (m_evaluate == NULL)
printErrorAndExit("Can't locate evaluation method.");
else if (verbosity > 1)
printf("Evaluation method ok.\n");
jstring classnamearg = env->NewStringUTF(classname);
jstring paramarg = env->NewStringUTF(param);
if (verbosity > 0)
printf("Backend class: %s\n", classname);
//calls "public static void initialize(String kernelClassString, String paramFileString) ..."
fflush(stdout);
env->CallStaticBooleanMethod(backend, m_initialize, classnamearg, paramarg);
fflush(stdout);
printf("OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO");
if (env->ExceptionCheck()) {
printf("\n");
env->ExceptionDescribe();
printErrorAndExit("Java exception during initialization (see stderr).");
} else if (verbosity > 0)
printf("Java backend ready.\n");
if (normalize)
printf("Kernel normalization is on.\n");
initialized = true;
fflush(stdout);
}
[/code]