views:

436

answers:

1

I am trying to get my feet wet with JNI because I have an application in C that needs to access a single Java library function (no C-equivalent library). I've written a very simple test program to load a Java VM from C and call a static function and get the return value.

Unfortunately, I am unable to get the class to properly load. Although it will probably boil down to it, I think my ClassPath is correct: when I use the java command with the same ClassPath in the same directory, the class loads and executes perfectly.

Environment:
Ubuntu 8.04 server
Java JRE&SDK 1.6
gcc

My present working directory is always /home/me/project.

Here is what I get when I run the java command (java -Djava.class.path=/home/me/project/ -verbose my.ClassABC):

[Loaded ...] (many loads)
[Loaded my.ClassABC from file:/home/me/project/]
Hello test
[Loaded java.lang.Shutdown from shared objects file]
[Loaded java.lang.Shutdown$Lock from shared objects file]

Here is what I get when I run my C program (./myClassABC):

[Loaded ...]
[Loaded my.ClassABC from file:/home/me/project/]
Exception in thread "main" java.lang.NoClassDefFoundError: my.ClassABC
Failed to get class

Here is my gcc command line:

gcc -o myClassABC myClassABC.c -I/usr/lib/jvm/java-6-sun-1.6.0.16/include/ -I/usr/lib/jvm/java-6-sun-1.6.0.16/include/linux -L/usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/i386/server/ -ljvm

My C code (myClassABC.c):

int main(int argc,char **argv)
{
    JNIEnv *env;
    JavaVM *jvm;
    jint res;
    jclass cls;
    jmethodID mid;
    jstring jstr;
    jclass stringClass;
    jobjectArray args;

    JavaVMInitArgs vm_args;
    JavaVMOption options[2];
    options[0].optionString =
     "-Djava.class.path=."; // or "-Djava.class.path=/home/me/project/";
    options[1].optionString =
     "-verbose";
    vm_args.version = JNI_VERSION_1_6;
    vm_args.options = options;
    vm_args.nOptions = 2;
    vm_args.ignoreUnrecognized = JNI_FALSE;
    /* Create the Java VM */
    res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);

    if (res < 0) {
     fprintf(stderr, "Can't create Java VM\n");
     exit(1);
    }
    if ((*env)->ExceptionOccurred(env)) {
     (*env)->ExceptionDescribe(env);
    }

    cls = (*env)->FindClass(env,"my.ClassABC");
    if (cls == NULL) {
        if ((*env)->ExceptionOccurred(env)) {
         (*env)->ExceptionDescribe(env);
        }
        printf("Failed to get class\n");
        exit(1);
    }

    [call methods, etc.]
}

And my java code, just for #$%@s and giggles (gets compiled to /home/me/project/my/ClassABC.class):

package my;

class ClassABC {
    public static void main(String[] args) {
     System.out.println(ClassABC.getPassword("test"));
     return;
    }

    static String getPassword(String filename)
    {
     return "Hello "+filename;
    }
}

Thanks,
Brian

+4  A: 

Just replace this

cls = (*env)->FindClass(env,"my.ClassABC");

with

cls = (*env)->FindClass(env,"my/ClassABC");

and you should be fine.

Else try adding

...
JavaVMOption options[3];
...
options[2].optionString = "-verbose:jni";
...
jitter
Oh man, thank you so much! Looking back at the specification and things I now see that I looked over that.
HalfBrian