我目前正在寻找具有特定功能的OpenJDK JVM的JVM。我想知道JVM如何调用本机函数。我知道它会动态加载它们并将它们保存为void*
,但我似乎无法找到实际的调用部分。
例如:
jint Java_Test_add(jobject*, jint);
可以是原生c函数,但也可以:
jvoid Java_Test_main(jobject*);
所以现在我想知道JVM在运行时只将方法签名作为字符串时如何调用这些函数。据我所知,C不支持这种动态调用。我希望有人能告诉我这是如何工作的,或者如何解决这个问题。
提前致谢!
答案 0 :(得分:1)
C不支持此类动态调用
实际上确实如此。 Dynamic libraries被称为 dynamic ,因为它们可以在运行时加载,并且它们的代码可以通过符号名称链接。
DLL(或Unix术语中的共享库)通常包含用于将符号名称映射到函数地址的符号表。 OS提供API以通过名称解析地址,例如, POSIX中的dlsym
或Windows上的GetProcAddress
。
JVM基本上使用此API在第一次调用本机方法时查找函数地址。然后它会记住解析的地址,以便以后的调用直接通过这个地址完成。
将本机方法绑定到函数地址的另一种方法是调用RegisterNatives
JNI函数。调用者提供指向本机函数的直接指针,不一定根据标准JNI命名约定命名。
这就是本机方法链接的工作方式。 调用本机方法的过程描述为here。
答案 1 :(得分:0)
您可以通过以下两种基本方式之一解决此问题:
答案 2 :(得分:0)
每种语言都有自己的一组过程调用约定(如何执行对子例程的调用,应该放在堆栈或寄存器中的内容,从子例程返回必须执行的操作)以及案例中发生的情况像这样,从Java调用一个用C语言编写的本机方法,jvm需要模仿C调用约定,在其正常上下文之外执行你编写的方法Java_Test_add
。
方法签名将用于获取对内存中C函数位置的引用(从编译项目时链接的静态库加载)和invoke_native指令实现(每个jvm实现不同)将处理执行调用并处理返回(这可以手动完成,但正如有人已经说过的,有像libffi这样的库实现各种调用约定)。
因此,您不必从 C语言功能的角度来看这个,因为是的,该语言不提供一些简单的语法糖设施来执行这种在运行时调用“动态”调用,但仍然可以实现,最终在混合中添加一些程序集。