2013-10-01 21 views
7

Ho una semplice classe java ("MainX") che compilo usando uno script di shell ed eclipse. Quando invoco la funzione env-> FindClass ("MainX") il file MainX.class generato dallo script restituisce null mentre il file MainX.class generato da eclipse restituisce la classe ed esegue in seguito la funzione runMainX.JNI- Funzione FindClass restituisce null

Il file MainX.class generato si trova nella stessa cartella con l'eseguibile JNI C++.

MainX.java

public class MainX { 
    public static void main(String[] args) { 
     // TODO Auto-generated method stub 
     System.out.println(new MainX().runMainX()); 
    } 

    public String runMainX(){ 
     return ("0.789"); 
    } 
} 

JNIBinding.cpp

#define USER_CLASSPATH "." 
.... 
.... 

JNIEnv* createVM (JavaVM **jvm) 
{ 
    JNIEnv *env;      /* pointer to native method interface */ 
    JavaVMInitArgs vm_args;    /* JDK/JRE 6 VM initialization arguments */ 
    JavaVMOption* options = new JavaVMOption[1]; //holds various JVM optional settings 

    options[0].optionString = const_cast<char*>("-Djava.class.path="USER_CLASSPATH); 
    vm_args.version = JNI_VERSION_1_6;  //version of Java platform 
    vm_args.nOptions = 1; 
    vm_args.options = options; 
    vm_args.ignoreUnrecognized = false; 
    /* load and initialize a Java VM, return a JNI interface * pointer in env */ 
    long status = JNI_CreateJavaVM(jvm, (void**)&env, &vm_args); 

    if (status == JNI_ERR){ 
     cout << "Fail: Unable to load JVM \t Exit" << endl; 
    } 
    else if (status == JNI_OK){ 
    cout << "CreateVM:\t\tJVM loaded successfully!" << endl ; 
    } 

    delete options; 
    return env; 
} 

.... 
.... 

float invokeMainX(JavaVM **jvm, JNIEnv *env){ 

    jclass mainClass ; //Returns a class object from a fully-qualified name, or NULL if the class cannot be found. 
    jmethodID classConstructor; //Returns the method ID for an instance (nonstatic) method of a class 
    jobject classObject; //Constructs a new java object 
    jmethodID methodid; 

    float outcome = 0; 

    mainClass = env->FindClass("MainX"); //Returns a class object from a fully-qualified name, or NULL if the class cannot be found. 
    if (mainClass==0) return 0; 
     classConstructor = env->GetMethodID(mainClass, "<init>", "()V"); //Returns the method ID for an instance (nonstatic) method of a class 
    if (classConstructor==0) return -1; 
     classObject = env->NewObject(mainClass, classConstructor); //Constructs a new java object 
    if (classObject==0) return -2; 
     methodid = env->GetMethodID(mainClass, "runMainX", "()Ljava/lang/String;"); 
    if (methodid==0) return -3; 
      jstring result = (jstring)env->CallObjectMethod(classObject, methodid); //returns the result of the calling method, an object 

.... 
.... 
} 

Qualcuno mi potrebbe spiegare perché questo accade?

Apprezzo qualsiasi aiuto.

Qualche idea ??? Grazie in anticipo

risposta

15

Dal JNI Documentation per FindClass:

 
name: a fully-qualified class name (that is, a package name, delimited by "/", 
     followed by the class name). 

Quindi, supponendo la classe è nel pacchetto your.package.name, immagino che dovrete sostituire

mainClass = env->FindClass("MainX"); 

con

mainClass = env->FindClass("your/package/name/MainX"); 

speranza questo aiuta!

+0

Grazie mille. Tuttavia, non ho alcun pacchetto. È nella directory src – STiGMa

+0

che vedo. Non ho idea quindi, sono abituato a utilizzare JNI nel contesto Android in cui i pacchetti sono obbligatori per quanto ne so ... – mbrenon

13

Non sono sicuro di questo problema sulla piattaforma, ma ho riscontrato un problema simile sulla piattaforma Android.

Il metodo FindClass deve essere chiamato solo dal thread Java. L'implementazione di FindClass sta cercando un ClassLoader attraversando lo stack di chiamate corrente. Poiché stai cercando di chiamare FindClass da un thread nativo, non c'è ClassLoader da cercare. Date un'occhiata a questo JNI FAQ:

Se il nome della classe guarda a destra, si potrebbe essere in esecuzione in un problema class loader . FindClass desidera avviare la ricerca della classe nel caricatore della classe associata al codice. Si esamina lo stack di chiamate, che avrà un aspetto simile:

Foo.myfunc(Native Method) 
Foo.main(Foo.java:10) 
dalvik.system.NativeStart.main(Native Method) 

Il metodo più in alto è Foo.myfunc. FindClass trova l'oggetto ClassLoader associato alla classe Foo e lo utilizza.

+0

Per una soluzione di codice completa a questo, vedere http://stackoverflow.com/a/16302771/1046167 e i suoi commenti. –

0

ho CentOS 6 x86_64 e non ha funzionato fino a quando ho modificato questa linea:

vm_args.version = JNI_VERSION_1_4; 
... 
options[0].optionString = (char *)"-Djava.class.path=/home/oscar/Projects/Java-C++"; 

anche ho bisogno di esportare LD_LIBRARY_PATH:

javac HelloWorldApp.java Bicycle.java 
g++ Prueba2.cpp -o Prueba2 -L/usr/lib64/gcj-4.4.4 -ljvm 
export LD_LIBRARY_PATH=/usr/lib64/gcj-4.4.4/ 

Spero che aiuta!

Problemi correlati