java - 编写使用类的两个实现之一进行编译的 Java 代码

标签 java ffi binary-compatibility source-compatibility

我正在用 Java 编写一些大量使用 sun.misc.Unsafe 的 FFI 代码。

在 Java 9 中,这个类将变得不可访问,并将变为 jdk.unsupported.Unsafe。我想编写我的代码,使其现在可以工作,但继续在 Java 9 中工作。

最简单的方法是什么?我更喜欢二进制兼容性,但源兼容性也不错。

编辑:每次调用 Unsafe 上的方法时,我 100% 不同意使用反射——甚至是虚拟分派(dispatch)。这些方法中的大多数都编译为一条机器指令。因此,性能真的很重要。可以使用包装器 – 但前提是我可以确定 JIT 每次都会内联它们。

我目前的计划是在运行时加载一个合适的类。

最佳答案

一个选项:您可以为需要访问的 Unsafe 上的方法提供一个小的 shim 帮助程序接口(interface),有两种实现:一种用于 sun.misc.Unsafe ,另一种用于新的 jdk.unsupported.Unsafe。这两个类都可以作为二进制资源存储在您的 JAR 中,并且在类初始化期间(即,在 static block 中)您可以创建一个新的 ClassLoader 并加载 shim 类。这会在类初始化期间给您带来一些反射开销,但在运行时不涉及反射,只有虚拟方法分派(dispatch)——只要您只加载一个实现类,JIT 应该能够内联它。

如果您可以引入库依赖项,cglib 的 FastClass 基本上可以轻松地为您完成这项工作。

与往常一样,对于此类低级性能黑客,您需要一些数据。为此创建一个 JMH 测试工具,并验证反射开销确实 无法忍受,并且 JIT 确实可以内联您的解决方案——这是唯一可以确定的方法。

关于java - 编写使用类的两个实现之一进行编译的 Java 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40062881/

相关文章:

ruby - 如何使用 Go 共享库在 Ruby 中传递字符串数组并获取字符串数组?

io - 如何处理长时间运行的外部函数调用,例如 Rust 中的阻塞 I/O?

c# - 缩小返回类型是一个重大变化吗?

java - 使用类的对象来获取对其内容的引用的术语或习惯用法是什么?

java - 如何在 IntelliJ IDEA 11 中添加 Java EE SDK 库

rust - C 字符串中缺少第一个字符

c++ - _WIN32_WINNT 定义在 header 中更改,这是否会导致二进制不兼容?

java - 我可以将 Node.js 应用程序打包为 Java EAR

java - 如何更改 JTextField 的不可编辑前景

unix - 如何构建二进制文件并在 Unix 的多台机器上使用它?