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.
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 ?
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".
Note that one could be very very dirty and do the following - working for OpenJDK, Zulu and Oracle 11.0.1 - but it is not the target goal of this question.
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);
}
}
In the source code, implAddExports
is marked as @apiNote This method is for JDK tests only
. :(
In JDK 11, the Java EE and CORBA modules were removed. These modules were deprecated for removal in JDK 9. The removed modules are: java.xml.ws: Java API for XML Web Services (JAX-WS), Web Services Metadata for the Java Platform, and SOAP with Attachments for Java (SAAJ)
Java 11 is backwards compatible with Java 8. So you can swiftly change from Java 8 to 11.
In JDK 11, this is no longer an option. In this release, the JRE or Server JRE is no longer offered. Only the JDK is offered. Users can use jlink to create smaller custom runtimes.
This answer comes from the various comments of Alan Bateman to the question.
No, there are no standard API to access the two wanted methods.
Since JDK 6, DirectxxxBuffers are not paged aligned anymore. Thus, accessing VM.isDirectMemoryPageAligned
is not needed to reproduce what DirectBuffers do.
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
.
Comment references: 1 2 3
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With