我有一个简单的java类(“MainX”),我使用shell脚本和eclipse编译。当我调用env-> FindClass(“MainX”)函数时,从脚本生成的MainX.class文件返回null,而从eclipse生成的MainX.class文件返回该类,然后执行runMainX函数。
生成的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
....
....
}
有人可以解释一下为什么会这样吗?
我感谢任何帮助。
任何想法???提前致谢
答案 0 :(得分:19)
来自FindClass
的{{3}}:
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");
希望这有帮助!
答案 1 :(得分:15)
我对您的平台上的这个问题不太确定,但我在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找到ClassLoader 与Foo类关联的对象并使用它。
答案 2 :(得分: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/
我希望它有所帮助!