我试图在托管JVM的可执行文件中调用JNI C函数。我用-rdynamic编译,并用nm -D确认符号是在动态符号表中导出的。但是,当我调用它时,JVM会抱怨找不到符号。
我过去和LuaJIT一起完成了这项工作,这是相当微不足道的,如果不能用Java完成,我会感到非常惊讶。
我在JNITest类中创建了一个测试方法
public static native int strLen();
并实施:
#include <jni.h>
#include <java/com_jnitest_JNITest.h>
#include <string>
#include <iostream>
JNIEXPORT jint JNICALL Java_com_jnitest_JNITest_strLen(JNIEnv* env, jclass clazz)
{
return 1111;
}
int main()
{
JNIEnv* env;
JavaVM* jvm;
JavaVMInitArgs args;
JavaVMOption options[1];
args.version = JNI_VERSION_1_8;
args.nOptions = 1;
args.options = options;
args.ignoreUnrecognized = false;
std::string classpath = "-Djava.class.path=";
classpath += "/var/projects/jnitest/src/java";
options[0].optionString = (char*)classpath.c_str();
jint result = JNI_CreateJavaVM(&jvm, (void**)&env, &args);
if (result != JNI_OK) {
std::cerr << "Could not create JVM" << std::endl;
return 1;
}
jclass main_class = env->FindClass("com/jnitest/JNITest");
if (main_class == nullptr) {
std::cerr << "Could not find JNITest class" << std::endl;
return 1;
}
jmethodID main_method = env->GetStaticMethodID(main_class, "main", "()V");
// Call JNITest.main() transferring control to Java
env->CallStaticVoidMethod(main_class, main_method, nullptr);
if(env->ExceptionCheck()) {
env->ExceptionDescribe();
return 1;
}
jvm->DestroyJavaVM();
return 0;
}
答案 0 :(得分:1)
如果加载System.loadLibrary(),JVM仅注册共享库中的所有函数。
由于您在程序中创建了JVM,它不知道这个函数,您可以使用env->RegisterNatives(...)将本机方法与您的java类链接。
此外,不需要JNIEXPORT
,因为您使用函数指针注册它,并且无需从外部访问此方法。