替换JDK 11对sun.msc.VM的访问



在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:(

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

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

从JDK6开始,DirectxxxBuffers不再分页对齐。因此,不需要访问VM.isDirectMemoryPageAligned来再现DirectBuffers的功能


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


注释参考:1 2 3

最新更新