编写使用类

时间:2016-10-15 18:45:49

标签: java ffi binary-compatibility source-compatibility

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

在Java 9中,此类将无法访问,并将变为jdk.unsupported.Unsafe。我想编写我的代码,以便它现在可以正常工作,但继续在Java 9中工作。

这样做最不实用的方法是什么?我更喜欢二进制兼容性,但源兼容性也没关系。

编辑:每次调用Unsafe上的方法时,我100%不能使用反射 - 甚至是虚拟调度。大多数方法编译为单个机器指令。因此,性能真的很重要。拥有包装器是可以的 - 但只有当我确定JIT每次都会内联它们时才会这样。

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

3 个答案:

答案 0 :(得分:2)

一个选项:您可以为需要访问的Unsafe上的方法设置一个小的垫片辅助接口,有两个实现:一个用于sun.misc.Unsafe,另一个用于新的jdk.unsupported.Unsafe。这两个类都可以作为二进制资源存储在JAR中,并且在类初始化期间(即在static块中),您可以创建一个新的ClassLoader并加载shim类。这会在类初始化期间给你一些反射开销,但是在运行时没有涉及反射,只有一个虚拟方法调度 - 只要你只加载一个实现类,JIT应该能够内联。

如果您可以引入库依赖项,那么cglib的FastClass基本上可以帮您完成这项工作。

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

答案 1 :(得分:0)

一种方法是编写一个包装任一实现的类,并使用辅助方法来获得正确的实现。您可以检查System.getProperties()。getProperty(“java.version”)以了解您是否使用JDK 1.8或1.9,或者您可以像我一样尝试/ catch来获取类。

不幸的是没有接口可以实现,所以你必须像普通的Object一样使用它。你必须包装每个方法。也许有更通用的方法来做到这一点。

实施开始的实例

(\(*)(\w[\w.]*)\s*([<>!=]{1,2}|like|not like|is null|is not null|in\s*\()?\s*(?!and|or)(?:(?:(between )(?:(['"])(.*?)(\5)|(\S+))( and )(?:(['"])(.*?)(\10)|(\S+)))|(?:(['"])(.*?)(\14)|(\S+)))\s*(\)*)\s*(?!'|")\s*(and|or)?\s*

答案 2 :(得分:0)

当然,低技术解决方案只是简单地记录您的库与Java 9不兼容,并发布一个适用于Java 9的独立版本分支(但不适用于以前的版本)。这会将问题推向您的客户,但这对于绝大多数真实用例来说可能已经足够了。