Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JNI Invocation API - NoClassDefFoundError (C/Java)

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

like image 212
HalfBrian Avatar asked Nov 23 '09 14:11

HalfBrian


People also ask

How do I fix Java Lang NoClassDefFoundError error?

You can fix NoClassDefFoundError error by checking following: Check the exception stack trace to know exactly which class throw the error and which is the class not found by java.

How do I get rid of NoClassDefFoundError in Java?

NoClassDefFoundError, which means the Class Loader file responsible for dynamically loading classes can not find the . class file. So to remove this error, you should set your classpath to the location where your Class Loader is present. Hope it helps!!

What causes NoClassDefFoundError?

NoClassDefFoundError is a common error in Java that occurs if a ClassLoader cannot find a particular class in the classpath while trying to load it. The Exception in thread "main" suggests that this error has occurred in the main thread, the thread which is responsible for running the Java application.


1 Answers

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";
...
like image 195
jitter Avatar answered Sep 22 '22 08:09

jitter