jni错误 UnsatisfiedLinkError

很久没写过jni了。这次项目中用到,准备使用vs2015生成dll,供java调用。我用premake5生成了vs2015项目,但生成出来的dll,无法在java中调用,报以下错误:

Exception in thread "main" java.lang.UnsatisfiedLinkError: RecastLib.hello()V
    at RecastLib.hello(Native Method)
    at RecastLib.main(RecastLib.java:22)

使用vs2015中的工具 dumpbin 查看dll中的方法:

          1    0 00001200 ?Java_RecastLib_hello@@YAXPEAUJNIEnv_@@PEAV_jobject@@@
Z = ?Java_RecastLib_hello@@YAXPEAUJNIEnv_@@PEAV_jobject@@@Z (void __cdecl Java_R
ecastLib_hello(struct JNIEnv_ *,class _jobject *))
          2    1 00001220 ?_Java_RecastLib_hello@@YAXPEAUJNIEnv_@@PEAV_jobject@@
@Z = ?_Java_RecastLib_hello@@YAXPEAUJNIEnv_@@PEAV_jobject@@@Z (void __cdecl _Jav
a_RecastLib_hello(struct JNIEnv_ *,class _jobject *))

发现 vs2015 编译的方法名全部被添加上了@后缀。

正确的应该是:

    ordinal hint RVA      name

          1    0 00011091 Java_RecastLib_hello = @ILT+140(Java_RecastLib_hello)

这是因为 vc++中的 Name Mangling:

	JNIEXPORT void JNICALL Java_RecastLib_hello
		(JNIEnv *, jobject);

如果要导出的cpp中使用了c++特性,即使指定为 extern “C” 也受Name Mangling的影响。

这里可以定义一个  java.def 文件也解决。定义如下:

LIBRARY recastDll
EXPORTS
  Java_RecastLib_hello

然后在vs2015的链接器中定义:

这样导出的函数即不会受name mangling 的影响。

除此之外,还可以使用  RegisterNatives 的方式将函数入口注入java vm(两种试并无性能差异)。

如下:

static JNINativeMethod s_methods[] = {
	{ "jniHello", "()V", (void*)Java_RecastLib_hello },
	{ "jniLoad",  "(Ljava/lang/String;)I", (void*)Java_RecastLib_load },
	{ "jniFind",  "(FFFFFF)Ljava/util/List;", (void*)Java_RecastLib_find }
};
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *vm, void *reserved)
{
	JNIEnv* env = NULL;
	if (vm->GetEnv((void**)&env, JNI_VERSION_1_8) != JNI_OK)
	{
		return JNI_ERR;
	}
	jclass cls = env->FindClass("LRecastLib;");
	if (cls == NULL)
	{
		return JNI_ERR;
	}
	int len = sizeof(s_methods) / sizeof(s_methods[0]);
	if (env->RegisterNatives(cls, s_methods, len) < 0)
	{
		return JNI_ERR;
	}
	return JNI_VERSION_1_8;
}
发表评论?

0 条评论。

发表评论


注意 - 你可以用以下 HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>