在OpenJDK 8中,可以访问sun.misc.VM
并调用isDirectMemoryPageAligned
和maxDirectMemory
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