Skip to content

Commit 1247596

Browse files
authored
feat(jdk14): Add demo for JEP 352 - Non-Volatile Mapped Byte Buffers (#349)
* Add demo for JEP 352 - Non-Volatile Mapped Byte Buffers * Fix BufferUnderflowException in JEP 352 demo * Convert long println to comment as per review feedback
1 parent 8d8668a commit 1247596

3 files changed

Lines changed: 237 additions & 1 deletion

File tree

src/main/java/org/javademos/init/Java14DemoLoader.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44

55
import org.javademos.commons.IDemo;
66
import org.javademos.commons.IDemoLoader;
7-
87
import org.javademos.java14.jep305.InstanceofPatternMatchingPreview;
98
import org.javademos.java14.jep343.PackagingToolIncubatorDemo;
109
import org.javademos.java14.jep349.JFREventStreamingDemo;
10+
import org.javademos.java14.jep352.NonVolatileMappedByteBuffersDemo;
1111
import org.javademos.java14.jep358.NullPointerDemo;
1212
import org.javademos.java14.jep359.RecordsPreviewDemo;
1313
import org.javademos.java14.jep361.SwitchExpressionsDemo;
@@ -30,6 +30,7 @@ public void loadDemos(Map<Integer, IDemo> demos) {
3030
demos.put(305, new InstanceofPatternMatchingPreview());
3131
demos.put(343, new PackagingToolIncubatorDemo());
3232
demos.put(349, new JFREventStreamingDemo());
33+
demos.put(352, new NonVolatileMappedByteBuffersDemo());
3334
demos.put(358, new NullPointerDemo());
3435
demos.put(359, new RecordsPreviewDemo());
3536
demos.put(361, new SwitchExpressionsDemo());
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
package org.javademos.java14.jep352;
2+
3+
import java.io.IOException;
4+
import java.nio.MappedByteBuffer;
5+
import java.nio.channels.FileChannel;
6+
import java.nio.file.Files;
7+
import java.nio.file.Path;
8+
import java.nio.file.StandardOpenOption;
9+
10+
import org.javademos.commons.IDemo;
11+
12+
/// Demo for JDK 14 feature JEP 352 - Non-Volatile Mapped Byte Buffers.
13+
///
14+
/// This JEP extends the MappedByteBuffer API to provide access to non-volatile memory (NVM).
15+
/// It adds new methods to FileChannel that allow Java programs to create MappedByteBuffer instances
16+
/// over non-volatile memory, and provides methods to control when changes are forced to storage.
17+
///
18+
/// Key API additions:
19+
/// - FileChannel.map() now supports MapMode.READ_WRITE_SYNC mode for non-volatile memory
20+
/// - MappedByteBuffer.force() to ensure data is written to storage
21+
///
22+
/// JEP history:
23+
/// - JDK 14: [JEP 352 - Non-Volatile Mapped Byte Buffers](https://openjdk.org/jeps/352)
24+
///
25+
/// Further reading:
26+
/// - [JEP 352: Non-Volatile Mapped Byte Buffers](https://openjdk.org/jeps/352)
27+
/// - [Non-Volatile Memory Access](https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/nio/channels/FileChannel.html#map(java.nio.channels.FileChannel.MapMode,long,long))
28+
///
29+
/// @author Abhineshhh
30+
public class NonVolatileMappedByteBuffersDemo implements IDemo {
31+
32+
@Override
33+
public void demo() {
34+
info(352);
35+
36+
System.out.println("=== Basic Mapped Byte Buffer ===");
37+
demonstrateBasicMapping();
38+
39+
System.out.println("\n=== Force and Load Operations ===");
40+
demonstrateForceAndLoad();
41+
42+
System.out.println("\n=== Read-Write-Sync Mode ===");
43+
demonstrateReadWriteSyncMode();
44+
}
45+
46+
/**
47+
* Demonstrates basic file mapping with MappedByteBuffer.
48+
* This creates a memory-mapped file that can be accessed like an array.
49+
*/
50+
private void demonstrateBasicMapping() {
51+
System.out.println("Creating and writing to a memory-mapped file...");
52+
53+
Path tempFile = null;
54+
try {
55+
// Create a temporary file in the tmp directory
56+
tempFile = Path.of("tmp", "mapped-buffer-demo.dat");
57+
Files.createDirectories(tempFile.getParent());
58+
59+
// Open file channel and create mapped buffer
60+
try (FileChannel channel = FileChannel.open(tempFile,
61+
StandardOpenOption.CREATE,
62+
StandardOpenOption.READ,
63+
StandardOpenOption.WRITE)) {
64+
65+
// Map 1KB of the file into memory
66+
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 1024);
67+
68+
// Write some data
69+
String message = "Hello, Non-Volatile Memory!";
70+
byte[] messageBytes = message.getBytes();
71+
buffer.putInt(messageBytes.length); // Write length first
72+
buffer.put(messageBytes);
73+
buffer.putInt(42);
74+
buffer.putDouble(3.14159);
75+
76+
System.out.println(" Data written to mapped buffer");
77+
System.out.println(" Buffer position: " + buffer.position());
78+
System.out.println(" Buffer capacity: " + buffer.capacity());
79+
80+
// Read back the data - reset position to beginning
81+
buffer.position(0);
82+
int stringLength = buffer.getInt();
83+
byte[] bytes = new byte[stringLength];
84+
buffer.get(bytes);
85+
int value = buffer.getInt();
86+
double pi = buffer.getDouble();
87+
88+
System.out.println(" Read string: " + new String(bytes));
89+
System.out.println(" Read int: " + value);
90+
System.out.println(" Read double: " + pi);
91+
}
92+
93+
} catch (IOException e) {
94+
System.err.println(" Error: " + e.getMessage());
95+
} finally {
96+
// Clean up
97+
try {
98+
if (tempFile != null && Files.exists(tempFile)) {
99+
Files.delete(tempFile);
100+
System.out.println(" Cleaned up temporary file");
101+
}
102+
} catch (IOException e) {
103+
System.err.println(" Cleanup error: " + e.getMessage());
104+
}
105+
}
106+
}
107+
108+
/**
109+
* Demonstrates the force() method which ensures changes are written to storage.
110+
* This is crucial for non-volatile memory to guarantee data persistence.
111+
*/
112+
private void demonstrateForceAndLoad() {
113+
System.out.println("Demonstrating force() to persist changes...");
114+
115+
Path tempFile = null;
116+
try {
117+
tempFile = Path.of("tmp", "force-demo.dat");
118+
Files.createDirectories(tempFile.getParent());
119+
120+
try (FileChannel channel = FileChannel.open(tempFile,
121+
StandardOpenOption.CREATE,
122+
StandardOpenOption.READ,
123+
StandardOpenOption.WRITE)) {
124+
125+
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 512);
126+
127+
// Write critical data
128+
buffer.put("Critical data that must be persisted".getBytes());
129+
130+
System.out.println(" Data written to buffer (in memory)");
131+
132+
// Force changes to be written to storage
133+
// This is important for ensuring data durability
134+
buffer.force();
135+
136+
System.out.println(" force() called - changes are now in storage");
137+
System.out.println(" This ensures data persistence even if the system crashes");
138+
139+
// The load() method loads the entire mapped region into physical memory
140+
// This can improve performance for subsequent accesses
141+
buffer.load();
142+
System.out.println(" load() called - entire region loaded into physical memory");
143+
144+
// Check if the buffer is currently loaded
145+
System.out.println(" isLoaded(): " + buffer.isLoaded());
146+
}
147+
148+
} catch (IOException e) {
149+
System.err.println(" Error: " + e.getMessage());
150+
} finally {
151+
try {
152+
if (tempFile != null && Files.exists(tempFile)) {
153+
Files.delete(tempFile);
154+
}
155+
} catch (IOException e) {
156+
// Ignore cleanup errors
157+
}
158+
}
159+
}
160+
161+
/**
162+
* Demonstrates the concepts behind READ_WRITE_SYNC mode for non-volatile memory.
163+
* Note: The actual MapMode.READ_WRITE_SYNC is primarily useful with NVM hardware.
164+
*
165+
* MapMode.READ_WRITE_SYNC mode (introduced in JEP 352):
166+
* - Designed for non-volatile memory (NVM) devices
167+
* - Provides synchronous writes that bypass the page cache
168+
* - Ensures data durability without explicit force() calls
169+
* - Optimized for byte-addressable persistent memory
170+
*
171+
* Key benefits:
172+
* - Reduced latency for persistent writes
173+
* - Guaranteed data durability after each write
174+
* - Better performance on NVM hardware like Intel Optane
175+
*
176+
* Traditional READ_WRITE mode:
177+
* - Writes go through the page cache
178+
* - Requires force() to ensure persistence
179+
* - Optimized for traditional block storage
180+
*
181+
* When to use:
182+
* - Use READ_WRITE_SYNC for NVM-backed files when durability is critical
183+
* - Use READ_WRITE for traditional storage or when buffering is acceptable
184+
*/
185+
private void demonstrateReadWriteSyncMode() {
186+
System.out.println("Demonstrating concepts for non-volatile memory access...");
187+
188+
// Example of how you would use it (conceptual, as NVM hardware is not common):
189+
Path tempFile = null;
190+
try {
191+
tempFile = Path.of("tmp", "nvm-demo.dat");
192+
Files.createDirectories(tempFile.getParent());
193+
194+
try (FileChannel channel = FileChannel.open(tempFile,
195+
StandardOpenOption.CREATE,
196+
StandardOpenOption.READ,
197+
StandardOpenOption.WRITE)) {
198+
199+
// With traditional READ_WRITE mode
200+
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, 256);
201+
buffer.put("Data with traditional mode".getBytes());
202+
buffer.force(); // Explicit force needed for durability
203+
204+
System.out.println(" Traditional mode: explicit force() required for durability");
205+
206+
// In a real NVM environment, you would use:
207+
// MappedByteBuffer nvmBuffer = channel.map(
208+
// FileChannel.MapMode.READ_WRITE_SYNC, 0, 256);
209+
// nvmBuffer.put("Data with NVM mode".getBytes());
210+
// No force() needed - writes are synchronous and durable
211+
212+
System.out.println(" NVM mode: writes are automatically durable (no force needed)");
213+
}
214+
215+
} catch (IOException e) {
216+
System.err.println(" Error: " + e.getMessage());
217+
} finally {
218+
try {
219+
if (tempFile != null && Files.exists(tempFile)) {
220+
Files.delete(tempFile);
221+
}
222+
} catch (IOException e) {
223+
// Ignore cleanup errors
224+
}
225+
}
226+
}
227+
}

src/main/resources/JDK14Info.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@
2323
"link": false,
2424
"code": true
2525
},
26+
{
27+
"jep": 352,
28+
"jdk": 14,
29+
"name": "JEP 352 - Non-Volatile Mapped Byte Buffers",
30+
"dscr": "Extends MappedByteBuffer API to support non-volatile memory with new FileChannel mapping modes",
31+
"link": false,
32+
"code": true
33+
},
2634
{
2735
"jep": 358,
2836
"jdk": 14,

0 commit comments

Comments
 (0)