2013-10-01 14 views
7

Tôi có một lớp java đơn giản ("MainX") mà tôi biên dịch bằng cách sử dụng một kịch bản lệnh shell và nhật thực. Khi tôi gọi hàm env-> FindClass ("MainX"), tệp MainX.class được tạo ra từ tập lệnh trả về null trong khi tệp MainX.class được tạo ra từ nhật thực trả về lớp và thực hiện sau đó hàm runMainX.Hàm JNI- FindClass trả về null

Tệp MainX.class được tạo nằm trong cùng thư mục với thực thi 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 

.... 
.... 
} 

Ai đó có thể giải thích cho tôi tại sao điều này xảy ra?

Tôi đánh giá cao sự giúp đỡ nào.

Bất kỳ ý tưởng nào ??? Cảm ơn trước

Trả lời

15

Từ JNI Documentation cho FindClass:

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

Vì vậy, giả sử lớp được trong gói your.package.name, tôi đoán bạn sẽ phải thay thế

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

với

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

Hy vọng điều này có ích!

+0

Cảm ơn mbrenon. Tuy nhiên, tôi không có gói nào. Nó nằm trong thư mục src – STiGMa

+0

Tôi hiểu rồi. Không có ý tưởng sau đó, tôi đang sử dụng để sử dụng JNI trong bối cảnh Android, nơi gói là bắt buộc theo như tôi biết ... – mbrenon

13

Tôi không chắc chắn về vấn đề này trên nền tảng của bạn, nhưng tôi đã gặp phải sự cố tương tự trên nền tảng Android.

Phương thức FindClass chỉ nên được gọi từ chuỗi Java. Triển khai của FindClass đang tìm kiếm một ClassLoader bằng cách duyệt qua ngăn xếp hiện tại. Vì bạn đang cố gắng gọi FindClass từ một chuỗi gốc, không có Trình nạp Lớp để tìm kiếm. Hãy xem JNI FAQ này:

Nếu tên lớp có vẻ đúng, bạn có thể chạy vào một vấn đề bộ nạp lớp . FindClass muốn bắt đầu tìm kiếm lớp học trong lớp học trình tải liên kết với mã của bạn. Nó xem xét các cuộc gọi stack, mà sẽ giống như thế:

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

Phương pháp trên cùng là Foo.myfunc. FindClass tìm đối tượng ClassLoader được liên kết với lớp Foo và sử dụng nó.

+0

Đối với một giải pháp mã hoàn chỉnh này, xem http://stackoverflow.com/a/16302771/1046167 và ý kiến ​​của nó. –

0

Tôi có CentOS 6 x86_64 và nó đã không làm việc cho đến khi tôi sửa đổi dòng này:

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

tôi cũng cần phải xuất khẩu 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/ 

Tôi hy vọng nó sẽ giúp!