Summary
Enhance class java.nio.MappedByteBuffer
so that instances can be mapped via a file belonging to a file system mounted from an non-volatile memory (NVM) device, allowing writes to be committed via an efficient cache-line flush.
Problem
NVM offers the opportunity for application programmers to create and update program state across program runs without incurring the significant copying and/or translation costs that output to and input from a persistent medium normally implies. This is particularly significant for transactional programs, where regular persistence of in-doubt state is required to enable crash recovery.
Existing C libraries (such as Intel's libpmem) provide C programs with highly efficient access to NVM at the base level. They also build on this to support simple management of a variety of persistent data types. Currently, use of even just the base library from Java is costly because of the frequent need to make system calls or JNI calls to invoke the primitive operation which ensures memory changes are persistent. The same problem limits use of the higher-level libraries and is exacerbated by the fact that the persistent data types provided in C are allocated in memory not directly accessible from Java. This places Java applications and middleware (for example, a Java transaction manager) at a severe disadvantage compared with C or languages which can link into C libraries at low cost.
This proposal attempts to remedy the first problem by allowing efficient writeback of NVM mapped to a ByteBuffer. Since ByteBuffer-mapped memory is directly accessible to Java this proposal enables the second problem to be addressed by implementing client libraries equivalent to those provided in C to manage storage of different persistent data types.
Solution
A public extension enumeration ExtendedMapMode
will be added to package jdk.nio.mapmode
in a newly created module of the same name. Module jdk.nio.mapmode
will export this package unconditonally. Enumeration ExtendedMapMode
will expose two new MapMode
enumeration values READ_ONLY_SYNC
and READ_WRITE_SYNC
.
Method FileChannelImpl.map
will be modified to recognize these modes and, when specified, return a MappedByteBuffer
that has been mapped to NVM. The file channel for the mapping must belong to a file system which can be mapped to memory using the mmap flags MAP_SYNC
and MAP_SHARED_VALIDATE
.
Methods force()
and force(long,long)
of MappedByteBuffer
will be modified to respect the mapping of the mapped memory to NVM or volatile memory. In the former case writeback operations will proceed using a new internal API that flushes changes using cache line writeback. In the latter case the existing writeback implementation will be retained, employing file descriptor-based force operations.
Statistics for mapped NVM buffers will be published via a new BufferPoolMXBean
. Class ManagementFactory
provides method List<T> getPlatformMXBeans(Class<T>)
which can be used to retrieve a list of BufferPoolMXBean
instances tracking count
, total_capacity
and memory_used
for the existing categories of mapped or direct byte buffers. It will be modified to return an extra, new BufferPoolMXBean
with name "mapped - 'non-volatile memory'"
, which will track the above stats for all MappedByteBuffer
instances currently mapped with mode ExtendedMapMode.READ_ONLY_SYNC
or ExtendedMapMode.READ_WRITE_SYNC
. The existing BufferPoolMXBean
with name mapped
will continue only to track stats for MappedByteBuffer
instances currently mapped with mode MapMode.READ_ONLY
, MapMode.READ_WRITE
or MapMode.PRIVATE
.
The new MapMode
values and new implementation of FileChannelImpl.map
do not imply a change to the API of the map
operation. However, they do introduce new error cases. These are specified in the javadoc of ExtendedMapMode
but a few extra comments are required:
The new implementation of FileChannelImpl.map
may only be implemented on specific platforms: initially this will be x86_64/Linux and AArch64/Linux. If the new MapMode
values are passed to map on unsupported platforms an UnsupportedOperationException will be thrown.
In the case of AArch64, UnsupportedOperationException will be thrown when the current CPU does not implement the hardware instructions needed to support cache line writeback to memory (all current ARMv8.1 CPUs and, potentially, some ARMv8.2 CPUs).
The new implementation of FileChannelImpl.map
may throw IOException, even on a supported platform. This will occur if the underlying OS implementation does not implement support for mapping into memory files from a file system associated with an NVM device. It will also happen if the file associated with the FileChannel does not belong to such a file system.
Specification
The new Map Modes are documented as follows:
/**
* Defines JDK-specific file mapping modes.
*
* @moduleGraph
* @since 14
*/
module jdk.nio.mapmode; {
exports jdk.nio.mapmode;
}
package jdk.nio.mapmode;
/**
* JDK-specific file mapping modes.
*
* @since 14
* @see java.nio.channels.FileChannel#map
*/
public class ExtendedMapMode {
private ExtendedMapMode() { }
/**
* File mapping mode for a read-only mapping of a file backed by
* non-volatile RAM.
*
* <p> The {@linkplain FileChannel#map map} method throws
* {@linkplain UnsupportedOperationException} when this map mode
* is used on an implementation that does not support it.
*
* @implNote On Linux, the {@code MAP_SYNC} and {@code
* MAP_SHARED_VALIDATE} flags are specified to {@code mmap} when
* mapping the file into memory.
*/
public static final MapMode READ_ONLY_SYNC = . . .
/**
* File mapping mode for a read-write mapping of a file backed by
* non-volatile RAM. {@linkplain MappedByteBufefr#force force}
* operations on a buffer created with this mode will be performed
* using cache line writeback rather than proceeding via a file
* device flush.
*
* <p> The {@linkplain FileChannel#map map} method throws
* {@linkplain UnsupportedOperationException} when this map mode
* is used on an implementation that does not support it.
*
* @implNote On Linux, the {@code MAP_SYNC} and {@code
* MAP_SHARED_VALIDATE} flags are specified to {@code mmap} when
* mapping the file into memory.
*/
public static final MapMode READ_WRITE_SYNC = . . .
}
- csr of
-
JDK-8224974 Implement JEP 352
-
- Resolved
-