JNI- FindClass関数はnullを返します
単純なJavaクラス( "MainX")クラス( "MainX")があり、シェルスクリプトと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
....
....
}
なぜこれが起こるのか誰かが私に説明できますか?
どんな助けにも感謝します。
何かアイデア???事前に感謝
JNIドキュメント for FindClass
から:
name:完全修飾クラス名(つまり、「/」で区切られたパッケージ名、 の後にクラス名が続きます)。
したがって、クラスがパッケージyour.package.name
、交換する必要があると思います
mainClass = env->FindClass("MainX");
と
mainClass = env->FindClass("your/package/name/MainX");
お役に立てれば!
お使いのプラットフォームでのこの問題についてはわかりませんが、Androidプラットフォームで同様の問題がありました。
FindClassメソッドは、Javaスレッドからのみ呼び出す必要があります。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オブジェクトを見つけ、それを使用します。
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/
お役に立てば幸いです。