kukumayas1 2011-06-30 16:53
浏览 551
已采纳

JNI用C调用java程序,程序class.forname(其他包的类)时发生类找不到异常

我用的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]

  • 写回答

1条回答

  • taolei 2011-07-02 01:53
    关注

    附件异常在哪里?
    你把这个
    options[2].optionString = "-Djava.class.path=" USER_CLASSPATH;

    改成
    options[2].optionString = "-classpath" ;
    options[3].optionString = USER_CLASSPATH;
    试试
    USER_CLASSPATH里确定要包含所有需要的java类。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘