为什么某些 Java 库方法委托给具有几乎相同签名的本机方法?

2022-08-31 15:57:33

在深入研究了JRE库的源代码之后,我注意到一个奇怪的通用代码结构,如下所示:

public int foo(double bar) {
    return foo0(bar);
}

private native int foo0(double bar);

此代码模式的目的是什么,为什么使用它而不是简单地将基础本机方法公开为公共方法?


答案 1

本机版本只是一个实现细节。

此模式将方法的公共接口与实际实现分开。

我看到至少5个理由说明为什么这是有用的:

  • 测试目的(您可以模拟java方法调用)
  • 替代实现:Java库的特定版本可以以纯java形式实现该方法,而无需调用本机实现(在swing代码中很常见)。
  • 向后兼容性:如果在新版本中,该方法接受一些额外的参数,则可以保留原始java方法签名并调整本机实现。
  • 输入/输出验证:大多数情况下,在调用本机版本之前,java代码会对输入参数进行一些检查,并在需要时抛出异常。
  • 隔离:直接使用本机代码的方法数量有限,允许在内部代码结构中进行更多更改。

你可能会发现更多的优势。


答案 2
private native int foo(double bar);

因此,最终这必须调用C++函数来实现。特别是,它最终会调用一个名为以下内容的函数:

Java_MyClass_foo

如果有多个具有不同签名的本机 foo 方法,会发生什么情况?并发症。如果这样做,Java 会将类型信息添加到它查找的方法的名称中。但是,如果您坚持使用非重载方法,则更容易。

public int foo(double bar) {
    return foo0(bar);
}

private native int foo0(double bar);

foo0已经被赋予了一个唯一的名称,永远不应该有理由再添加一个。这使得C++的实现变得简单,它永远不必处理损坏的名称。即使 foo 最终获得了重载,它也会调用而不是,C++ JNI 实现也不必处理重载的额外复杂性。foo0foo1foo0


推荐