2013-10-01 131 views
7

我有一个简单的java类(“MainX”),我使用shell脚本和eclipse编译。当我调用env-> FindClass(“MainX”)函数时,从该脚本生成的MainX.class文件返回null,而从eclipse生成的MainX.class文件返回该类并在其后执行runMainX函数。JNI-FindClass函数返回null

生成的MainX.class文件位于与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 

.... 
.... 
} 

有人能解释我为什么出现这种情况?

我很感激任何帮助。

任何想法???在此先感谢

回答

15

JNI DocumentationFindClass

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

所以假设类是在包your.package.name,我想你将不得不更换

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

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

Hope这有助于!

+0

谢谢mbrenon。但是,我没有任何包裹。它在我看到的src目录 – STiGMa

+0

中。不知道然后,我习惯于在Android上下文中使用JNI,其中包是强制性的,据我所知... – mbrenon

13

我不确定您的平台上存在这个问题,但我在Android平台上遇到类似问题。

只应从Java线程调用FindClass方法。 FindClass的实现通过遍历当前的调用栈来查找ClassLoader。由于您试图从本地线程调用FindClass,因此没有ClassLoader可供查找。 看看这个JNI FAQ

如果类名看起来正确,你可以运行在一个类加载器 问题。 FindClass想要在与您的代码相关的类 加载器中启动类搜索。它检查调用堆栈,这 看起来像:

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

最上面的方法是Foo.myfunc。 FindClass查找与Foo类关联的ClassLoader对象 并使用它。

+0

有关完整的代码解决方案,请参阅http://stackoverflow.com/a/16302771/1046167及其评论。 –

0

我有CentOS 6的x86_64的,并没有工作,直到我修改此行:

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

我也需要出口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/ 

我希望它能帮助!