2013-10-01 21 views
7

Bir kabuk komut dosyası ve tutulma kullanarak derlediğim basit bir java sınıfım ("MainX") var. Env-> FindClass ("MainX") işlevini çağırdığımda, komut dosyasından oluşturulan MainX.class dosyası null değerini döndürürken, eclipse'den oluşturulan MainX.class dosyası, sınıfı döndürür ve daha sonra runMainX işlevini çalıştırır.JNI- FindClass işlevi null değerini döndürür

Oluşturulan MainX.class dosyası, JNI C++ yürütülebilir dosyasıyla aynı klasörde bulunur. Bu durumda neden

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 

.... 
.... 
} 

birisi beni açıklayabilir misiniz?

Yardımlarınız için minnettarım.

Herhangi bir fikir ??? FindClass için JNI Documentation itibaren peşin

cevap

15

teşekkürler:

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

Yani sınıf paketinde your.package.name yılında, ben değiştirmek gerekecek sanırım edilir varsayarak

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

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

Umut Bu yardımcı olur!

+0

Teşekkürler mbrenon. Ancak, hiçbir paketim yok. Gördüğüm src dizininde – STiGMa

+0

var. Hiçbir fikrim yok, ben paketler için zorunlu olduğunu bildiğim kadarıyla Android bağlamında JNI kullanıyorum ... – mbrenon

13

Platformunuzda bu sorun hakkında emin değilim, ancak Android platformunda da benzer bir sorun yaşadım.

FindClass yöntemi yalnızca Java iş parçacığından çağrılmalıdır. FindClass'ın uygulaması, mevcut çağrı yığınını geçerek bir ClassLoader arıyor. FindClass'ı yerel bir iş parçacığından aramaya çalıştığınız için, aramak için ClassLoader yok.

sınıf adı doğru görünüyorsa, bir sınıf yükleyici sorunu çalışıyor olabilir: bu JNI FAQ bir göz atın. FindClass, kodunuzla ilişkili yükleyicide sınıf aramasını başlatmak istiyor.

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

üstteki yöntem Foo.myfunc şudur: gibi bir şey olacaktır çağrı yığını, inceler. FindClass Foo sınıfı ile ilişkili ClassLoader nesnesini bulur ve bunu kullanır.

+0

Bunun için tam bir kod çözümü için, bkz http://stackoverflow.com/a/16302771/1046167 ve yorumları. –

0

Ben CentOS 6 x86_64 var ve bu satırları değiştirilene kadar işe yaramadı:

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

da ben dışa gerek 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/ 

Ben yardımcı umut!

İlgili konular