问题描述
在OpenJDK 8中,可以访问sun.misc.VM
并调用isDirectMemoryPageAligned
和maxDirectMemory
.isDirectMemoryPageAligned
用于正确调整要分配的直接内存的大小,如 DirectByteBuffer .maxDirectMemory
用于报告内存统计信息以及访问,并提供为-XX:MaxDirectMemorySize
配置的值.在内部,它将为直接内存的允许使用量设置一个限制.
In OpenJDK 8, it was possible to access sun.misc.VM
and call isDirectMemoryPageAligned
and maxDirectMemory
.isDirectMemoryPageAligned
is used to size correctly the direct memory to allocate, as done by DirectByteBuffer.maxDirectMemory
is used to report memory statistics as well as access giving the value configured for -XX:MaxDirectMemorySize
. Internally, it will set a limit to the allowed consumption of direct memory.
自OpenJDK 9起,类VM已移至 jdk.internal.misc ,除非运行应用程序时使用--add-export java.base/jdk.internal.misc=xyz
,否则该类VM不可用.
Since OpenJDK 9, the class VM has been moved to jdk.internal.misc and is not available unless --add-export java.base/jdk.internal.misc=xyz
is used when running the application.
是否有正确"的方法来做到这一点?
Is there a "right" way to do this ?
我已经尝试使用ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getMax()
代替maxDirectMemory
,但是它总是返回-1-表示该值不可用.也可以通过反射方式访问java.nio.Bits#MAX_MEMORY
,但它仍为" hackish ".
I already tried to use ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().getMax()
as a replacement for maxDirectMemory
but it always returned -1 - meaning that the value was not available. It is also possible to access java.nio.Bits#MAX_MEMORY
by reflection, but it remains "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
.:(
In the source code, implAddExports
is marked as @apiNote This method is for JDK tests only
. :(
推荐答案
此答案来自艾伦·贝特曼(Alan Bateman)提问.
不,没有标准的API可以访问这两种通缉方法.
No, there are no standard API to access the two wanted methods.
自JDK 6起,DirectxxxBuffer不再分页对齐.因此,不需要访问VM.isDirectMemoryPageAligned
即可重现DirectBuffer的功能.
Since JDK 6, DirectxxxBuffers are not paged aligned anymore. Thus, accessing VM.isDirectMemoryPageAligned
is not needed to reproduce what DirectBuffers do.
关于手动内存分配,作为问题背后的用例,当前唯一可直接进行内存分配的API是ByteBuffer.allocateDirect
或其JNI替代品NewDirectByteBuffer
.
About manually memory allocation, being the use-case behind the question, the only API to do direct memory allocation is currently ByteBuffer.allocateDirect
, or its JNI alternative NewDirectByteBuffer
.
这篇关于替换对JDK 11的sun.misc.VM的访问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!