Java JNI- FindClass 函数返回 null
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19113719/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JNI- FindClass function returns null
提问by STiGMa
I have a simple java class ("MainX") that I compile using a shell script and eclipse. When I invoke the env->FindClass("MainX") function the MainX.class file generated from the script returns null whereas the MainX.class file generated from eclipse returns the class and executes thereafter the runMainX function.
我有一个简单的 java 类(“MainX”),我使用 shell 脚本和 eclipse 编译它。当我调用 env->FindClass("MainX") 函数时,从脚本生成的 MainX.class 文件返回 null,而从 eclipse 生成的 MainX.class 文件返回类,然后执行 runMainX 函数。
The generated MainX.class file is located in the same folder with the JNI C++ executable.
生成的 MainX.class 文件与 JNI C++ 可执行文件位于同一文件夹中。
MainX.java
主X.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
JNI绑定文件
#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
....
....
}
Could someone explain me why this occurs?
有人能解释一下为什么会发生这种情况吗?
I appreciate any help.
我很感激任何帮助。
Any idea??? Thanks in advance
任何的想法???提前致谢
采纳答案by mbrenon
From the JNI Documentationfor FindClass
:
从JNI文档为FindClass
:
name: a fully-qualified class name (that is, a package name, delimited by "/", followed by the class name).
So assuming the class is in the package your.package.name
, I guess you'll have to replace
所以假设类在包中your.package.name
,我想你将不得不替换
mainClass = env->FindClass("MainX");
with
和
mainClass = env->FindClass("your/package/name/MainX");
Hope this helps!
希望这可以帮助!
回答by Ivan Mushketyk
I am not sure about this problem on your platform, but I had a similar problem on Android platform.
我不确定您的平台上是否存在此问题,但我在 Android 平台上遇到了类似的问题。
The FindClass method should be called from Java thread only. FindClass's implementation is looking for a ClassLoader by traversing the current call-stack. Since you are trying to call the FindClass from a native thread, there is no ClassLoader to look for. Take a look at this JNI FAQ:
FindClass 方法只能从 Java 线程调用。FindClass 的实现是通过遍历当前调用堆栈来寻找 ClassLoader。由于您尝试从本机线程调用 FindClass,因此没有要查找的 ClassLoader。看看这个JNI 常见问题:
If the class name looks right, you could be running into a class loader issue. FindClass wants to start the class search in the class loader associated with your code. It examines the call stack, which will look something like:
如果类名看起来正确,您可能会遇到类加载器问题。FindClass 想要在与您的代码关联的类加载器中开始类搜索。它检查调用堆栈,它看起来像:
Foo.myfunc(Native Method)
Foo.main(Foo.java:10)
dalvik.system.NativeStart.main(Native Method)
The topmost method is Foo.myfunc. FindClass finds the ClassLoader object associated with the Foo class and uses that.
最顶层的方法是 Foo.myfunc。FindClass 找到与 Foo 类关联的 ClassLoader 对象并使用它。
回答by oml
I have CentOS 6 x86_64 and it didn't work until I modified this lines:
我有 CentOS 6 x86_64,直到我修改了以下几行,它才起作用:
vm_args.version = JNI_VERSION_1_4;
...
options[0].optionString = (char *)"-Djava.class.path=/home/oscar/Projects/Java-C++";
also I need to export LD_LIBRARY_PATH:
我还需要导出 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/
I hope it helps!
我希望它有帮助!