JVM动态函数调用

时间:2016-11-14 15:14:16

标签: java c dynamic jvm java-native-interface

我目前正在寻找具有特定功能的OpenJDK JVM的JVM。我想知道JVM如何调用本机函数。我知道它会动态加载它们并将它们保存为void*,但我似乎无法找到实际的调用部分。

例如:

jint Java_Test_add(jobject*, jint);

可以是原生c函数,但也可以:

jvoid Java_Test_main(jobject*);

所以现在我想知道JVM在运行时只将方法签名作为字符串时如何调用这些函数。据我所知,C不支持这种动态调用。我希望有人能告诉我这是如何工作的,或者如何解决这个问题。

提前致谢!

3 个答案:

答案 0 :(得分:1)

  

C不支持此类动态调用

实际上确实如此。 Dynamic libraries被称为 dynamic ,因为它们可以在运行时加载,并且它们的代码可以通过符号名称链接。

DLL(或Unix术语中的共享库)通常包含用于将符号名称映射到函数地址的符号表。 OS提供API以通过名称解析地址,例如, POSIX中的dlsym或Windows上的GetProcAddress

JVM基本上使用此API在第一次调用本机方法时查找函数地址。然后它会记住解析的地址,以便以后的调用直接通过这个地址完成。

将本机方法绑定到函数地址的另一种方法是调用RegisterNatives JNI函数。调用者提供指向本机函数的直接指针,不一定根据标准JNI命名约定命名。

这就是本机方法链接的工作方式。 调用本机方法的过程描述为here

答案 1 :(得分:0)

您可以通过以下两种基本方式之一解决此问题:

  1. 编写一些了解调用约定的平台和机器特定代码,并将其全部正确设置。 (有关在引擎盖下广泛使用的示例,请参阅libffi)
  2. 写下许多带有vargs的C函数并根据类型调度它们。

答案 2 :(得分:0)

每种语言都有自己的一组过程调用约定(如何执行对子例程的调用,应该放在堆栈或寄存器中的内容,从子例程返回必须执行的操作)以及案例中发生的情况像这样,从Java调用一个用C语言编写的本机方法,jvm需要模仿C调用约定,在其正常上下文之外执行你编写的方法Java_Test_add

方法签名将用于获取对内存中C函数位置的引用(从编译项目时链接的静态库加载)和invoke_native指令实现(每个jvm实现不同)将处理执行调用并处理返回(这可以手动完成,但正如有人已经说过的,有像libffi这样的库实现各种调用约定)。

因此,您不必从 C语言功能的角度来看这个,因为是的,该语言不提供一些简单的语法糖设施来执行这种在运行时调用“动态”调用,但仍然可以实现,最终在混合中添加一些程序集。