替换对JDK 11的sun.misc.VM的访问权限

Kin*_*yan 8 java java-11

在OpenJDK的8,有可能访问sun.misc.VM和调用isDirectMemoryPageAlignedmaxDirectMemory.
isDirectMemoryPageAligned用于正确调整直接内存的大小,如DirectByteBuffer所做的那样.
maxDirectMemory用于报告内存统计信息以及提供配置值的访问权限-XX:MaxDirectMemorySize.在内部,它将限制直接内存的允许消耗.

从OpenJDK 9开始,类VM已移至jdk.internal.misc,除非--add-export java.base/jdk.internal.misc=xyz在运行应用程序时使用,否则不可用.

有没有"正确"的方法来做到这一点?

我已经尝试使用它ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getMax()作为替代,maxDirectMemory但它总是返回-1 - 意味着该值不可用.也可以java.nio.Bits#MAX_MEMORY通过反思访问,但它仍然是" hackish ".


请注意,一个可能非常非常脏,并执行以下操作 - 为OpenJDK,Zulu和Oracle 11.0.1工作 - 但这不是此问题的目标.

public static void tryExportInternal() {
    final String moduleName = "jdk.internal.misc";
    final Module javaLang = Integer.class.getModule();

    // Method used only for tests by the JDK...
    final Method exporter;
    try {
        exporter = Module.class.getDeclaredMethod("implAddExports", String.class);
        exporter.setAccessible(true);
        exporter.invoke(javaLang, moduleName);
    } catch (NoSuchMethodException | IllegalAccessException e) {
        LOG.log(Level.INFO, "Cannot access internal Module method", e);
    } catch (InvocationTargetException e) {
        LOG.log(Level.INFO, "Cannot call internal Module method", e);
    }
}
Run Code Online (Sandbox Code Playgroud)

在源代码中,implAddExports标记为@apiNote This method is for JDK tests only.:(

Kin*_*yan 1

这个答案来自艾伦·贝特曼对这个问题的各种评论。

不,没有标准 API 来访问这两个所需的方法。

从 JDK 6 开始,DirectxxxBuffer 不再进行分页对齐。因此,VM.isDirectMemoryPageAligned不需要访问即可重现 DirectBuffer 的功能。


关于手动内存分配,作为问题背后的用例,目前唯一执行直接内存分配的 API 是ByteBuffer.allocateDirect或其 JNI 替代方案NewDirectByteBuffer


评论参考:1 2 3