【问题标题】:Replace access to sun.misc.VM for JDK 11替换对 JDK 11 的 sun.misc.VM 的访问
【发布时间】:2018-11-29 16:03:42
【问题描述】:

在 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,否则该类 VM 不可用。

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

我已经尝试使用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);
    }
}

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

【问题讨论】:

  • 你测试过@VGR 吗?如果是这样,请向我报告您使用的虚拟机。我会试着找出原因。这里的技巧是使用 --add-exports 的动态等效项打开包,这是使用 java.lang.Module 和反射的私有方法完成的。见this code
  • 问题中包含的 hack 非常可怕,随时可能中断。多个版本的直接缓冲区都没有进行页面对齐,因此不清楚为什么现在需要这样做。更多关于 -XX:MaxDirectMemorySize= 值的信息也需要。
  • 自 JDK 6 以来,缓冲区没有进行页面对齐。没有支持的接口可用于您正在做的事情,最好先解释一下为什么需要它?
  • 为什么不直接调用 ByteBuffer.allocateDirect 呢?
  • 如果您自己分配内存,那么您可以使用 JNI 的 NewDirectByteBuffer 将该区域包装为直接缓冲区,也许这就是您要寻找的。​​span>

标签: java java-11


【解决方案1】:

这个答案来自Alan Bateman对问题的各种cmet。

不,没有标准的 API 可以访问这两种想要的方法。

自 JDK 6 起,DirectxxxBuffers 不再分页对齐。因此,无需访问VM.isDirectMemoryPageAligned 即可重现 DirectBuffers 的功能。


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


评论参考:123

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-19
    • 1970-01-01
    • 2022-10-14
    • 2020-07-23
    • 2019-05-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多